Errors and limits
The error envelope, the status codes, rate limits and caching.
The error envelope
Every error has the same shape:
{
"code": "forbidden",
"params": { "reason": "cannot_create_request" },
"fields": null
}codeis one of a short, fixed list, matching the HTTP status.params.reason, when present, says which rule refused the call.fieldslists what was wrong with the body, for422: each with itspath(such asdeal_ids) andcode.
Status codes
| Status | code | Common params.reason |
|---|---|---|
| 400 | bad_request | empty_message: a message with no text and no links |
| 401 | unauthenticated | no_api_key, invalid_api_key; see Keys |
| 403 | forbidden | read_only_key, cannot_create_request, cannot_edit_request, cannot_transition, cannot_post |
| 404 | not_found | Unknown, outside your key's deals, or not yours to see |
| 409 | conflict | deal_archived (archived deals read only), invalid_transition (a status the request can't move to), number_taken, section_has_no_status |
| 422 | validation_failed | See fields |
| 429 | rate_limited | Too many calls; see below |
| 500 | internal | Our fault: retry later, and tell us the X-Request-ID |
Who may do what is the same as in the app. The side that runs the request list raises, edits and assigns requests (its admins and editors); either side answers and moves the status (anyone but a viewer).
Rate limits
Each key may make about 600 calls a minute. Past that, calls answer 429 with a
Retry-After header, in seconds, and params.retry_after saying the same. Wait that long, then
carry on. Each key counts on its own.
Request ids
Every response carries an X-Request-ID header. When something goes wrong, quote it to
Cerclen: it finds the call in our logs.
Caching
GET responses carry an ETag. Send it back as If-None-Match and an unchanged response is a
304 Not Modified with no body: cheap to poll.