API reference
Errors
The error envelope, every error code and when to retry.
Envelope#
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Not enough credits.",
"request_id": "a698a9af-0685-4557-9b29-ca57637748f9",
"details": { "top_up_url": "https://scifig.ai/pricing?utm_source=api" }
}
}Branch on error.code and details.reason, never on message, which may change. Responses never contain internal diagnostics.
Codes#
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
| UNAUTHORIZED | 401 | Missing or invalid credentials. | No; change the request or use a new key |
| ACCOUNT_UNAVAILABLE | 401 | This account cannot use the API. | No; change the request or use a new key |
| SCOPE_DENIED | 403 | The credential does not grant this permission. | No; change the request or use a new key |
| INVALID_REQUEST | 400 | The request is invalid. | No; change the request or use a new key |
| IDEMPOTENCY_KEY_REQUIRED | 400 | An Idempotency-Key header (1-255 visible ASCII characters) is required. | No; change the request or use a new key |
| IDEMPOTENCY_CONFLICT | 409 | This Idempotency-Key was already used with a different request. | No; change the request or use a new key |
| IDEMPOTENCY_IN_PROGRESS | 409 | A request with this Idempotency-Key is still being processed. | Yes, with the same Idempotency-Key |
| NOT_FOUND | 404 | Not found. | No; change the request or use a new key |
| REVISION_CONFLICT | 409 | The chart or flowchart job cannot be edited now: NOT_LATEST_REVISION, EDIT_IN_PROGRESS, or PARENT_JOB_RUNNING while the parent job is still running. | Only PARENT_JOB_RUNNING: after Retry-After, with the same key. Otherwise edit the latest version with a new key |
| PAYLOAD_TOO_LARGE | 413 | The request body is too large. | No; change the request or use a new key |
| INSUFFICIENT_CREDITS | 402 | Not enough credits. | No; change the request or use a new key |
| CONTENT_REJECTED | 422 | The content policy refused the request. Returned as 422 when the request is created, or as error.code of a failed job when it happens while the task runs; refunded either way. | No; change the prompt or the input and use a new key |
| PLAN_REQUIRED | 403 | Your plan does not include this option. | No; change the request or use a new key |
| RATE_LIMITED | 429 | Too many requests, tasks per hour, conversions per day or uploads; details.reason says which. | Yes, with the same Idempotency-Key |
| CONCURRENCY_LIMITED | 429 | Too many tasks are running for this account. | Yes, with the same Idempotency-Key |
| SERVICE_UNAVAILABLE | 503 | The service is temporarily unavailable. Retry with the same Idempotency-Key. | Yes, with the same Idempotency-Key |
| TASK_FAILED | 502 | The task failed and its credits were refunded. Send a new request (with a new Idempotency-Key) to try again. | No; change the request or use a new key |
| INTERNAL_ERROR | 500 | Internal error. | Yes, with the same Idempotency-Key |
INVALID_REQUEST always has details.reason (and details.field or details.issues); bodies larger than the limit (256 KB for JSON, the file limits for uploads) return 413 PAYLOAD_TOO_LARGE. Only INSUFFICIENT_CREDITS carries details.top_up_url. When a create request fails after its job was created (429, 503, 409 IDEMPOTENCY_IN_PROGRESS or 500 INTERNAL_ERROR), details.job_id names that job: retry with the same Idempotency-Key or poll GET /jobs/{job_id}, never a new key.
Codes inside a failed job#
A job that was created and then failed reports status: "failed" and an error object. Besides the codes above (for a refused request), its error.code can be:
| error.code | 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 |
Causes of 429#
- Too many requests: 20 create requests per minute per credential, 40 per account, 120 reads per minute per credential.
Retry-Afteris the time until the window resets; there is nodetails.reason. - Too many tasks started in the last hour: up to 200 per account, shared with the website.
Retry-After: 30. - Too many tasks running:
429 CONCURRENCY_LIMITED, by plan and shared with the website (seeGET /credits).Retry-After: 30. - The daily allowance of 200 free PNG, PDF, TIFF and PPTX conversions is used up:
details.reason = DAILY_CONVERSION_LIMIT,Retry-Afteruntil the day window resets. - Uploads too fast:
details.reason = UPLOAD_RATE_LIMITED(images and masks onPOST /files, flowchart attachments, chart data), the website’s per-minute upload limit. - Too many uploads in a day:
details.reason = UPLOAD_DAILY_LIMIT_REACHED(flowchart attachments and chart data), the website’s daily upload limit. - Text detections: 20 per 15 minutes per account, shared with the website.