Skip to content

Authors, content ids and metadata

Five optional fields tie a moderation to your own data. They say who wrote the content, which object it is, what it belongs to and whether it is stored.

A moderation is more useful when it knows where the content came from. Five optional fields say so: who wrote it, which object of yours it is, what it belongs to, anything else you want to carry along, and whether the content may be stored. Each works with every template and on every plan, and your ids and metadata come back with the moderation wherever you read it.

curl https://api.useinfrared.com/v1/moderations \
  -H "Authorization: Bearer $INFRARED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",
    "input": "Is the table still available? I could collect it on Saturday morning.",
    "author_id": "user_42",
    "content_id": "message_77120",
    "context_id": "conversation_5531",
    "metadata": {
      "client": "ios",
      "app_version": "4.12.0"
    }
  }'
200 OK, trimmedJSON
{
  "object": "moderation",
  "id": "mod_7JETFVvNC1PmPgQRu9ecxh",
  "status": "completed",
  "flagged": false,
  "recommendation": "allow",
  "author": { "id": "aut_1reK9hfk33nRTsdZpGN25v", "external_id": "user_42", "status": "enabled", "trust_level": "new", "known": true },
  "content_id": "message_77120",
  "context_id": "conversation_5531",
  "metadata": { "client": "ios", "app_version": "4.12.0" }
}
author_idstringOptional

Your id for the person who wrote the content. Up to 200 characters.

content_idstringOptional

Your id for the content itself: the listing, the message, the review. Up to 200 characters.

context_idstringOptional

Your id for what the content belongs to: a conversation, a thread, an order. Up to 200 characters.

metadataobjectOptional

Up to 50 keys of your own. A key has up to 64 characters. A value is a string of up to 1,000 characters, a number, a boolean or null: no nested objects and no lists.

storebooleanOptional

false keeps the content of this moderation out of storage.

Say who wrote it

The first moderation that carries an unknown author_id creates an author in the project, with status enabled and trust level new. From then on the author is addressed by your id, and the author object in each response shows the status and trust level the decision used.

Sending the author does four things:

  • Content rules can read it. A rule can block a suspended author or let a trusted one through. A request without author_id is judged as an enabled author with the lowest trust level.
  • History builds up. Each finished moderation adds to the author's counters, and the trust level follows from them. Moderations sent with a test key, dry runs and invalid submissions do not count.
  • Duplicates are told apart. A repeat by the same author scores lower than the same content posted by somebody else.
  • Reviewers see who it is. The review queue item and the author's page in the dashboard list the moderation.

A template's Require an author id setting is not enforced today: a request without author_id is accepted on such a template too.

Name the content

content_id is your handle on the object. It does not have to be unique: each edit of a listing can be moderated under the same id, and each moderation is kept.

Duplicate detection uses it. Earlier moderations with the same content_id are left out of the comparison, so checking an edited object again is not a duplicate of itself. Without a content_id, the same text sent twice by the same author does count as one, where the template enables the duplicate policy. When a later submission is a duplicate, its details names the content_id of the earlier one.

While the result cache holds the first answer, which is six hours, an identical text sent again to the same template version gets the cached scores of the first run. duplicate therefore stays at 0 for it until the entry expires.

The review queue and the Live console show the id beside the content, and they show it in place of the content when the content was not stored.

context_id ties moderations together: every message of a conversation, every reply in a thread. It is stored, returned and searchable. It does not change scores or decisions, and earlier content with the same context_id is not shown to the models.

Attach your own data

metadata is carried with the moderation and returned wherever the moderation is: in the response, in the list, in webhook events. Policies and rules do not read it and the list cannot be searched by it. It is removed with the rest of the stored content on the moderation's retention date.

Keep the content out of storage

Content is stored when the plan, the project and the template all allow it. store: false turns storage off for one request. It cannot turn it on: store: true on a plan or in a project that stores nothing changes nothing.

A moderation that is not stored keeps no text, no image and no source URL. Its scores, its decision and a hash of the content remain, so the result cache and duplicate detection still work. Three things follow:

  • the dashboard and the review queue show no preview of it,
  • it cannot be re-moderated,
  • what the policies quoted is still kept: details, with its matches and masked text, stays with the moderation until its retention date.

Data retention covers what each plan keeps and for how long.

Find moderations later

GET /v1/moderations lists the project's moderations, newest first, and takes your ids as filters.

curl "https://api.useinfrared.com/v1/moderations?context_id=conversation_5531&limit=50" \
  -H "Authorization: Bearer $INFRARED_KEY"
200 OK, trimmedJSON
{
  "object": "list",
  "data": [
    {
      "object": "moderation",
      "id": "mod_7JETFVvNC1PmPgQRu9ecxh",
      "type": "text",
      "status": "completed",
      "flagged": false,
      "recommendation": "allow",
      "author": { "id": "aut_1reK9hfk33nRTsdZpGN25v", "external_id": "user_42" },
      "content_id": "message_77120",
      "context_id": "conversation_5531"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
FilterMatches
author_id, content_id, context_idThe id you sent, exactly
templateThe slug of the template that ran
statusscreening, completed, partial, failed or invalid
recommendationallow, review or reject
typetext, image or form
languageAn ISO 639-1 code
flagged, dry_runtrue, or an empty value for the opposite
created_from, created_toA UTC time ending in Z, such as 2026-10-01T00:00:00Z

A few things about the list:

  • flagged and dry_run read any value that is not empty as true, the word false included. To list what was not flagged, send the parameter empty, as in flagged=. To get both, leave it out.
  • A date without a time, or a time with an offset, answers 422.
  • The list holds live and test moderations together. The test field tells them apart.
  • A form is one row, without its children. Fetch it by id for the fields.

Pages follow the usual cursor. To read one author's history, GET /v1/authors/{external_id}/moderations returns compact rows for that author alone.

Next

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