API reference
Jobs and bounded waiting
Read job status, credits and outputs, and wait for a job without polling.
Read a job#
GET /jobs/{id} (scope jobs:read) returns the same job object as the create request. Jobs of other accounts and unknown IDs both return 404 NOT_FOUND. GET /jobs?limit=10&cursor=… lists your jobs, newest first (1–20 per page, follow next_cursor).
{
"id": "5f4a9a5e-fc45-4eae-9f9c-56b5f686cba5",
"kind": "chart",
"status": "succeeded",
"created_at": "2026-10-14T11:20:05.000Z",
"credits": { "reserved": 50, "charged": 50, "refunded": 0 },
"outputs": [
{
"file_id": "0b7c…",
"format": "png",
"width": 2126,
"height": 1417,
"download_url": "https://scifig.ai/api/v1/files/0b7c…?exp=…&sig=…",
"expires_at": "2026-10-14T12:21:40.000Z",
"editor_url": "https://scifig.ai/app/datachart?conversation=…"
}
],
"error": null
}kind is image_generation, image_edit, image_upscale, image_conversion, chart or flowchart. Responses never include your prompt, your inputs or internal identifiers.
| Output field | Present | Meaning |
|---|---|---|
| file_id | always | Pass it to another endpoint or to GET /files/{file_id} |
| format | always | File extension of the output, such as png, svg or pdf |
| width, height | PNG outputs | Pixel size |
| download_url, expires_at | always | Signed link, valid for one hour |
| editor_url | chart and flowchart jobs | Opens the result in its website workspace; illustrations and conversions have none |
Status lifecycle#
| status | Meaning |
|---|---|
| queued | Accepted and waiting for capacity |
| processing | Running |
| succeeded | Done; outputs are ready and credits charged |
| failed | Did not produce a result; error.code says why and the reservation is refunded |
| canceled | Stopped before finishing; refunded |
| `error.code` of a failed job | Meaning | What to do |
|---|---|---|
| TASK_TIMED_OUT | The task timed out and was refunded. An illustration generation or edit may carry late_delivery_until: until then the result can still arrive for free. | Keep reading the job until late_delivery_until; otherwise send a new request with a new key |
| CONTENT_REJECTED | The content policy refused the result while the task ran; refunded. The same code is returned as 422 when the request itself is refused at creation. | Change the prompt or the input and use a new key |
| ADMISSION_INCOMPLETE | The job was never started because a retryable error stopped it. No credits were used. | Send the same request with the same Idempotency-Key |
| TASK_NOT_FOUND | The job was admitted but its task can no longer be found. | Send a new request with a new key |
| TASK_FAILED | The task failed and was refunded. Every engine failure without a public code of its own becomes TASK_FAILED; the engine code is in details.reason. | Send a new request with a new key |
| INTERNAL_ERROR | The task failed without reporting a reason; refunded. | Send a new request with a new key |
succeeded, failed and canceled are final, with one exception: an illustration generation or edit that failed with TASK_TIMED_OUT carries late_delivery_until. Until then the result may still arrive, for free, and the job turns succeeded; keep reading it instead of creating a new one.
If any job in the list cannot be read, GET /jobs returns 503 SERVICE_UNAVAILABLE with Retry-After: 3; retry the list request. It does not replace that job with a failed result.
Bounded waiting#
Prefer: wait=N(1–30) on a create request holds the response until the job is final or N seconds pass. Final jobs return200; jobs still running return202withLocation: /api/v1/jobs/{id}andRetry-After.- Waiting does not change the job: a
202is not an error, and the job keeps running after the response. - Poll
GET /jobs/{id}no faster thanRetry-After(3 seconds). Illustrations usually finish in 20–90 seconds, charts and flowcharts in 30–120 seconds. - A failed job may also hold a refused request: a create request refused with an error such as
402 INSUFFICIENT_CREDITSor422 CONTENT_REJECTEDstays inGET /jobsas afailedjob with that code and no credits. - Server integrations should store the job ID before waiting, so that a dropped connection never leads to a second job.
cURL#
curl https://scifig.ai/api/v1/jobs/<job_id> \
-H "Authorization: Bearer $SCIFIG_API_KEY"JavaScript#
const response = await fetch('https://scifig.ai/api/v1/jobs/<job_id>', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.SCIFIG_API_KEY}`,
},
});
const result = await response.json();
console.log(response.status, result);Python#
import os
import requests
headers = {
"Authorization": f"Bearer {os.environ['SCIFIG_API_KEY']}",
}
response = requests.get(
"https://scifig.ai/api/v1/jobs/<job_id>",
headers=headers,
timeout=60,
)
print(response.status_code, response.json())