Errors
Branch on code, never on the message text. Messages
get reworded; codes are part of the contract.
| Code | HTTP | Meaning |
|---|---|---|
unauthenticated | 401 | No bearer token, or the token is not a key. |
invalid_key | 401 | The key is unknown or has been revoked. |
forbidden_scope | 403 | The key does not hold the required scope. |
not_found | 404 | No such task, business, or resource for this developer. |
invalid_request | 422 | The body is missing a field or fails validation. |
conflict | 409 | The task is not in a state that allows this action. |
idempotency_conflict | 409 | An Idempotency-Key was reused with a different body. |
rate_limited | 429 | Too many requests in the window. Retry shortly. |
quota_exceeded | 429 | The daily task quota for this key mode is spent. Resets 00:00 UTC. |
internal | 500 | Something broke on our side. Nothing was charged. |
{
"code": "forbidden_scope",
"message": "Key is missing required scope 'tasks:write'.",
"docs_url": "https://docs.gethandleit.com/guide/errors#forbidden_scope",
"detail": "Key is missing required scope 'tasks:write'.",
"scope": "tasks:write"
}
detail repeats the message so clients written
against the older shape keep working.
Retrying
rate_limited is worth an immediate retry with
backoff. quota_exceeded is not: it carries used,
limit and remaining, and only resets at 00:00 UTC.
Everything in the 4xx range is a bug in the request, not bad luck.