Write a blog post
Give the blog post writer API a title and a short brief — angle, audience, key points to cover — and it returns a complete draft, not an outline you still have to flesh out. It exists for the editorial calendar that has more slots than writers, run as a queued job so a whole week of drafts can be requested before lunch.
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 gap between an outline and a draft
Plenty of content tools will hand back bullet points and call it a first draft; a content manager still has to turn those bullets into readable paragraphs before an editor can touch it. This endpoint skips that intermediate step — the brief goes in, a structured article with an introduction, body sections and a close comes out, so the editor's job starts at revision rather than at drafting from a blank page.
How a request moves through the system
A call to POST /text/blog-post with the title and brief returns a task_id immediately and queues the writing job. The finished article arrives later by signed webhook — the recommended path for a CMS integration — or through a signed link valid for 24 hours, useful when a person wants to review the draft directly before it touches the publishing pipeline.
What a useful brief looks like
The quality of the draft tracks the specificity of the brief the same way it would with a freelance writer: a title alone produces a generic article, while a title plus target audience, tone, key points to hit and anything to avoid produces something closer to what an editor actually wants on the first pass. This is not a limitation unique to the endpoint — it is how briefing has always worked, automated or not.
Where article generation sits in a content operation
Because every request returns a task_id and a webhook, this slots directly into an editorial pipeline: a content calendar tool queues Monday's five scheduled posts on Friday afternoon, catches each webhook as the draft finishes, and routes it into a review queue automatically. Nothing about the design assumes a person is refreshing a browser tab waiting for the article to appear.
Honest expectations on length and cost
Longer requested articles take proportionally longer in the queue and cost proportionally more, since pricing is $0.003 per request plus $0.0135 per article rather than a flat unlimited-length fee. There is no free tier — access needs prepaid balance, and a task that fails after three retries is never charged, so a queue full of draft requests never turns into a surprise line item for work that never landed.
What you can do with it
Weekly editorial calendar fill
A content team queues briefs for every scheduled post on Friday and reviews finished drafts from the webhook feed on Monday morning.
SEO content at volume
A growth team generates first drafts for a long list of target keywords, then has editors focus their time on fact-checking and polish rather than first-pass writing.
Multi-brand content operations
An agency running several client blogs queues briefs per brand voice and routes each finished article to the right client's review queue automatically.
Rapid-response topical posts
A newsroom-adjacent site drafts a first take on a breaking topic the moment an editor submits a brief, cutting the time from assignment to reviewable copy.
FAQ
How does the blog post writer API work?
Send a title and brief to POST /text/blog-post; the task is queued and the finished draft is delivered by signed webhook or a signed link valid for 24 hours.
Is the blog post generator API free?
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 is each article priced?
$0.003 per request plus $0.0135 per article, billed only for articles that are actually generated.
What should a good brief include?
A title, target audience, tone and the key points the article should cover produce a noticeably better first draft than a title alone.
Can I generate a whole week of blog posts in bulk?
Yes — queue one request per post; each gets its own task_id, so a batch of drafts can be requested and delivered in parallel.
What happens if the draft generation fails?
The task retries automatically up to three times, and a task that ultimately fails is never billed.
Do I still need to edit the draft before publishing?
Yes — this returns a genuine first draft meant for editorial review, not a copy-paste-ready final piece, the same way any human-written first draft would be treated.
How long is the finished article available?
The signed link stays valid for 24 hours, after which the draft is deleted and never used for training.
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/blog-post \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/text/blog-post", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"input": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/text/blog-post",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"input": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/text/blog-post", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"input":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"input":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/text/blog-post", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"input": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "text.blog_post",
"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. |