Run tasks in parallel
Some jobs don't need to wait for each other, they need to happen at the same time. The Parallel Fan-Out API launches several independent steps together and joins their results into a single response, so a job that would take three sequential calls finishes in the time of the slowest one.
The problem with running things one after another
If you need a document translated into four languages, there's no reason the French translation should wait for the Portuguese one to finish. Running them sequentially wastes time for no benefit, since the steps don't depend on each other and none of them needs to see another's output before it can start. POST /flow/parallel fires every branch at the same moment and waits only as long as the slowest branch takes, instead of the sum of every branch's individual duration.
How the fan-out works
You submit a list of independent task definitions, each with its own type and parameters, and the platform dispatches them concurrently on our global edge. There's no shared state between branches by design, which is what makes true parallel execution safe: one branch's outcome never blocks or corrupts another's, and a slow or unusual input in one branch can't stall the rest of the batch waiting on it.
How the results join back up
Once every branch finishes, the outputs are collected into one structured result, indexed by the branch you named when you submitted it. You get a single task_id at submission time and a single joined payload at completion, delivered by signed webhook or a signed link valid for 24 hours, so your application reads one response instead of correlating several arrivals by hand.
What happens when one branch fails
A failing branch retries up to three times on its own, independent of the others, and only the branches that actually fail incur no charge. The joined result tells you plainly which branches succeeded and which didn't, instead of failing the whole fan-out over one bad input, so three good translations still land even if the fourth needed a closer look.
Where fan-out earns its keep
It's the natural fit for anything with independent variants: translating one source into many languages, generating multiple image sizes, transcribing several files from the same batch. Because it's a standard async task, a parallel fan-out can itself be one step inside a larger chain or scheduled flow, so you might chain a summarisation step followed by a fan-out that translates that one summary into several languages at once.
What you can do with it
Simultaneous multi-language translation
Translate the same source text into five target languages at once instead of five sequential requests, cutting total wait time to that of the slowest language.
Multi-format image export
Generate thumbnail, medium and full-resolution variants of an upload in parallel and receive all three under one task_id.
Batch file transcription
Transcribe several audio files from the same recording session concurrently and get every transcript back in one joined response.
Cross-region content checks
Run the same validation task against content variants for different markets at the same time, then review all results together.
FAQ
How is parallel fan-out different from just sending several requests?
Sending separate requests means tracking separate task_ids and separate webhooks; fan-out groups them under one task_id and one joined result.
Is the Parallel Fan-Out API free to use?
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 many branches can I run at once?
Fan-out is built for a practical set of concurrent branches per request; very large batches of similar items are better handled with the batch processing task instead.
What if two branches take very different amounts of time?
The joined result returns once the slowest branch finishes, so total time is bound by your longest branch, not the sum of all of them.
Do branches share data with each other?
No, branches run independently with no shared state, which keeps one branch's failure or delay from affecting the others.
How do I know which output belongs to which branch?
The joined result is indexed by the identifier you assign each branch when you submit the request, so mapping outputs back is direct.
Can I combine fan-out with chaining?
Yes, a parallel fan-out can be one step inside a chain, so you can run several branches at once and then feed the joined result into a following step.
What happens if one branch keeps failing?
It retries up to three times, then returns a clear per-branch error while the other branches complete normally; failed branches are never charged.
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/flow/parallel \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/flow/parallel", {
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/flow/parallel",
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/flow/parallel", 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/flow/parallel", 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": "flow.parallel",
"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.
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. |