Skip to content

Create a moderation

POST/v1/moderationsKey scope moderate

Moderates one object (input) or a whole form (fields) against a template and returns the verdict, the recommendation and a score per policy. Text runs in the request and answers 200; a request with images is queued and answers 202 with the status screening, and the result then arrives in the moderation.completed webhook event or from GET /v1/moderations/{id}. A submission that fails the template's validation is not an error: it answers 200 with the status invalid, the recommendation reject and validation_errors, and consumes no checks.

Needs a key with the moderate scope. Authentication

curl https://api.useinfrared.com/v1/moderations \
  -H "Authorization: Bearer $INFRARED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "review",
    "type": "text",
    "input": "Worst seller ever. You are a complete idiot."
  }'
200 OKResponse
{
  "object": "moderation",
  "id": "mod_20KilKON2Z1Lf75c7AXP6m",
  "template": {
    "slug": "review",
    "version": 1
  },
  "type": "text",
  "status": "completed",
  "flagged": true,
  "recommendation": "reject",
  "severity": "critical",
  "policies": {
    "personal_data": 0,
    "lookalike_characters": 0,
    "profanity": 0,
    "hate_speech": 0,
    "toxicity": 0.98,
    "violence": 0,
    "self_harm": 0,
    "sexual": 0,
    "spam": 0,
    "links_contact": 0,
    "illicit": 0,
    "gibberish": 0,
    "off_topic": 0,
    "made_with_ai": 0,
    "instructions": 1
  },
  "triggered": ["toxicity", "instructions"],
  "rule": null,
  "reasons": [
    "trigger:toxicity:flag",
    "trigger:instructions:flag",
    "triage:reject"
  ],
  "details": {
    "toxicity": {
      "labels": ["insult"],
      "matches": [
        {
          "label": "insult",
          "value": "Worst seller ever. You are a complete idiot."
        }
      ]
    },
    "instructions": {
      "labels": ["confidence:100"],
      "matches": [
        {
          "label": "evidence",
          "value": "You are a complete idiot.",
          "field": "input"
        }
      ],
      "explanation": "The review contains personal attacks against the seller rather than focusing on the product or service, which violates the policy against personal attacks.",
      "field": "input"
    }
  },
  "author": null,
  "language": "en",
  "usage": {
    "checks": 1,
    "cached": false
  },
  "latency_ms": 2184,
  "dry_run": false,
  "content_id": null,
  "context_id": null,
  "metadata": null,
  "created_at": "2026-10-08T09:28:34.691Z",
  "completed_at": "2026-10-08T09:28:37.066Z"
}

Headers

Idempotency-Keystring

A unique string of up to 255 characters that makes the request safe to retry. The first response is stored for 24 hours and returned again, with the header Idempotent-Replayed: true, to any request that repeats the key with the same body. Keys are scoped to the API key and the endpoint.

Request body

A single object

templatestring

Slug of the template to run, 2 to 80 characters. When omitted, the project's default template runs, or the built-in basic check (basic) when the project has none. On a plan without templates only the basic check runs, and naming any other template answers 403 plan_limit.

content_idstring

Your id for the object, up to 200 characters. It is stored, returned and usable as a list filter. Duplicate detection skips earlier moderations with the same content_id, so a resubmitted object is not counted as its own duplicate.

author_idstring

Your id for the end user who wrote the content, up to 200 characters. An unknown id creates the author. The author's status and trust level are then available to content rules, and the moderation counts towards the author's history unless it is a dry run or made with a test key.

context_idstring

Your id for what the content belongs to, such as a conversation or an order, up to 200 characters. It is stored, returned and usable as a list filter. The pipeline does not read it.

metadatamap

Up to 50 key and value pairs of your own, returned with the moderation. Keys are up to 64 characters; values are strings of up to 1,000 characters, numbers, booleans or null. Nested objects and arrays answer 422. The pipeline does not read it.

modeenumDefault auto

auto (default) runs text in the request and queues anything with images. sync runs in the request whatever the content. async always queues and answers 202.

One ofautosyncasync

dry_runboolean

When true, the result is marked dry_run: true and you are expected not to enforce its recommendation. The pipeline runs in full, checks are consumed and a review recommendation still creates a review queue item, but the author's history is not updated. A project can also run in dry run as a whole, with the same effect on every request. Default false.

storeboolean

Set to false to keep the input and its media out of storage for this moderation; it then cannot be re-moderated. True does not override a project, template or plan that stores no content. Default: the project's setting.

