Skip to main content

Rate limits & errors

The API protects itself with two rate limits. Both apply to every request.

Limits

LimitDefaultConfigurable up toScope
Per-API-key requests60 / minute10,000 / minuteSet per key when the key is issued.
Per-IP requests600 / minuteNot configurableApplied across all keys from a given IP.

A request that breaches either limit is rejected with 429 rate_limited.

The default per-key budget is intentionally low. If your integration sustains higher throughput, raise the per-key ceiling at issuance rather than spreading load across multiple keys — the per-IP cap will catch you anyway.

Headers

Every successful response carries the per-key window state:

HeaderMeaning
X-RateLimit-LimitThe current per-key budget.
X-RateLimit-RemainingRequests remaining in the current window.
X-RateLimit-ResetUnix epoch seconds when the current window resets.

A 429 response also carries Retry-After, in seconds. Honor it. Do not retry sooner than the value advertises — doing so deepens the throttle, it does not bypass it.

Error envelope

All non-2xx responses share one shape:

{
"error": {
"code": "validation_error",
"message": "displayName is required.",
"details": {
"field": "displayName"
}
}
}

The fields:

  • code — a stable, machine-readable identifier. Switch on this, not on message.
  • message — a human-readable summary. May change between versions.
  • details — optional, structured. Shape depends on the code. Absent when there's nothing useful to add.

Canonical error codes

HTTPCodeMeaning
400validation_errorRequest body or parameters failed schema validation.
401invalid_tokenBearer token is missing, malformed, expired, or revoked.
403insufficient_scopeToken is valid but lacks a scope the endpoint requires.
404<resource>_not_foundThe named resource does not exist or is not visible to this token. The prefix is the resource name (contact_not_found, deal_not_found, etc.).
429rate_limitedPer-key or per-IP budget exhausted. Honor Retry-After.

<resource>_not_found is intentionally indistinguishable between "doesn't exist" and "exists but not visible to you" — the API does not leak the existence of resources outside the token's tenancy.

Retry guidance

  • Idempotent reads (GET): retry on 429 and on 5xx, with backoff. Cap retries.
  • Writes (POST, PATCH, DELETE): retry only on 429 and on connection-level failures, never on a non-429 4xx. A 4xx other than 429 means the request will not succeed if repeated.
  • Honor Retry-After when present; otherwise use exponential backoff with jitter.