# Rate limits and batch sizes (/rate-limits) ## There is no request rate limit today [#there-is-no-request-rate-limit-today] The public API does not enforce a request-rate limit and never returns `429`. You do not need to implement backoff for rate limiting. No enforced limit is not a promise of unlimited throughput. Everything below shares one database, so a fast enough loop degrades your own calls before anything rejects them. Treat the guidance in this page as the supported shape of a bulk load. If a limit is introduced it will arrive as `429` with a `Retry-After` header, and it will be announced on the [changelog](/changelog) first. ## The limits that do exist [#the-limits-that-do-exist] These are per-request size limits, not rate limits. Each rejects the **whole** request — no partial application — so split client-side before sending. | Operation | Limit | On exceeding | | -------------------------- | ---------------------------- | -------------------------- | | Create conversions | 5,000 records per request | `400`, nothing stored | | Add recipients to an order | 5,000 recipients per request | `400`, no recipients added | Both are enforced before any processing, so a rejected batch leaves no partial state — you can safely resubmit smaller batches. ## Pacing a bulk load [#pacing-a-bulk-load] Adding recipients is the expensive step: every recipient is address-validated and deduplicated against your suppression lists before it is stored. So: * **Send recipients in sequential batches, not in parallel.** Concurrent appends to the same order contend on the same rows and are slower in aggregate than one batch after another. * **Batch in the low thousands** rather than at the 5,000 ceiling. Smaller batches fail smaller: a rejected batch of 1,000 is cheaper to diagnose and resend. * **Expect the call to be slow** — it does real work per recipient. Set a generous client timeout (minutes, not seconds) rather than retrying, because a retry after a client-side timeout can re-send recipients the first call already stored. ## Retrying safely [#retrying-safely] The API does not implement idempotency keys, so a blind retry can duplicate work. Before retrying anything that writes: * **Adding recipients** — re-read the order's recipients and compare against what you sent, rather than resending the batch. * **Checkout** — re-read the order's status. If it moved past payment, the checkout succeeded and must not be repeated. * **Creating conversions** — a resend is comparatively safe: matchback deduplicates on the identifiers you supply, so the same record submitted twice does not double-count. And do not retry a `400`, `403`, `404`, `409`, `422`, or a **bodiless `500` on an entitlement-gated operation** — see [response shapes](/api-contract#not-every-response-is-json). Those are all deterministic; the same request will fail the same way.