docs

Errors

Every error has the same JSON shape and a stable code. What each code means and what to do about it.

Errors use standard HTTP statuses and always have this body:

{
  "error": {
    "code": "invalid_filters",
    "message": "Some filters are not valid for this audience.",
    "docs_url": "https://docs.diced.si/api/errors#invalid_filters",
    "request_id": "req_4hT9xQ2mLp0aZ7cK",
    "details": [{ "path": "where.0.op", "message": "Operator 'contains' is not valid for field 'state'. Valid operators: in, not_in." }]
  }
}
  • code is stable. Branch on it, not on message or the status.
  • message is plain English and may change. Field-level specifics are in details[].message.
  • docs_url links to the section below.
  • request_id matches the Diced-Request-Id header. Quote it to support.
  • details lists field-level problems on invalid_request and invalid_filters. path is dotted, like where.0.op or filters.topics.

The MCP server returns the same body as a tool result with isError: true. See MCP.

CodeStatusRetry?
unauthorized401No. Fix the key
forbidden403No
not_found404No
invalid_request400 (also 405, 409)After fixing the request
invalid_filters422After fixing the filters
insufficient_chips402After buying chips
max_chips_exceeded409With a higher max_chips or a smaller request
rate_limited429Yes, after Retry-After seconds
capacity_unavailable503Yes, after Retry-After seconds
upstream_unavailable502Yes, with backoff
internal_error500Yes, with backoff

unauthorized

401. The Authorization header is missing, isn't Bearer <key>, or the key is unknown or revoked. The response has WWW-Authenticate: Bearer realm="diced". Check the key in Developers → API keys and create a new one if needed.

forbidden

403. You're authenticated but can't do this. It happens over MCP with OAuth (Claude.ai, ChatGPT) and in the app, where requests act as a person:

  • That person hasn't accepted the Acceptable Use Policy yet, which is required before revealing leads, turning on auto-reveal or creating API keys. Accept it in the app, then retry.
  • An OAuth token without the diced scope. Reconnect the app.

API keys can only be created by someone who accepted the policy, so requests made with a key don't get this check.

not_found

404. No such resource in your workspace, or no such endpoint. Ids from another workspace are not_found too, never forbidden.

invalid_request

400. The request is malformed: the body isn't JSON, a required field is missing, a field has the wrong type, there's an unknown field, or a rule was broken (for example, sending both count and lead_ids to Reveal, or revealing from an audience that is still building). See error.details for each field.

invalid_request also comes with two other statuses:

  • 405 when the path exists but not with that method. The Allow header lists the methods it takes.
  • 409 when an Idempotency-Key was already used for a different request, or the first request with it is still running.

invalid_filters

422. The audience filters are well-formed JSON but not valid: an unknown field, an operator the field doesn't take, a value outside the allowed list, more than 5 topics, topics on a people audience, or an active_date outside the last 14 days. error.details[].path points inside the filters, such as where.2.value or topics. Check the filters reference or GET /v1/filters.

insufficient_chips

402. Your balance can't cover this. Nothing was revealed or charged. Buy a pack or start a plan in the app under Billing, then retry. GET /v1/me and GET /v1/chips show the balance. A batch enrichment job that runs out mid-way doesn't fail with this status; it finishes early with error_code: "insufficient_chips".

max_chips_exceeded

409. The call would spend more than the max_chips you sent. Nothing was revealed or charged. Raise max_chips if you meant to spend that much, or ask for fewer leads. Leads you already unlocked are free and don't count against max_chips.

rate_limited

429. More than 120 requests in the current minute for this key. Wait Retry-After seconds. Describing audiences (POST /v1/describe, or POST /v1/audiences with a prompt) has its own limit of 30 per minute per workspace. See Rate limits.

capacity_unavailable

503. We're temporarily out of capacity to build or look up. Nothing was charged. Retry after the Retry-After header (in seconds).

upstream_unavailable

502. A data source we depend on is down or timed out. Nothing was charged. Retry with exponential backoff; for chip-spending calls, reuse the same Idempotency-Key.

internal_error

500. Something broke on our side. Retry with backoff, reusing your Idempotency-Key, and contact support@diced.si with the request_id if it keeps happening.

On this page