Rate limits
Per organization, per minute, in two cost classes. The limits exist to stop a runaway loop, not to shape ordinary traffic.
Limits apply per organization, per minute, and are counted in two buckets by request method:
| Bucket | Methods | Limit |
|---|---|---|
| Reads | GET |
600 per minute |
| Writes | POST, PATCH, DELETE |
60 per minute |
Both are far above what an ordinary integration uses. A nightly sync that pages a 5,000-product catalogue at 100 per page makes 50 reads; an import of 2,000 products is one write.
Headers
Every response carries the state of the bucket it was counted in:
X-RateLimit-Limit: 600X-RateLimit-Remaining: 597X-RateLimit-Reset: 1756910040X-RateLimit-Reset is Unix seconds. Windows start on the minute, so callers in the same minute share a window.
When you exceed a limit
{ "error": { "type": "rate_limited", "code": "rate_limit_exceeded", "message": "Rate limit of 60 write requests per minute exceeded for this organization. Retry after 23s." }}The response carries Retry-After in seconds; wait that long and retry. A 429 is not a failure of the operation. Nothing was created, no credits were spent and no Idempotency-Key was consumed, so it is always safe to retry with the same request.
Polling
GET /v1/imports/{id} and GET /v1/exports/{id} carry Retry-After: 5 while a job is running. Polling at that interval keeps even a tight loop well inside the read bucket. A webhook removes the need to poll at all.