API reference
Tasks
Submit, fetch and list tasks, download results, and avoid duplicate submissions.
Every generation is an asynchronous task: submit it, get its ID at once, then poll for the result or wait for a callback.
Submit a task
POST /v1/tasks
Body fields:
model(required): the model ID. See the model list orGET /v1/models.input(required): generation parameters, which depend on the model's media type. See Models and parameters.route(optional): which routes this request may use, in what order. See Routes and routing.callback_url(optional): an https URL we post the result to when the task ends. See Callbacks.
curl https://janvia.io/v1/tasks \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-123" \
-d '{
"model": "gpt-image-2",
"input": { "prompt": "a red fox in the snow", "resolution": "2K" },
"route": ["fast", "cheap"]
}'Success is HTTP 202 with the task object; the Location header is the task's URL. Errors at submit time (bad parameters, low balance and so on) return a 4xx, create no task and charge nothing.
The task object
{
"id": "task_9f2c...",
"object": "task",
"model": "gpt-image-2",
"media_type": "image",
"status": "completed",
"progress": 100,
"input": { "prompt": "a red fox in the snow", "resolution": "2K" },
"route": "fast",
"route_name": "Fast",
"routing": {
"routes": [
{ "id": "fast", "name": "Fast", "price_usd": 0.06 },
{ "id": "cheap", "name": "Cheap", "price_usd": 0.04 }
],
"source": "request",
"rule": null
},
"output": {
"files": [
{
"type": "image",
"url": "https://...",
"mime_type": "image/png",
"width": 2048,
"height": 2048
}
]
},
"error": null,
"cost_usd": 0.06,
"callback": null,
"created_at": "2026-10-21T08:00:00.000Z",
"finished_at": "2026-10-21T08:00:12.000Z"
}status:queued,in_progress,completedorfailed.progress: 0–100; it moves only when the upstream reports progress.route/route_name: the route serving (or that served) the task.routing.routes: the routes this task may use, in the order they are tried, with their prices.sourcesays where the list came from:request(the request'sroute),rule(an exception rule on the key;ruleis its 0-based index),key(the key's sort settings) ordefault(the recommended order).output.files: the generated files.typeisimage,videooraudio; images havewidthandheight, video and audio may havedurationin seconds.error: on failure, acodeandmessage. See Errors.cost_usd: what the task cost; 0 when it failed (refunded).callback: with acallback_url, how its delivery went; otherwisenull. See Callbacks.- base64 images in
inputare shown shortened.
Fetch a task
curl https://janvia.io/v1/tasks/TASK_ID \ -H "Authorization: Bearer $API_KEY"
Polling every 3–5 seconds is plenty; video can wait longer. You can only fetch your own account's tasks; anything else returns 404 task_not_found.
List tasks
GET /v1/tasks?page=1&limit=20 returns your tasks, newest first, with limit up to 100:
{ "object": "list", "data": [ ... ], "page": 1, "limit": 20, "total": 132 }Download results
output.files[].url is either a CDN URL or this site's /v1/tasks/TASK_ID/content/N. Both download without a key: task IDs are random and can't be guessed, so don't share these URLs publicly. Save files to your own storage once you have them.
Avoid duplicate submissions
Retrying after a network timeout could submit (and pay for) the same task twice. Send an Idempotency-Key header (1–128 letters, digits or _ . : -) to prevent it:
- Within 24 hours, the same key with the same body returns the same task (HTTP 200 with
Idempotency-Replayed: true) and charges nothing more. - The same key with a different body returns 409
idempotency_conflict.