Errors
Envelope
All errors share one JSON shape:
{
"error": {
"code": "tier_required",
"message": "This route requires the pro tier",
"details": { "required_tier": "pro" },
"request_id": "f0e1d2c3-b4a5-…"
}
}
code— a stable, machine-readable string. Branch on this, not on the human-readablemessage.message— a human-readable explanation; wording may change.details— optional, present on some errors (e.g.allowedfor an unknown param,required_tierfor a tier gate).request_id— unique per request, also returned in theX-Request-IDresponse header. Include it when contacting support. You may set your own by sending anX-Request-IDrequest header.
HTTP status reflects the category (4xx client, 5xx server).
Error codes
| Status | code | Meaning |
|---|---|---|
400 | unknown_query_param | A query param isn't recognised; details.allowed lists valid ones. |
400 | invalid_sort | The sort field isn't sortable on this endpoint. |
400 | invalid_cursor | The pagination cursor is malformed or stale. |
400 | invalid_grade_type | A grade_type value (sales) isn't valid. |
400 | filter_not_available | A filter requires a higher tier (e.g. has_price on free). |
400 | query_too_long | The search q exceeds the length limit. |
401 | missing_api_key | No X-API-Key header. |
401 | invalid_api_key | Key not recognised. |
403 | tier_required | Your tier is below the route/field/sort requirement. |
403 | out_of_scope | (Beta access only) the resource is outside your catalog slice. |
404 | card_not_found | No card with that id. |
404 | set_not_found | No set with that id. |
404 | pokemon_not_found | No Pokémon with that id. |
404 | price_not_found | The card has no price record. |
422 | validation_error | Request failed schema validation; details carries the field errors. |
429 | rate_limited | Burst or monthly quota exceeded; see Retry-After. |
500 | internal_error | Unexpected server error — retry, and report the request_id if it persists. |
Handling pattern
resp = requests.get(url, headers=headers, params=params)
if not resp.ok:
err = resp.json()["error"]
if err["code"] == "rate_limited":
retry_after = int(resp.headers.get("Retry-After", "5"))
# back off and retry…
elif err["code"] == "tier_required":
# surface an upgrade prompt…
else:
raise RuntimeError(f"{err['code']}: {err['message']} ({err['request_id']})")