Errors
Every error has one JSON shape. Branch on its code, show its details and quote its request id. The table lists each code the API returns and when.
When the API refuses a request it answers with a status of 400 or above and the same JSON shape on every endpoint. Your code reads code. A person reads message.
A request to create a webhook endpoint without a url, for example:
{"error": {"code": "validation_error","message": "The request could not be validated","details": [{ "field": "url", "message": "Invalid input: expected string, received undefined" }],"request_id": "req_790d3c81de2a406395e413a56865b6f1"}}codestringA stable name in snake_case. Branch on this, never on the message.
messagestringOne plain sentence about what went wrong. The wording can change.
detailsarrayZero or more
{ "field", "message" }pairs that point at the part of the request that caused the error.request_idstringThe id of the request, the same value as the
X-Request-Idresponse header. Quote it when you ask for help.
Error codes
| Status | Code | When |
|---|---|---|
| 400 | invalid_json | The body is not valid JSON, or is not a JSON object or array. |
| 400 | invalid_request | The Idempotency-Key header is longer than 255 characters. |
| 400 | invalid_cursor | cursor is not a value a list returned. |
| 400 | not_supported_yet | The content is audio or video, which the API does not screen yet. Nothing is stored or charged. |
| 401 | missing_api_key | There is no Authorization header, or it is not a bearer token. |
| 401 | invalid_api_key | The key is malformed, unknown, revoked or expired. |
| 402 | quota_exceeded | The monthly checks and the extra checks are used up. details says how many the request needs and how many are left. |
| 403 | insufficient_scope | The key lacks the scope the endpoint asks for. |
| 403 | plan_limit | The plan does not include what was asked, or its limit is reached: a named template on the Free plan, one endpoint, guideline or wordlist too many, a batch larger than the plan takes. details names the limit. |
| 404 | not_found | No such path, or no such resource in the key's project. A resource of another project answers the same. |
| 404 | template_not_found | No template of the project has that slug. |
| 409 | idempotency_key_reused | The Idempotency-Key was already used with another body. |
| 409 | idempotency_in_progress | A request with the same Idempotency-Key is still running. |
| 409 | template_not_published | The template exists and has no published version. |
| 409 | input_not_stored | Re-moderating a moderation whose content was not stored, or has been removed. |
| 409 | is_child | Re-moderating one field of a form. Re-moderate the form. |
| 409 | not_resolved | Reopening a queue item that is not resolved. |
| 409 | action_disabled | Executing an action that is disabled. |
| 409 | slug_taken | A guideline or wordlist of the project already has that slug. |
| 409 | conflict | Another record already holds a value that must be unique. |
| 413 | payload_too_large | The body is larger than 2 MB. |
| 422 | validation_error | The request does not fit the endpoint, or a value in it is refused. details lists each problem. |
| 429 | rate_limited | The key passed its requests a minute. The Retry-After header says how long to wait. |
| 500 | internal_error | Something failed on Infrared's side. |
The pages on authentication, idempotency, rate limits and checks cover their own codes in depth. Statuses and failures covers what a moderation can answer without an HTTP error, such as status: "invalid".
Validation errors
A 422 carries one entry in details per problem.
fieldis the path of the value, joined with dots:url,event_types.0,items.3.input. A problem with the body as a whole readsbody, and one with the query string readsquery.messagesays what is wrong with it. Most messages come from the schema check and can change wording, so match onfield.
| The problem | field | message |
|---|---|---|
| A required value is missing | url | Invalid input: expected string, received undefined |
| A field the endpoint does not know | body | Unrecognized key: "secret" |
| A number out of range | limit | Too big: expected number to be <=100 |
| An id of the wrong kind | moderation_id | must be a mod_ id |
Some values are checked after the schema, and then message at the top says what was refused: url: Target resolves to a private address (localhost).
A submission that fails a template's own validation is not an HTTP error. It answers 200 with a moderation whose status is invalid.
Server errors
A fault on Infrared's side answers 500 and reads the same, whatever failed:
{
"error": {
"code": "internal_error",
"message": "Something went wrong on our side",
"details": [],
"request_id": "req_660bf6f2a3dd480e8a20bec694ba90ea"
}
}The cause is logged on Infrared's side under the request id. Retry the request, and send the id to support if it keeps failing.
A few requests answer 500 today where you would expect a 4xx:
- A body that is not UTF-8, or that uses a
Content-Encodingthe API cannot read. - A
reasonlonger than 255 characters on the author endpoints that block, suspend or enable. Keep it to 255. - A filter value outside its list on two lists:
statusonGET /v1/moderationsandpriorityonGET /v1/queue.
Errors inside a batch
One bad item does not fail a batch. The batch answers 200 or 202, and the item that was refused takes its place in data as an error:
{"object": "error","index": 1,"error": { "code": "template_not_found", "message": "Template old-listing not found", "details": [] }}index is the item's position in the request, counted from 0. The entry has no request_id of its own: use the one of the batch.
What to retry
| Answer | What to do |
|---|---|
429 rate_limited | Wait the number of seconds in Retry-After, then send it again. |
| 5xx, or no answer | Send it again after a short wait that grows with each try. When you create a moderation, reuse the same Idempotency-Key. |
409 idempotency_in_progress | The first request is still running. Wait, then send it again. |
402 quota_exceeded | Sending it again will not help until checks are added. Decide what your product does with unscreened content. |
| Any other 4xx | Do not retry as it is. Change the request, the key or the plan. |
When a moderation carried an Idempotency-Key, a refusal such as 402, 404 or 422 is stored under it. Once the cause is fixed, send the moderation with a new key, or the stored refusal comes back.
Next
- Statuses and errorsThe five statuses a moderation can have and every error the moderation endpoints return, with the HTTP status, the code and what to do next.
- IdempotencySend an Idempotency-Key when you create a moderation, and a retry returns the first answer in place of a second moderation and a second charge.
- Rate limitsEach API key may send a set number of requests a minute, by plan. Every response says where the key stands, and a 429 says how long to wait.
Something missing or unclear on this page? Write to support@useinfrared.com.