X-RateLimit-Limit header on every response tells you your key’s exact limit.
How the limit works
- It counts requests, nothing else. A call that lists a 10-contact audience and a call that imports a million contacts each cost one request. Payload size, list size, and message volume never count.
- Bursts are fine. Think of a bucket holding 600 tokens; each request spends one, and tokens refill at 10 per second. You can send 600 at once, and after that you keep getting 10 per second rather than being locked out for the rest of the minute. A steady 10 per second never hits the limit.
- It is per key. Each key has its own budget. If two systems share one key they share one budget; give each integration its own key.
- You can see it. Admin > API > your key > usage shows total requests, success rate, and how many requests were rate limited.
What happens at the limit
When you hit the limit, subsequent requests return429 Too Many Requests with a Retry-After header: the seconds until your next request will be allowed. At the default limit that is about one second. If both Retry-After and X-RateLimit-Reset are present, Retry-After wins (it is relative, so a skewed clock cannot mislead you). The official SDKs already do this.
Handling 429s correctly
Monitor X-RateLimit-Remaining on every response
Monitor X-RateLimit-Remaining on every response
Don’t wait for a 429 - track the remaining counter and start backing off when it gets low (e.g. below 10).
Implement exponential backoff for 429 responses
Implement exponential backoff for 429 responses
Standard pattern: on 429, sleep for the
Retry-After seconds (or for an initial delay of 1s, doubling each retry up to a cap). Retry the same request. Never retry tighter than once per second.Use caching to reduce API calls
Use caching to reduce API calls
Cache hierarchy data for 5–10 minutes (it changes infrequently). Cache historical stats for completed date ranges indefinitely.
Batch operations when possible
Batch operations when possible
Prefer one large date-range query over many small ones. Use hierarchy filters (
organization_id, brand_id, campaign_id) to reduce data volume per request.Poll project stats no faster than they change
Poll project stats no faster than they change
GET /v1/projects/{id}/stats is cached for 15 seconds while a project is sending and 5 minutes once it is idle, so polling faster than that returns the same numbers for another request. For many projects at once, GET /v1/projects/stats with a date range returns them in one call.