API reference
Errors
Status codes and the error body the API returns.
Errors come back as JSON with a single error field that says what went wrong in plain words.
Response · 400
{
"error": "type and idempotency_key are required"
}
Two kinds of error come back as plain text instead: a body that isn't valid JSON or an ID in the path that isn't a UUID (both 400), and unexpected server failures (500). Check the Content-Type before parsing.
Status codes
| Code | Meaning | What to do |
|---|---|---|
200 | Success | |
201 | Created: a note, a rule draft or a key | |
202 | Event accepted (async mode) | Nothing. The event is stored. |
400 | The request doesn't match the schema | Fix the request. The error field says what's wrong. |
401 | Missing, invalid or revoked key | Check the Authorization header and that the key is active |
403 | Four-eyes: you can't approve your own work | Ask someone with a different key to approve it |
404 | No such record in your organisation | Check the ID, and that you're using a key from the right organisation |
409 | The record isn't in a state that allows this | Fetch it again and check its status |
413 | The request body is over 1 MiB | Send smaller requests. An event is a few kilobytes |
429 | Too many requests for this API key | Wait the number of seconds in the Retry-After header, then retry. Spread steady traffic across time, or ask for a higher SENTINEL_RATE_LIMIT |
503 | Screening has no list loaded | Load a list. See Screening. |
5xx | Something failed on the server | Retry with the same idempotency key. You won't create duplicates. |
Messages you might see
| Endpoint | Code | error |
|---|---|---|
Any /v1 endpoint | 401 | missing or invalid API key |
POST /v1/entities | 400 | id is required |
POST /v1/entities | 400 | unknown kind |
POST /v1/events | 400 | type and idempotency_key are required |
POST /v1/events | 400 | amount needs a non-negative value and a 3-letter currency |
GET /v1/decisions/{id} | 404 | decision not found |
PATCH /v1/alerts/{id} | 400 | unknown status |
PATCH /v1/alerts/{id} | 400 | status can only be open or in_review here; close alerts through /closure |
PATCH /v1/alerts/{id} | 400 | assigned_to cannot be empty |
PATCH /v1/alerts/{id} | 409 | alert is pending closure or closed |
POST /v1/alerts/{id}/notes | 400 | body must be 1 to 5000 characters |
POST /v1/alerts/{id}/closure | 400 | unknown disposition |
POST /v1/alerts/{id}/closure | 409 | only open or in_review alerts can be put up for closure |
POST /v1/alerts/{id}/closure/approve | 403 | the person who requested closure cannot approve it |
POST /v1/alerts/{id}/closure/approve, /reject | 409 | alert is not pending closure |
Any /v1/alerts/{id} route | 404 | alert not found |
POST /v1/rules | 400 | key must be lowercase letters, digits and underscores, starting with a letter |
POST /v1/rules | 400 | weight must be between 1 and 100 |
POST /v1/rules | 400 | A compile error from the expression, for example rule my_rule: expression must return bool |
POST /v1/rules/{id}/activate | 403 | the author of a rule cannot approve it |
POST /v1/rules/{id}/activate | 409 | only a draft can be activated |
POST /v1/rules/{id}/backtest | 400 | window is capped at 31 days |
POST /v1/rules/{id}/... | 404 | rule not found |
POST /v1/screenings | 400 | kind must be person or business |
POST /v1/screenings | 503 | no screening list is loaded, so nothing can be checked |
GET /v1/screenings/{id} | 404 | screening not found |
POST /v1/keys | 400 | name must be 1 to 64 characters |
DELETE /v1/keys/{id} | 409 | you can't revoke the key you are signed in with |
DELETE /v1/keys/{id} | 409 | this is the last active key; create another before revoking it |
DELETE /v1/keys/{id} | 409 | this key is already revoked |
DELETE /v1/keys/{id} | 404 | key not found |
Each endpoint's page lists its full set. Treat the message as something to log and show to developers, not something to parse. Branch on the status code.