CitationBenchTalk to Sales
API reference

Error reference — HTTP status codes, error envelope, and stable codes

CitationBench uses standard HTTP status codes plus a single error envelope with stable `code`, `message`, `details`, and `requestId` across REST and MCP. Branch on `code` in your client.

CitationBench uses standard HTTP status codes and a single error envelope across REST and MCP. Every error response carries a stable error code you can branch on, a human-readable message, structured details, and a requestId to include in support tickets.

Envelope

{
  "type": "https://citationbench.com/errors/insufficient_credits",
  "code": "insufficient_credits",
  "message": "Need 150 credits to invoke bootstrap_brand; you have 42.",
  "details": {
    "required": 150,
    "available": 42,
    "skill": "bootstrap_brand"
  },
  "requestId": "req_01HVZ..."
}
FieldNotes
typeStable URL (also resolves to this page section); use to link from your own UI
codeBranch on this in code
messageSafe to surface to end users
detailsPer-error structured info
requestIdInclude in any support email or ticket

For agentic endpoints, errors land in the invocation's error field rather than in the top-level response. The invocation transitions to FAILED. The shape is the same.

Status-code overview

HTTPWhen
200OK, sync result
202Accepted, async job started; returns an invocation handle
204OK, no content (deletes)
400Validation, schema, or argument errors
401Auth missing, invalid, or expired (and endpoint doesn't allow demo mode)
402Insufficient credits
403Forbidden — workspace / scope / agency mismatch
404Resource not found
409Conflict — idempotency replay or concurrent modification
422Unprocessable — schema valid but business rule violated
429Rate limited
500Server bug; include requestId when reporting
503External dependency unavailable (DataForSEO, Ahrefs, GSC, Apollo, Anthropic, etc.)

Common error codes

Auth & access

CodeHTTPCauseWhat to do
unauthorized401Missing / invalid Authorization header on an endpoint that doesn't allow demo modeCheck key; if exploring, try without the header to get a demo-mode response
key_revoked401Key has been revokedCreate a new key
key_expired401Key reached its expiresAtRotate to a new key
forbidden403Key lacks the scope needed for the resourceCheck the key's scope field
workspace_forbidden403Key can't act on the requested X-Workspace-IdUse the correct workspace, or use an agency master key
agency_key_required403Endpoint requires an agency master keyUse an agency key

Validation

CodeHTTPCauseWhat to do
validation_error400Request body failed schema validationInspect details.errors for per-field issues
unknown_skill400skill is not in the registry (or not visible to your workspace)List skills with GET /v1/agent/skills
unknown_action400action on a bulk-action call is not a registered toolInspect inventory
invalid_url400URL malformed for an indexing / publish / outreach endpointValidate before sending
domain_not_verified403URL is on a domain not in the connected GSC's verified listVerify the domain in GSC first

Resources

CodeHTTPCauseWhat to do
not_found404Resource doesn't exist (or is archived)Check the ID; consider ?includeArchived=true
keyword_not_found404
pillar_not_found404
workspace_not_found404
account_not_found404Link-building account not found
relationship_not_found404Link-building relationship not found

Conflict / concurrency

CodeHTTPCauseWhat to do
idempotency_replay409Same Idempotency-Key was used recentlyReturns the prior result; safe to treat as success
concurrent_modification409Another invocation is currently modifying this resourceWait briefly and retry, or query the in-flight invocation
duplicate_keyword409Exact-match keyword already exists in this workspaceLook it up and update instead
duplicate_pending_indexing409URL already has a pending indexing submission todayNo action needed

Business rules

CodeHTTPCauseWhat to do
insufficient_credits402Reserved cost exceeds remaining creditsTop up credits or pass ?dryRun=true to estimate
budget_too_low422budget.maxCredits is below the skill's minimumRaise the budget
no_drafts_produced422All SERP results were filtered outLoosen filters
no_keywords_in_scope422Search filter matched zero keywordsBroaden the filter
content_too_long422targetWordCount exceeds the model's safe windowPick another model or lower the target
outreach_platform_not_configured403No Instantly connection in this workspaceConnect Instantly first
gsc_not_connected403No GSC connectionRun the OAuth flow at /v1/indexing/gsc-index/config
gsc_captcha_required503Cookie session needs reCAPTCHAAdmin must re-auth

Rate limiting

CodeHTTPCauseWhat to do
rate_limited429Per-key rate exceededBack off, respect Retry-After
concurrency_limited429Too many simultaneous invocationsStagger via mode: "BACKGROUND" + queue management

External

CodeHTTPCauseWhat to do
external_unavailable503Upstream provider downBack off; partial results may still have been saved
skill_unavailable503Skill depends on an external service that's downTry a different skill, or wait
dataforseo_unavailable503DataForSEO failureSame
ahrefs_unavailable503Ahrefs failureSame
apollo_unavailable503Apollo failureSame
model_unavailable503Selected LLM is upstream-degradedPass another model

Server

CodeHTTPCauseWhat to do
internal_error500Server bugDon't retry. Report requestId to support.

Retry guidance

StatusRetry?How
4xx (except 408, 429)NoFix the request
408YesOne immediate retry
429YesExponential backoff respecting Retry-After header
500NoReport the requestId
502 / 503 / 504YesExponential backoff, max 5 retries, jitter

For agentic endpoints, the invocation itself handles retries of its own internal tool calls (configurable via budget.maxRetries). You retry the invocation only when the request to start it fails — once you have an invocationId, the agent persists.

Idempotency

Every write endpoint accepts Idempotency-Key:

curl -X POST .../v1/agent/invoke \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{...}'

Same key replayed within 24h returns the same response — useful for resumable scripts and at-least-once delivery patterns. The replay sets code: "idempotency_replay" only when the request body changed; if the body is identical, you get a 200/202 with the original result.

Demo mode + errors

Demo mode endpoints can return error envelopes too — for example, validation_error if you send malformed JSON. They just won't return insufficient_credits (demo runs are free), external_unavailable (no real third parties touched), or anything tied to live state.

A short list of endpoints do not respond in demo mode and will return unauthorized if called without a live key: real publishing to a connected CMS, real outreach email send, real GSC indexing submission, real Apollo contact discovery. See Authentication.

Webhook delivery errors

Outbound webhooks have their own retry policy:

  • 4 retries with exponential backoff (1s, 5s, 30s, 5m)
  • Final failure → event moves to the dead-letter queue, queryable via GET /v1/webhooks/dead-letter
  • Replay via POST /v1/webhooks/dead-letter/{id}/replay

On this page