Skip to main content

Shape

Every error response is a single JSON object:
{
  "error": "short_machine_code",
  "reason": "(optional) human-readable explanation"
}
error is stable — safe to switch on in your code. reason is advisory — surface it in logs / alerts, don’t parse it.

Status codes

StatuserrorWhen
400invalid_jsonBody isn’t valid JSON.
400invalid_bodyBody is valid JSON but didn’t match the endpoint’s schema. reason explains which field.
401unauthenticatedMissing or malformed Authorization: Bearer ... header.
401invalid_keyKey is revoked, unknown, or doesn’t exist in our records.
403forbiddenKey is valid but lacks the required scope. reason says which scope.
404not_foundThe requested entity exists for no org you have access to.
429rate_limitedSee Rate limits. Includes retry_after_seconds.
5xxvariousServer-side bug or outage. Retry with backoff.

Retry guidance

  • Never retry 4xx. They’re client errors — fix and resend.
  • Retry 429 with the Retry-After value. Fixed windows don’t roll over; faster retries are pointless.
  • Retry 5xx with exponential backoff. Cap at 3-5 attempts per request. If 5xx persists, alert on it — don’t silently swallow.

Idempotency on writes

The only write endpoint — POST /v1/deals/events — is idempotent on dedup_key. You can safely retry without creating duplicate events. See Ingest a deal event for details.