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." }]
}
}codeis stable. Branch on it, not onmessageor the status.messageis plain English and may change. Field-level specifics are indetails[].message.docs_urllinks to the section below.request_idmatches theDiced-Request-Idheader. Quote it to support.detailslists field-level problems oninvalid_requestandinvalid_filters.pathis dotted, likewhere.0.oporfilters.topics.
The MCP server returns the same body as a tool result with isError: true. See MCP.
| Code | Status | Retry? |
|---|---|---|
unauthorized | 401 | No. Fix the key |
forbidden | 403 | No |
not_found | 404 | No |
invalid_request | 400 (also 405, 409) | After fixing the request |
invalid_filters | 422 | After fixing the filters |
insufficient_chips | 402 | After buying chips |
max_chips_exceeded | 409 | With a higher max_chips or a smaller request |
rate_limited | 429 | Yes, after Retry-After seconds |
capacity_unavailable | 503 | Yes, after Retry-After seconds |
upstream_unavailable | 502 | Yes, with backoff |
internal_error | 500 | Yes, 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
dicedscope. 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
Allowheader lists the methods it takes. - 409 when an
Idempotency-Keywas 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.