Errors & idempotency
Status codes, error envelope, safe retries.
All errors share a single envelope:
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded (5 req/s). Retry after 7s."
}
}Codes
| HTTP | code | Meaning |
|---|---|---|
400 | unknown_tool | Tool slug not found in the registry. |
400 | missing_input | input.url or input.fileId required. |
401 | unauthorized | Missing or malformed bearer token. |
401 | invalid_key | Key not recognized. |
401 | revoked | Key has been revoked. |
401 | expired | Key has expired. |
402 | insufficient_credits | Account balance is below the cost of this job. |
402 | spend_cap_reached | Per-key daily/monthly spend cap reached. |
403 | plan_not_eligible | Owner is not on Pro or Max. |
403 | ip_not_allowed | Source IP not in this key's allowlist. |
403 | insufficient_scope | Key lacks the required scope. |
404 | not_found | Job not found, or not owned by this key. |
409 | cannot_cancel | Job is already running or finished. |
413 | file_too_large | Upload exceeds plan size limit. |
429 | rate_limited | Per-key RPS exceeded. |
429 | concurrency_exceeded | Too many concurrent in-flight jobs. |
500 | enqueue_failed | Job submission failed before reaching the queue. |
Idempotency
Pass idempotencyKey on POST /v1/jobs. If the same key + value combination is replayed within 24 hours we return the original response without enqueueing a new job. Use a UUID per logical request.
POST /v1/jobs
{ "tool": "...", "input": {...}, "idempotencyKey": "0f...uuid" }