Errors

Every v2 error has the same shape and a stable code to branch on.

The error envelope

{
  "error": {
    "code": "missing_scope",
    "message": "Token lacks the investors:read scope.",
    "request_id": "9a9d1c5e-4f2b-4c8e-9a7d-2f1e6b3c4d5a",
    "details": []
  }
}
  • code — stable and machine-readable. Branch on this.
  • message — one sentence a person can act on. Show it, log it, but never parse it.
  • request_id — the same value as the X-Request-Id header. Quote it when you contact support.
  • details — one entry per problem when there's more to say: a field and reason for each failure on validation_failed, the permissions that would allow the call on missing_permission.

Status codes

StatusWhen
200 / 201Success. 201 when something was created.
202Accepted as an async job.
204Success with no body, typically a delete.
400The request is malformed.
401No usable token.
403The token is valid but not allowed to do this.
404Not found — or not visible to this token. v2 never reveals that a record you can't see exists.
409Conflicts with the current state, such as a name that's taken or a locked folder.
413The body is over the size limit. Nothing was stored.
422Validation failed, or the operation refused in a documented way.
429Rate limited.
502 / 503An upstream service (for example identity verification) failed or timed out. Retry after Retry-After.

Codes to handle

Authentication and access

CodeStatusWhat to do
invalid_token401The token is missing, malformed or unknown. Check the Authorization header.
expired401The token has passed its expiry. Create a new one.
revoked401The token was revoked. Create a new one.
org_disabled403API access is switched off for the organisation. An administrator can turn it on in Settings → API Suite.
scope_disabled403The area this scope covers is switched off for the organisation.
missing_scope403The token lacks the operation's scope — or its user no longer holds the matching permission.
missing_permission403The acting user lacks a permission the operation needs; details lists the ones that would work.
ip_blocked403The caller's IP isn't on the organisation's or the token's allowlist.
user_disabled403The token's user is suspended.
rate_limited429Wait Retry-After seconds, then retry.

Requests

CodeStatusMeaning
validation_failed422One details entry per problem, each naming the field.
invalid_cursor422The cursor is malformed or doesn't match the request's filters and sort.
not_found404No such record, or not one this token can see.
method_not_allowed405The path exists but not with this method.
payload_too_large413The body is over the limit.

Operations document their own domain codes too — for example folder_locked, form_not_completable or subscription_disabled — on their reference pages.

Rate limits

Each token has a per-minute budget — 60 by default — and every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over it you get 429 rate_limited with Retry-After. See Rate limits for how budgets are set and counted, the operations with tighter limits, and retry code.

Retrying safely

  • Retry 429, 502, 503 and network timeouts, with exponential backoff and jitter.
  • Don't retry other 4xx responses unchanged — fix the request first.
  • Make writes retry-safe with an Idempotency-Key, so a retried create never makes two records.

Request IDs

Every response — success or failure — carries an X-Request-Id. Log it alongside your own request. Every call, including rejected ones, is recorded in your organisation's API audit log under that id, so support can find exactly what happened.