Product descriptions
A spreadsheet of SKUs, specs and attributes goes in; a catalogue of distinct, sellable product descriptions comes out — one task per item, queued and delivered by webhook, so a 10,000-row import does not turn into 10,000 hours of copywriting. It is built for the catalogue, not the single hero product page.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The catalogue problem this exists for
A single flagship product deserves a copywriter's full attention, but a 10,000-SKU catalogue of phone cases, fasteners or fabric bolts does not get that treatment from anyone, ever — the economics simply do not work. Left unaddressed, that gap becomes a store full of listings that are either blank, duplicated across variants, or copied verbatim from a manufacturer feed that every competitor is also using. This endpoint targets exactly that middle tier of inventory: too large for hand-written copy, too important to leave empty.
What a request looks like
A call to POST /text/product-description takes the attributes for one item — name, category, specs, whatever structured data you have — and queues a task, returning a task_id right away. The finished description arrives later through a signed webhook, the natural fit for a catalogue-management system that already listens for events, or through a signed link valid for 24 hours for a smaller manual batch.
Why per-item pricing matters for a catalogue
Catalogue work lives or dies on unit economics: a description generator priced like a flat subscription either overcharges a small shop or undercharges an enterprise ingesting a warehouse feed. Pricing this at $0.0135 per item plus $0.003 per request means the cost of describing a catalogue scales exactly with the catalogue's size, and a 200-SKU seasonal drop costs a predictable fraction of a 10,000-SKU full-store import.
How it slots into a catalogue pipeline
Because each item is its own task with its own task_id, this integrates naturally after a product-feed import or a PIM sync: queue a description job for every new or updated SKU, let completed webhooks write straight back into the product record, and leave unchanged SKUs untouched rather than re-generating the whole catalogue on every run.
What to expect on variety and limits
The more distinct attributes an item carries, the more distinct its description will read from its neighbors on the shelf — a listing with only a name and category will read more generic than one with material, dimensions and use case attached, which is simply a reflection of the input rather than a flaw in the endpoint. There is no free tier; access requires prepaid balance, and any task that fails after three retries is never billed, so a large catalogue run never bills for SKUs that did not actually get described.
What you can do with it
New supplier feed onboarding
A marketplace ingests a manufacturer's raw spec feed for 8,000 new SKUs and queues a description task for each before the listings go live.
Seasonal drop copy
A fashion retailer generates distinct descriptions for a 300-item seasonal collection in the same afternoon the buying team finalizes the line sheet.
Multi-variant differentiation
A hardware store fixes a catalogue where every screw-size variant shared identical copy, giving each SKU description its own specific dimensions and use case.
Marketplace expansion
A brand entering a new sales channel regenerates descriptions for its full catalogue to fit that channel's tone and length conventions, one task per SKU.
FAQ
How does the product description generator API work?
Send an item's attributes to POST /text/product-description; the task is queued and the finished description arrives by signed webhook or a signed link valid for 24 hours.
Can it really handle a catalogue of 10,000 SKUs?
Yes — each SKU is its own queued task, so a catalogue of any size is processed as a batch of individual, independently priced requests.
Is there a free tier for bulk catalogue generation?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How much does it cost per product?
$0.003 per request plus $0.0135 per item, so the cost of a catalogue run scales directly with the number of SKUs described.
Will descriptions be duplicated across similar products?
Each request is generated from that item's own attributes, so items with distinct specs, materials or dimensions receive distinct descriptions rather than templated copy.
What happens if a description task fails?
It retries automatically up to three times; a task that ultimately fails returns a clear error and is never charged.
Can this update only new or changed SKUs?
Yes — since each item is an independent task, you can queue descriptions only for new or updated products and leave the rest of the catalogue untouched.
What input data does it need per product?
Whatever structured attributes you have — name, category, specs, materials, dimensions — with richer attributes producing more specific, differentiated copy.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/text/product-description \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"items":["valor-1","valor-2"]}'const res = await fetch("https://api.kit.forhosting.com/text/product-description", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"items": [
"valor-1",
"valor-2"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/text/product-description",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"items": [
"valor-1",
"valor-2"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/text/product-description", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"items":["valor-1","valor-2"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"items":["valor-1","valor-2"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/text/product-description", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"items": [
"valor-1",
"valor-2"
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "text.product_description",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_tokens | 20000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
422 | task_failed | The task failed after 3 retries. You are never charged for it. |