Skip to content

Statuses and errors

The five statuses a moderation can have and every error the moderation endpoints return, with the HTTP status, the code and what to do next.

A request to moderate can go wrong in two different ways. The API can refuse it: the answer is a 4xx with an error body, and no moderation exists. Or the API can accept it and return a moderation whose status says the result is not a complete screening. Your code needs a branch for each.

One case sits where people do not expect it. A submission that breaks the template's validation is not refused: it answers 200 with a moderation whose status is invalid.

The five statuses

statusWhat it meansrecommendationChecks
screeningAccepted and queued, or running. The request answered 202.nullNone yet
completedEvery policy answered.ComputedUsed
partialAt least one policy did not answer. The others stand.Computed from the policies that answeredUsed in full
failedThe run itself did not finish.nullNone
invalidThe submission failed validation. Nothing was screened.rejectNone

Only completed and partial carry a recommendation that came from screening.

Invalid submissions

Validation runs before any model and costs nothing. This form breaks four rules of a template named listing: an unknown field, a title that is too short, a missing description and a negative price.

curl https://api.useinfrared.com/v1/moderations \
  -H "Authorization: Bearer $INFRARED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "listing",
    "content_id": "listing_18343",
    "fields": {
      "title": "Oak",
      "price": -5,
      "colour": "brown"
    }
  }'
200 OK, trimmedJSON
{
  "object": "moderation",
  "id": "mod_2JVuJCJ0O0vr3KhzCfN6wY",
  "template": { "slug": "listing", "version": 1 },
  "type": "form",
  "status": "invalid",
  "flagged": true,
  "recommendation": "reject",
  "severity": "none",
  "policies": {},
  "triggered": [],
  "rule": null,
  "reasons": ["validation_failed"],
  "details": {},
  "validation_errors": [
    { "field": "colour", "code": "unknown_field", "message": "colour is not a field of this template" },
    { "field": "title", "code": "min_length", "message": "Title must be at least 5 characters" },
    { "field": "description", "code": "required", "message": "Description is required" },
    { "field": "price", "code": "min", "message": "Price must be at least 0" }
  ],
  "usage": { "checks": 0, "cached": false },
  "content_id": "listing_18343"
}

Each entry names the field, a stable code and a message you can show. The message uses the field's display name from the template.

codeThe value
requiredis missing or empty, and the field is required
typeis not the kind the field takes: text, a number, true or false, an object
min_length, max_lengthis shorter or longer than the field allows, or longer than 20,000 characters
numeric, pattern, enumdoes not match the field's format or its allowed values
min, maxis a number outside the field's range
min_items, max_itemsholds too few or too many files
urlis not an http or https URL
unknown_fieldbelongs to a field the template does not have
type_mismatchwas sent as text to an image field, or as an image to a text field

For a single object sent without field, the entry's field is input for a text and null for an image. When the field parameter itself is wrong, it is the word field.

An invalid moderation is still a moderation. It has an id, shows in the Live console and is reported by a moderation.completed event. It does not enter the review queue and does not count in the author's history.

Partial results

partial means one or more policies did not answer: a model call failed or timed out, or an image could not be fetched. The decision was made on the rest.

An image that could not be fetched, trimmedJSON
{
  "object": "moderation",
  "id": "mod_3awxoUbFeEr4cO37Rim1mh",
  "type": "image",
  "status": "partial",
  "flagged": false,
  "recommendation": "review",
  "severity": "none",
  "policies": { "toxicity": 0, "hate_speech": 0, "profanity": 0, "spam": 0 },
  "reasons": ["triage:allow", "partial:violence,self_harm,sexual,illicit", "partial_review"],
  "details": {
    "violence": { "error": "HTTP 404 fetching media" },
    "self_harm": { "error": "HTTP 404 fetching media" },
    "sexual": { "error": "HTTP 404 fetching media" },
    "illicit": { "error": "HTTP 404 fetching media" }
  }
}

Three places say which policies are missing: they are absent from policies, named in one partial: entry of reasons, and listed in details with an error. When a missing policy was able to trigger, an allow becomes review, so content does not pass on a screening that did not happen. A recommendation set by one of your content rules is kept as it is.

A partial result uses its checks in full.

Failed runs

failed means the run did not finish at all. error holds code: "pipeline_error" and a message, there is no recommendation, and no check is used. A moderation.failed event is sent. Treat the content as not screened and send it again.

Errors that refuse the request

Every error has the same body. code is stable and is what your code should branch on; request_id is also in the X-Request-Id response header.

402 Payment RequiredJSON
{
  "error": {
    "code": "quota_exceeded",
    "message": "The monthly checks quota is exhausted and no extra checks are available",
    "details": [{ "field": "checks", "message": "1 needed, 0 available" }],
    "request_id": "req_d04336b3bb314aa594a223d16009a477"
  }
}
HTTPcodeWhenWhat to do
400invalid_jsonThe body is not valid JSON.Fix the body.
400not_supported_yettype is audio or video, or a form holds a value in an audio or video field.Leave those values out.
401missing_api_key, invalid_api_keyNo bearer key, or one that is unknown, revoked or expired.Check the key.
402quota_exceededA live key, and the monthly checks plus extra checks cannot cover this request.Buy extra checks or wait for the reset. See Checks.
403insufficient_scopeThe key lacks the moderate scope, or read for a GET.Use a key with the scope.
403plan_limitThe request names a template on a plan without templates, or a batch is larger than the plan allows.Send it without template, shrink the batch, or change plan.
404template_not_foundNo template has that slug, or it is archived.Check the slug.
404not_foundThe moderation id is unknown or belongs to another project.Check the id and the key.
409template_not_publishedThe template has no published version yet.Publish it.
409idempotency_key_reused, idempotency_in_progressThe Idempotency-Key was used with another body, or its first request is still running.See Idempotency.
409input_not_stored, is_childA re-moderation of content that was not stored, or of one field of a form.See Dry run and re-moderation.
413payload_too_largeThe body is over 2 MB.Send fewer or shorter items.
422validation_errorThe body or the query does not match the schema.Read details.
429rate_limitedThe key passed its requests per minute.Wait for Retry-After seconds. See Rate limits.
500internal_errorSomething failed on Infrared's side.Retry with the same Idempotency-Key.

Details worth knowing

422 is about the shape of the request, not the content. A body is either a single object or a form, and when it fits neither, details often says only { "field": "body", "message": "Invalid input" }. A missing input, a misspelt mode or type, a nested value in metadata and fields sent together with input all read that way. An unknown key is named: Unrecognized key: "priority".

Validation comes before the quota. A submission that is invalid answers 200 with status: "invalid" even when no checks are left, because it would use none.

A template is never swapped for another. On a plan without templates, a request that names one answers 403 whether or not the template exists. The basic check answers to the name basic on every plan.

The default template has to be published. When the project's default template has no published version, requests that name no template answer 409 template_not_published too.

An error is replayed under the same key. A 4xx answer is stored with its Idempotency-Key for 24 hours. After you fix the cause, send the request with a new key.

Next

Something missing or unclear on this page? Write to support@useinfrared.com.