Janvia

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 or GET /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, completed or failed.
  • 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. source says where the list came from: request (the request's route), rule (an exception rule on the key; rule is its 0-based index), key (the key's sort settings) or default (the recommended order).
  • output.files: the generated files. type is image, video or audio; images have width and height, video and audio may have duration in seconds.
  • error: on failure, a code and message. See Errors.
  • cost_usd: what the task cost; 0 when it failed (refunded).
  • callback: with a callback_url, how its delivery went; otherwise null. See Callbacks.
  • base64 images in input are 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.