Skip to content

The moderation object

The verdict, the scores, the evidence in details and your own context. Every field of a moderation, and when each one is present.

Every endpoint that returns a moderation returns the same object: the response to POST /v1/moderations, each entry of a batch, GET /v1/moderations/{id}, each row of the list and data.moderation in a webhook event. Read it once and you can read all of them.

The object never echoes the content you sent. It carries what Infrared concluded about it.

A finished moderation, details trimmedJSON
{
  "object": "moderation",
  "id": "mod_7ZgXCne4LiwQrsodlx4R8U",
  "template": { "slug": "listing", "version": 1 },
  "type": "text",
  "field": "description",
  "status": "completed",
  "flagged": true,
  "recommendation": "review",
  "severity": "critical",
  "policies": {
    "personal_data": 0.75,
    "lookalike_characters": 0,
    "wordlist/competitors": 0,
    "duplicate": 0,
    "profanity": 0,
    "hate_speech": 0,
    "toxicity": 0,
    "violence": 0,
    "self_harm": 0,
    "sexual": 0,
    "spam": 0,
    "links_contact": 0.9,
    "illicit": 0,
    "gibberish": 0,
    "made_with_ai": 0,
    "instructions": 0.8,
    "guideline/no-off-site-deals": 1,
    "screenshot": 0,
    "image_quality": 0,
    "watermark": 0
  },
  "triggered": ["personal_data", "guideline/no-off-site-deals", "instructions"],
  "rule": { "id": "r6", "name": "Links from new accounts", "action": "review" },
  "reasons": [
    "trigger:personal_data:flag",
    "trigger:guideline/no-off-site-deals:flag",
    "trigger:instructions:flag",
    "rule:r6"
  ],
  "details": {
    "personal_data": {
      "labels": ["phone"],
      "matches": [{ "label": "phone", "value": "+44 7700 900123", "start": 88, "end": 103 }],
      "masked_output": "Solid oak, minor marks on one leg. Order direct at https://shop.example.com/oak or call +44***23",
      "field": "description"
    },
    "links_contact": {
      "labels": ["url", "phone"],
      "matches": [
        { "label": "url", "value": "https://shop.example.com/oak", "start": 51, "end": 79 },
        { "label": "phone", "value": "+44 7700 900123", "source": "model" }
      ],
      "field": "description"
    },
    "instructions": {
      "labels": ["confidence:90"],
      "matches": [{ "label": "evidence", "value": "Order direct at https://shop.example.com/oak or call +44 7700 900123", "field": "description" }],
      "explanation": "The description directs users to an external website and provides a phone number, which violates the policy against off-site deals.",
      "field": "description"
    }
  },
  "author": { "id": "aut_1reK9hfk33nRTsdZpGN25v", "external_id": "user_42", "status": "enabled", "trust_level": "new", "known": true },
  "language": "en",
  "usage": { "checks": 0, "cached": false }, // sent with a test key, which uses none
  "latency_ms": 3073,
  "dry_run": false,
  "test": true,
  "content_id": "listing_18342",
  "context_id": null,
  "metadata": null,
  "created_at": "2026-10-08T08:54:58.214Z",
  "completed_at": "2026-10-08T08:55:01.913Z"
}

This is the description of a listing from Moderate text, sent to a template named listing that has a guideline, a wordlist and AI instructions of its own.

What was moderated

idstring

mod_ and 22 characters. Use it to fetch the moderation, to re-moderate it and to match a webhook event.

templateobject

The slug of the template that ran and the version of it. basic is the built-in check. A moderation keeps the version it ran on when the template changes later.

typestring

What was sent. form is the parent of a whole form.

One oftextimageform

fieldstring

The template field this object is. Present on a single object sent with field and on every child of a form.

fieldsmap

Present on a form only: one moderation per content field, keyed by field key.

parent_idstring

Present on a child of a form only: the id of its parent.

The verdict

statusstring

Where the moderation stands. Read it first: the fields below mean something only once it is no longer screening. Statuses and errors describes each one.

One ofscreeningcompletedpartialfailedinvalid

flaggedboolean

true when a trigger with the flag effect fired, and on a submission that failed validation. This is the SAFE or FLAGGED verdict.

recommendationstring

What to do with the content. null while screening and on a failed run.

One ofallowreviewreject

severitystring

The band of the highest weighted score. null while screening and on a failed run.

One ofnonelowmediumhighcritical

policiesmap

