Skip to content

Rate limits and quotas

Two independent limits apply to your traffic. They are enforced at different layers, count different things, and produce different responses, so it is worth knowing which one you have hit before changing anything.

Your partner record is associated with a usage tier. There is no API key to send: which tier meters you is a Collaterate-side association with your partner identity, resolved from the credential you already present.

Tier Sustained rate Burst Daily quota
Standard 10 requests/second 20 100,000 requests
Enterprise 50 requests/second 100 1,000,000 requests

Ask Partner Integrations which tier you are on. These are deliberately conservative starting values rather than a capacity ceiling; if your integration needs more, that is a conversation to have before you build around the numbers rather than after.

Sustained rate is a token-bucket refill rate, and burst is the depth of that bucket. A client that sends 20 requests instantly and then pauses stays inside the standard tier; one that sustains 15 per second does not, even though it never exceeds the burst figure.

Daily quota resets on a fixed daily boundary, not on a rolling 24-hour window. A backfill that consumes the day’s quota by lunchtime leaves nothing for the rest of the day, so pace large one-off reads rather than running them flat out.

Throttled requests are rejected with 429 and code: rate_limit_exceeded. The response is produced by the gateway before your request reaches any application code, but it is shaped as the same application/problem+json document everything else returns, with a requestId - so your existing error handling covers it without a special case.

Above the per-partner tiers, a web application firewall at the edge enforces a rate-based rule of 2,000 requests per source IP per 5-minute window. Exceeding it blocks further requests from that IP until the window rolls off.

Three things about it are easy to get wrong:

  • It counts by IP, not by partner. If you proxy several integrations - or several customers - through one outbound IP, they share this budget. Your own per-partner tier says nothing about how much of it is left.
  • It applies to unauthenticated requests too, including GET /v1/ping. A health check hammering the ping endpoint counts against the same budget as real traffic.
  • It answers 403, not 429. The response comes from the firewall, so there is no problem document and no scope-related meaning to the status. A 403 with no insufficient_scope body is almost always this.

The same firewall runs AWS managed rule sets against request contents. A request that trips one is also rejected with a 403 from the edge. If a request you believe is well-formed is consistently rejected this way, send Partner Integrations the exact request rather than retrying it.

Cache your token. Read expires_in and reuse the token until shortly before it lapses. Minting per request wastes your own budget and Cognito’s token endpoint has limits of its own.

Page with a large limit. The maximum is 200 and the default is 50. Fetching a fixed result set at 200 per page costs a quarter of the requests that the default does, for the same data.

Retry with exponential backoff and jitter. Fixed-interval retries from a fleet of workers re-synchronise into a spike that reproduces the condition you are backing off from. Cap the total number of attempts.

Do not poll for changes. There is no change feed and updatedOn is not a watermark, so a polling loop is both wrong and expensive. See no change polling.

Space out scheduled work. If your integration runs on a cron, avoid the top of the hour. Everyone’s default is the top of the hour.

Symptom Almost certainly
429 rate_limit_exceeded, arriving in proportion to how fast you send Your per-partner rate or burst.
429 rate_limit_exceeded starting partway through the day and continuing Your daily quota.
403 with no insufficient_scope body, from one source IP The per-IP backstop.
403 with an insufficient_scope problem document Not a rate limit at all - a missing scope. See Errors.