Skip to main content
The Errors & status codes page documents the canonical response shape and every code the API returns. This guide is the practical companion — how to handle them in code without writing the same boilerplate at every call site.

The minimum viable handler

Now every caller can pattern-match on error.code rather than parsing JSON ad-hoc.

Typed handling by status class

Validation errors — surfacing field messages

400 VALIDATION_ERROR returns per-field arrays of human-readable messages:
Map them straight onto a form:
Nested fields use dot-notation in the key (e.g. boundaries.coordinates).

Retry semantics by status

StatuscodeRetry?How
400VALIDATION_ERRORNoFix the payload
400INVALID_IDNoUUID is malformed
401EXPIRED_API_KEYNoMint a fresh key
401INVALID_API_KEYNoKey was revoked
403INSUFFICIENT_SCOPENoRotate to a key with the required scope
404NOT_FOUNDNoThe resource doesn’t exist
409CONFLICTMaybeIdempotent create — fetch the existing record
429RATE_LIMIT_EXCEEDEDYesWait until X-RateLimit-Reset — see Rate-limit handling
5xxanyYesExponential backoff, max 3 attempts

Idempotency on writes

Mutating endpoints accept an optional Idempotency-Key header (UUID) so a retry after a network blip doesn’t create duplicate resources:
The server stores the result of the first request keyed on (user_id, idempotency_key) for 24 hours. Subsequent requests with the same key and a matching body return the cached response — different bodies for the same key return 409 CONFLICT. Use idempotency keys for:
  • POST creates that you don’t want to double-execute on retry
  • Financial transactions (expenses, sales, payroll runs)
  • Any state-changing call where retries are possible

Logging recommendations

Capture all five fields of an API error in your logs:
The code field is the most useful for grouping; the details field is the most useful for debugging individual incidents.

See also