Essentials

Errors

One envelope, every code, and which are worth retrying.

The envelope

Every failure answers with the same shape, so a client can branch on error.code without parsing prose. The message is written for a person and can change; the code will not.

402 Payment Required
{
  "error": {
    "code": "plan_required",
    "message": "API and MCP access is included on the Grow, Scale and Custom plans."
  }
}

The same codes reach MCP clients as tool errors, formatted code: message. See Using the tools.

Every code

StatusCodeWhen
401unauthorizedNo key was sent, or the key is unknown, revoked or expired, or the member who created it has left the workspace or been deactivated.
402plan_requiredThe workspace's plan doesn't include API access. It's included on Grow, Scale and Custom.
402credits_exhaustedThis month's content credits are used up. Retrying won't help until the credits reset on the 1st (UTC).
402payment_requiredThe plan doesn't include this capability for the project, or the workspace has reached its daily usage limit. Drafting a content opportunity is the call that can return it.
403workspace_not_approvedThe workspace is still waiting for approval, or wasn't approved.
403write_not_allowedThe key is read-only. Writes need a read-and-write key, and read-and-write keys need Scale or Custom.
403plan_feature_unavailableThe feature is on a higher plan. Bulk exports and webhooks are Custom-only.
403forbiddenThe workspace or the member the key acts as can't do this in the dashboard either — for example a project with competitive analysis switched off.
404not_foundThe project or item doesn't exist in this workspace. A project from another workspace also returns 404, never 403.
409conflictThe item isn't in a state that allows the change — for example marking an opportunity published before it has a draft, or drafting one that is already being drafted.
422invalid_requestA parameter or body field is missing or has the wrong type or value. The message names the field. Also returned when a write would pass the plan's prompt limit.
422confirmation_requiredA draft spends a content credit, and the call didn't confirm it with `confirm_credit: true`.
422limit_reachedThe workspace already has the maximum number of webhooks (10).
429rate_limitedToo many requests this minute. Wait for the number of seconds in the `Retry-After` header, then retry.
Two of these are easy to confuse and must never be handled the same way. rate_limited means slow down and retry; credits_exhausted means this month is over — the reason it answers 402 rather than 429is precisely so a retrying client doesn’t loop until the 1st.

Server errors

An unexpected failure answers 500with a different body — the one response that isn’t in the envelope:

{
  "detail": "Internal server error",
  "request_id": "5f9c2b14-7a3d-4e21-b0c8-91d2e4f6a7b3"
}

Retry with backoff, and quote the request_id if you report it — it is how we find the request in our logs.

What to branch on

  • Retry: 429 rate_limited after Retry-After, and 5xx with backoff.
  • Stop and tell a human: 401, 402, 403 — a credential, a plan or an approval has to change.
  • Fix the call: 404, 409, 422 — the id, the state or a parameter is wrong. The message names the field.