Error codes
Every HTTP status the API can return, what triggers it, and how to recover.
Error response format
Errors come back as JSON with a consistent shape. Two variants exist depending on where in the stack the error originated:
// FastAPI-generated (most common)
{ "detail": "Human-readable message" }
// Custom business errors
{ "error": "Short type", "status_code": 429, "message": "…" }
Both are safe to display to end users — we've scrubbed anything sensitive.
Status codes
| Code | Meaning | Common causes | What to do |
|---|---|---|---|
| 400 | Bad Request | Invalid indicator format; batch exceeds plan limit; missing required field | Fix the request; check Lookup endpoint for shape |
| 401 | Unauthorized | Missing, invalid, or revoked API key / JWT; token expired | Re-authenticate; generate a new key if it was revoked |
| 403 | Forbidden | Feature not available on your plan (webhooks on Starter, team invite on Pro); viewer tried a destructive action | Upgrade the plan or ask the workspace owner |
| 404 | Not Found | Unknown endpoint; resource doesn't exist or belongs to another user | Check the URL; resource IDs are scoped per user |
| 429 | Too Many Requests | Daily or burst rate limit exceeded | Honor Retry-After header; see Rate limits |
| 500 | Internal Server Error | Unexpected server-side bug | Retry with exponential backoff; if persistent, contact support |
| 502 | Bad Gateway | Upstream dependency (Paddle, Redis) returned an error while we were proxying | Retry; if persistent, check status.reput.io |
| 503 | Service Unavailable | Rate-limiter backing store unreachable (fail-closed) | Retry with backoff; see Rate limits |
Common 400 subtypes
| Message | Fix |
|---|---|
Missing required field: 'indicators' | Include an indicators array in the JSON body |
'indicators' must be an array | Send a JSON array, not a string |
Your pro plan allows a maximum of 50 indicators per request | Reduce the batch or upgrade |
Indicator '…' contains invalid characters | Strip non-ASCII / control characters before sending |
Indicator '…' exceeds maximum length | Truncate — max is 2048 chars for URLs, 253 for hostnames |
Invalid webhook URL — must be http(s) and ≤ 2048 chars | Use a valid absolute URL |
At least one event must be selected | Pick at least one event type when registering a webhook |
Invalid invite token | Token is 64 hex chars; check for truncation |
Retry strategy
- 429, 503: back off. Honor
Retry-Afterif present; otherwise use exponential backoff starting at 1s, max 60s, with jitter. - 500, 502: retry up to 3 times with exponential backoff. If it keeps happening, file an issue — this is not expected.
- 400, 401, 403, 404: don't retry. These are deterministic — retrying will just produce the same error. Fix the input / credentials / plan instead.
Idempotency
/lookup is naturally idempotent — calling it twice with the same body
produces the same response and counts as two requests against your quota
but doesn't mutate state. Webhook registration, API-key creation, and
team invites are not idempotent — retrying those will either
create duplicates or return a 400.