client_actionobject

Your own decision about the object, applied after the content rules and severity triage.

actionenumRequired

escalate replaces the recommendation only when yours is stricter, in the order allow, review, reject. override always replaces it.

One ofescalateoverride

recommendationenumRequired

The recommendation to apply: allow, review or reject.

One ofallowreviewreject

typeenumDefault text

The kind of content in input: text (default) or image. audio and video are in development and answer 400 not_supported_yet.

One oftextimageaudiovideo

inputstring or URL or array of URLsRequired

The content of a single object. For text, a string of up to 20,000 characters. For image, an http or https URL of up to 2,048 characters, or an array of 1 to 20 of them; without field, exactly one image is accepted. Infrared fetches each image itself: JPEG, PNG, WebP or GIF, up to 10 MB.

fieldstring

Key of the template field this object is: a lowercase letter followed by up to 63 lowercase letters, digits or underscores. The field's validation and triggers then apply. Without it, only template-level settings apply and every field-level trigger of the template is applied to the object.

A whole form

templatestring

Slug of the template to run, 2 to 80 characters. When omitted, the project's default template runs, or the built-in basic check (basic) when the project has none. On a plan without templates only the basic check runs, and naming any other template answers 403 plan_limit.

content_idstring

Your id for the object, up to 200 characters. It is stored, returned and usable as a list filter. Duplicate detection skips earlier moderations with the same content_id, so a resubmitted object is not counted as its own duplicate.

author_idstring

Your id for the end user who wrote the content, up to 200 characters. An unknown id creates the author. The author's status and trust level are then available to content rules, and the moderation counts towards the author's history unless it is a dry run or made with a test key.

context_idstring

Your id for what the content belongs to, such as a conversation or an order, up to 200 characters. It is stored, returned and usable as a list filter. The pipeline does not read it.

metadatamap

Up to 50 key and value pairs of your own, returned with the moderation. Keys are up to 64 characters; values are strings of up to 1,000 characters, numbers, booleans or null. Nested objects and arrays answer 422. The pipeline does not read it.

modeenumDefault auto

auto (default) runs text in the request and queues anything with images. sync runs in the request whatever the content. async always queues and answers 202.

One ofautosyncasync

dry_runboolean

When true, the result is marked dry_run: true and you are expected not to enforce its recommendation. The pipeline runs in full, checks are consumed and a review recommendation still creates a review queue item, but the author's history is not updated. A project can also run in dry run as a whole, with the same effect on every request. Default false.

storeboolean

Set to false to keep the input and its media out of storage for this moderation; it then cannot be re-moderated. True does not override a project, template or plan that stores no content. Default: the project's setting.

client_actionobject

Your own decision about the object, applied after the content rules and severity triage.

actionenumRequired

escalate replaces the recommendation only when yours is stricter, in the order allow, review, reject. override always replaces it.

One ofescalateoverride

recommendationenumRequired

The recommendation to apply: allow, review or reject.

One ofallowreviewreject

fieldsmapRequired

A whole form: an object of 1 to 40 entries that maps each template field key to its value. Text fields take a string, image fields a URL or an array of URLs, and number, boolean, enum, url and json fields a value of their type. A key that is not a field of the template fails validation. Not accepted together with input, type or field.

Returns

Status 200 with the finished moderation when it ran in the request: status is completed, partial or invalid. Status 202 with the moderation in the status screening when it was queued: recommendation, severity, latency_ms and completed_at are null, policies is empty and details is absent until it finishes.

Errors

400
not_supported_yet

The request carries audio or video, as type or as a value in an audio or video field of a form. Nothing is stored and no check is consumed.

400
invalid_request

Idempotency-Key is longer than 255 characters.

402
quota_exceeded

The organisation's remaining monthly checks and extra checks together are fewer than the checks this request needs. Test keys are never refused for quota.

403
plan_limit

The request names a template other than basic and the organisation's plan does not include templates.

404
template_not_found

The project has no template with that slug, or the template is archived.

409
template_not_published

The template has no published version.

409
idempotency_key_reused

The Idempotency-Key was already used with a different request body.

409
idempotency_in_progress

A request with the same Idempotency-Key is still being processed.

422
validation_error

The body matches neither shape: it has an unknown key, both input and fields, neither of them, or a value outside the limits listed for the properties.

Every endpoint can also answer the errors any request can meet: a missing key, a rate limit, a malformed body. Errors

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