Errors & Rate Limits

This page covers the REST API. MCP reports errors differently — inside a successful JSON-RPC response — and has its own page: MCP errors & retries.

The response envelope

Every REST response has the same shape. On success error is null; on failure data is null:

{ "data": { "…": "…" }, "error": null, "meta": { "limit": 25, "offset": 0, "total": 3 } }
{ "data": null, "error": { "id": "a1b2c3d4", "code": "INSUFFICIENT_SCOPE", "message": "this API token does not have the required scope: sbom:write" } }
  • error.code is stable and machine-readable. Branch on it, never on message.
  • error.message is a human-readable explanation; it may change.
  • error.args, when present, carries details — the invalid parameter, the allowed values, the plan a feature needs, or retryAfterSeconds.
  • error.id, when present, is a correlation ID. Quote it to support.

A request to a path that does not exist at all gets a plain-text 404 from the web server, not an envelope.

Error codes

Status Code When What to do
400 VALIDATION_FAILED A JSON body or query parameter failed validation. Bodies reject unknown fields; error.args names the parameter Fix the request
400 SCOPE_INVALID A scope at token creation is unknown, a wildcard or a preset name. The message names it Send explicit scope names from GET /api/v1/tokens/scopes
400 INVALID_REQUEST A malformed multipart form Fix the request
400 MISSING_FILE, UNSUPPORTED_FORMAT, PARSE_ERROR SBOM upload problems — see Upload an SBOM Fix the file
400 INVALID_STATUS, INVALID_SEVERITY An unknown findings filter value Use a documented value
401 UNAUTHORIZED No Authorization header Send Authorization: Bearer aci_…
401 INVALID_TOKEN The token is malformed, unknown, expired or revoked Create a new token
402 FEATURE_GATED Your plan does not include the feature. error.args.minTierName names the lowest plan that does Upgrade, or stop calling it
403 FORBIDDEN The path does not accept API tokens, or the API is not enabled for your deployment Use a signed-in session or MCP; scopes will not help
403 OWNER_REQUIRED The scope you tried to grant can be granted only by an Owner Ask an Owner to create the token
403 INSUFFICIENT_ROLE Your role may not grant one of the requested scopes Ask someone with a higher role
403 SUPPORT_SESSION_NO_MINT A token was created or revoked from a support session Do it from your own signed-in session
403 ORG_SUSPENDED The organisation is suspended. Returned to a token on every token-accessible surface (including the MCP endpoint); the response carries no plan or organisation details, and the suspension can take up to 30 seconds to take effect Contact support; calls work again once the organisation is reactivated
403 PII_UNAVAILABLE A response containing names or emails is not available for this token or deployment Use a token that holds the identity scope, or contact support
403 INSUFFICIENT_SCOPE The token lacks the scope named in the message — or holds pii:read that cannot be honoured Create a token with the right scopes
403 HUMAN_APPROVAL_REQUIRED A human-only action (publish, send back, archive, delete) Do it in the console
404 NOT_FOUND and resource-specific *_NOT_FOUND Unknown or foreign ID. The body is the same for both, so IDs cannot be probed Check the ID
409 STALE_REVISION and limit codes A concurrent edit, or a questionnaire limit — see Supplier questionnaires API Reload and retry, or stay within the limit
413 FILE_TOO_LARGE An SBOM upload over 5 MB Upload a smaller manifest
422 QUERY_TOO_BROAD A lifecycle feed would return more rows than allowed — see Poll leaver items nightly Narrow the filter
422 EXPIRY_REQUIRED, EXPIRY_TOO_LONG, SCOPE_UNAVAILABLE Token creation rules — see API tokens Adjust the token
429 RATE_LIMITED A rate limit was hit. Honour Retry-After Wait, then retry once
500 INTERNAL_ERROR, DB_ERROR Unexpected server error Retry later; quote error.id to support
503 BILLING_UNAVAILABLE The plan could not be checked Retry later
503 AUDIT_UNAVAILABLE A response with names or emails could not be written to the audit trail, so it was withheld Retry later

Rate limits

Limit Applies to Value
Edge limit Every request, per client IP 20 requests per second
Failed authentication Per client IP Repeated failures are blocked for a short while
Lifecycle (/api/v1/jml/*) Per token 5 requests per second sustained, burst of 30; plus an organisation-wide ceiling
Lifecycle feeds (…/items) Per organisation A small number of concurrent requests; excess gets Retry-After: 1
Responses with names or emails Per token, shared by REST, MCP employee_resolve and lifecycle 3,000 identities per hour; see Employee identity
Questionnaire structural edits (create, clone, add or delete sections, questions, options, submit) Per token / per person 30 per hour / 300 per hour
Questionnaire field edits (meta, question, option, translate) Per token / per person 120 per hour / 1200 per hour
MCP Per token and per organisation See MCP errors & retries

The supply-chain endpoints have no per-token limit beyond the edge limit. Per-token limits are design targets enforced per server instance, so the effective ceiling can be somewhat higher; do not build a design that depends on an exact number.

Rate-limit headers

Responses to token calls on rate-limited endpoints carry three headers, on success as well as on 429:

Header Meaning
RateLimit-Limit The size of your token’s request allowance (its burst)
RateLimit-Remaining Whole requests left right now
RateLimit-Reset Seconds until the allowance is full again

Use them to slow down before you hit a 429. A limit that is a daily row budget answers with Retry-After set to the seconds left until 00:00 UTC. The three headers also appear on the supply-chain, supplier-template and lifecycle endpoints, which now share one per-token allowance.

Handling 429

A 429 RATE_LIMITED response carries a Retry-After header in whole seconds (at least 1). Wait that long and retry once; on repeated 429s back off exponentially. Never retry in a tight loop.

If several of your servers share one outbound IP address — a NAT gateway or a CI runner pool — one job that keeps failing authentication can briefly lock the others out. Give each integration its own valid token and fix failing jobs quickly.

Last reviewed: 2026-10-13

Was this page helpful?

Esc