A score from 0 to 1 for every policy the template enables, keyed by policy. Empty while screening and on failed and invalid moderations.

triggeredarray of strings

The keys of the policies whose trigger fired, each once.

ruleobject

The content rule that decided, as id, name and action. null when severity triage decided.

reasonsarray of strings

The path to the decision, step by step. How a decision is made lists every value.

The evidence

details holds what each policy found, keyed by policy. A policy appears there when it has something to say. On an object that names a field, every policy that ran appears, at least with that field's key.

KeyTypeWhat it holds
labelsarray of stringsSub-labels of the finding: insult, phone, url. Also marks the pipeline adds: ocr for a finding in text read from an image, confidence:90 on AI instructions and guidelines.
matchesarray of objectsThe pieces of evidence. Their shape depends on the policy, as listed below.
masked_outputstringpersonal_data only: the text with every finding masked, ready to store or show.
canonical_termstringWordlists only: the canonical form of the first term that matched.
explanationstringAI instructions and guidelines: one or two sentences on why. Image policies: a one-sentence description of the picture.
fieldstringThe field the result belongs to, or the field a whole-form finding is about.
cachedbooleantrue when the result came from the result cache.
errorstringThe policy did not answer. Its score is then missing from policies.
PolicyOne entry of matches
personal_datalabel (email, phone, iban, card, national_id, address), value, start, end
links_contactlabel (url, messenger, off_platform, phone, email) and value. A pattern match adds start and end. A contact the model found adds source: "model".
toxicity, hate_speech, spam and the other model-backed text policieslabel, value (a quote of up to 200 characters) and sometimes a reason
lookalike_characterslabel (mixed_script, invisible), value (the word as written)
wordlist/<slug>label (the list's mode), value (the word that matched), term, canonical, similarity, start, end
duplicatelabel (same_author, other_author), value (the earlier submission's content_id, or null), created_at
instructions, guideline/<slug>label: "evidence", value (a quote), field

validation_errors is present on an invalid moderation and lists what failed. error is present on a failed one.

Your context

authorobject

The author as the decision saw them: id, your external_id, status, trust_level and known. null when the request carried no author_id. The trust level is the one used for this decision, before this moderation was counted. In a 202 body and in list rows the object holds id and external_id only.

content_idstring

Your id for the content, as sent. null when you sent none.

context_idstring

Your grouping key, as sent.

metadataobject

Your own keys and values, as sent.

languagestring

The ISO 639-1 code of the text's language. null for an image and for text too short to tell.

Authors, content ids and metadata shows how to send these and how to search by them.

Accounting and time

usageobject

checks is the number of checks this moderation used. cached is true when every result came from the result cache. A child of a form reports 0: its parent carries the cost.

latency_msinteger

How long the screening run took, in milliseconds, not counting time spent in the queue. null while screening.

dry_runboolean

true when the request or the project asked for a dry run.

testboolean

true when the request used a test key. The field is left out otherwise, so test for its presence.

created_atstring

When the request was accepted, as an ISO 8601 time in UTC.

completed_atstring

When the run ended. null while screening.

Scores are rounded, decisions are not

policies shows two decimals. The decision uses the unrounded score, so a policy shown as 0.7 can sit a hair under a threshold of 0.70 and not trigger.

A policy the template enables that did not run on this content, such as an image policy on a text, is listed with 0. A policy that failed is not listed at all: look for its key in details with an error.

Positions follow the normalised text

start and end in matches, and the whole of masked_output, refer to the text after normalisation: invisible characters removed, lookalike letters folded, whitespace collapsed. They line up with your input only when normalisation changed nothing.

To show a user where the problem is, quote value or show masked_output. Do not cut your original string by start and end.

Rows of the list

GET /v1/moderations returns the same object with three differences. A form comes without fields: fetch it by id to get its children. author holds id and external_id only. details is present for as long as the stored response is kept.

After the retention date

A moderation outlives its content. Past the retention date the scores, the verdict, reasons and validation_errors remain, while metadata becomes null and details loses its quotes: matches, masked_output and explanation are removed and labels stay. On a plan that stores no content this happens within a day. Data retention has the schedule.

In the dashboard

The Live console shows the same object: the verdict card, the score and evidence of each policy, and under Response the JSON your integration received.

A flagged listing description in the live console: the verdict card with the policy scores, the facts of the moderation and the first policy results.
Dashboard, Live consoleOne moderation in the Live console: the verdict card, the facts and what the first policies matched. The response body is further down the same pane.

Next

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