SalesOS

Rate limits

Per-key quotas, the RateLimit headers, and how to back off.

Per-key quota

Every API key has its own limit: N requests per window, set when you create the key (default 1,000 per hour, configurable per minute, hour or day). Each response tells you where you stand:

RateLimit-Limit: 1000
RateLimit-Remaining: 997
RateLimit-Reset: 2712
RateLimit-Policy: 1000;w=3600
HeaderMeaning
RateLimit-LimitRequests allowed in this window
RateLimit-RemainingRequests left in this window
RateLimit-ResetSeconds until the window resets
RateLimit-PolicyThe quota and window length (w, in seconds)

When the quota is spent the API answers 429 with code API_KEY_RATE_LIMITED and a Retry-After header (in seconds). Requests that are refused still appear in the key's usage as rate-limit hits.

Per-app quota

An OAuth app has its own quota, counted separately in each organization that authorized it, with the same headers. Past it the API answers 429 OAUTH_RATE_LIMITED with Retry-After.

Per-address limits

Independently of keys, each client IP is limited to 20 requests per second, 200 per minute and 2,000 per hour. Some sensitive routes are tighter. These return 429 too.

Twenty failed key authentications from one IP within 15 minutes blocks that IP for the rest of the window (API_KEY_AUTH_THROTTLED).

Backing off

  1. On 429 or 503, wait Retry-After seconds, then retry.
  2. Without a Retry-After, back off exponentially (1s, 2s, 4s, …) with jitter, up to a cap.
  3. Retry writes only with an Idempotency-Key, so a retry can never apply twice.
  4. Use RateLimit-Remaining to pace bulk jobs instead of running into the limit. For large volumes use the Bulk API.

Usage analytics

Settings → Developer → Usage shows, for up to 90 days, requests, error rate, p50/p95 latency, top endpoints, status codes and a daily series per API key, per OAuth app and per serverless function (GET /v1/api-usage/summary?days=30, org owner/admin; API keys need *). Traffic appears within about a minute, in hourly buckets. Latency percentiles are approximate: they are reported as the upper bound of a bucket between 10 ms and 10 s. Requests refused by scope checks or rate limits are counted against the key or app that made them. The web app's own session traffic is not counted.

On this page