Skip to main content
The Developer API uses conventional HTTP status codes and returns a JSON body on every error. The body carries a stable _tag you can switch on and a message meant for your logs:
Branch on _tag (and code where present), never on the message text — messages may change, tags won’t.

Status codes

4xx bodies are safe to surface to your own logs and dashboards. 5xx responses should be retried with backoff — the order decision and webhook replay endpoints are replay-safe, so retrying them is harmless.

Error tags

The 403 codes

A DeveloperApiForbidden always tells you why:
  • insufficient_scope — the credential is valid but lacks a scope the endpoint requires. Check GET /v1/me against the scopes table.
  • wrong_environment — you used a test credential against live data or vice versa. The credential’s prefix fixes its environment.

Handling errors well

  • Switch on _tag/code, log the message. The tag is your control flow; the message is for humans debugging.
  • Don’t retry 4xx unchanged. They mean the request needs to change. The one nuance: a 409 may clear once the conflicting state is resolved.
  • Retry 5xx with exponential backoff. Add jitter to avoid retry storms.
  • Treat write retries as safe. Order decisions and webhook replay are replay-safe, so a retry after a timeout won’t double-apply.