API limits
The limits that apply to every integration, and the headers that let your code respect them automatically.
Rate limits
Requests are limited per API key, per minute. The default is 60 requests/minute; paid plans can raise it, and a specific key can carry its own override. The effective number is always in the response headers:
| Parameter | Type | Description |
|---|---|---|
| X-RateLimit-Limit | header | Your limit for the current window. |
| X-RateLimit-Remaining | header | Requests left in the window. |
| X-RateLimit-Reset | header | Unix time when the window rolls over. |
| Retry-After | header | On a 429 only: seconds to wait before retrying. |
Exceeding the limit returns 429 rate_limited. Back off for Retry-After seconds instead of retrying immediately. Hammering a 429 only keeps the counter full.
if (res.status === 429) {
const seconds = Number(res.headers.get("Retry-After") ?? 1);
await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
// then retry the request
}Upload limits
| Parameter | Type | Description |
|---|---|---|
| Max file size | 10 MB | Larger uploads return 413 payload_too_large. |
| Formats | JPEG, PNG, WebP, AVIF | Sniffed from the bytes; anything else returns 415 unsupported_media_type. |
| image_url | public HTTPS | URL sources must be reachable without authentication and are subject to the same size and format checks. |
Processing guarantees
- Jobs are retried internally up to 3 times before being marked
failed. - A job that has not finished within 20 minutes is abandoned, marked
failed, and its credits are refunded automatically. - Result downloads are signed URLs valid for five minutes each; request a fresh one whenever you need the file again. Results are retained, the links are what expire.
Need higher limits? Reach out from your account settings and tell us about your workload.