429. A rate limit
counts how many requests you send per minute. A concurrency limit counts how
many long operations you keep running at the same time.
Read error.type to tell them apart. A rate limit means slow down. A
concurrency limit means wait for work already in flight to finish.
Rate limits
The sustained rate is 1,000 requests per minute, and the window holds a little headroom above that so a short burst is not punished. Every response carries the current state of the window.429, rate limit exceeded
Concurrency limits
Renders and uploads hold separate concurrency budgets, and the upload budget is never the larger of the two. Only the endpoints that hold a slot report these headers: a PSD upload, a synchronous render, and a background removal.429, concurrency limit exceeded
429 carries Retry-After as well, and five seconds is usually
enough: the slot frees as soon as the request holding it returns.
Queue instead of waiting
A queued render never holds a concurrency slot while it waits. Sendis_async
as true on POST /api/v1/renders and
the call returns a 202 with a job you poll through
GET /api/v1/jobs/{job_id}, or
receive over a webhook. Video mockups are always queued
and behave the same way.
That is the right shape for a large batch: submit the whole set, then follow
the jobs.
Read your own ceilings
Do not hardcode the concurrency numbers. Both budgets move with the plan catalogue, so read them at runtime fromGET /api/v1/packages/plans,
which returns max_concurrent_requests and max_concurrent_uploads for the
plan you are on. Size your worker pool from those two fields and a 429 stops
being something you have to handle.
Errors
Every status code, every
error_code, and the retry loop.