Limits and errors
Rate limits
Requests are limited per key and per organization to the number per minute your plan allows. A request counts against both; the stricter answers.
Every /v1 answer carries:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per minute |
X-RateLimit-Remaining | Requests left in the current window |
X-RateLimit-Reset | When the window resets (Unix seconds) |
X-Request-ID | Id of this request; quote it to support |
A request over the limit is refused with 429 and code rate_limited, a Retry-After header (seconds to wait), and it does not count as use. Back off for that long, then retry.
The request rate does not replace the other limits, which hold as they always do: your credit balance, your plan's number of concurrent jobs, and spending limits. Prefer webhooks to polling, and poll a job no more than every few seconds.
Errors
Every error, on every status, has one shape:
{
"error": {
"code": "insufficient_credits",
"message": "Not enough credits for this job",
"details": {}
}
}codeis stable and meant for your code to branch on. Codes do not change within a version.messageis for people; do not parse it.detailsis an optional object with specifics (for a validation error, which setting was wrong).
| Status | Codes |
|---|---|
| 401 | unauthenticated |
| 403 | not_allowed, model_locked |
| 404 | not_found |
| 409 | idempotency_key_reused, job_not_cancellable, org_read_only, insufficient_credits, spending_limit_reached, asset_not_ready, upload_not_open |
| 422 | idempotency_key_required, invalid_job_input, unknown_model, price_unavailable, invalid_upload, unsupported_file_type, asset_too_large, size_mismatch, upload_incomplete |
| 429 | rate_limited |
| 5xx | internal_error and similar; retry with the same Idempotency-Key |
A failed job is not an HTTP error: the request succeeded and the job's status is failed (or blocked), with error_code and error_message on the job. Its credits return.
Always send and log the X-Request-ID of failed calls.
Versioning
The version is in the path: /v1.
Within /v1 the platform only adds: new endpoints, new optional settings, new fields in answers and new webhook event types. So:
- Ignore fields you do not know, and ignore event types you do not handle. Do not fail on them.
- Do not depend on the order of fields or of keys in objects.
Removing or changing the meaning of anything is a new version. When that happens the old version answers with Deprecation and Sunset headers, and stays available for at least six months after it is announced.