Skip to content

Templates

A template is the configuration for one kind of content. It holds the fields, the policies and the rules, and requests name it by its slug.

A listing, a review and a chat message are not judged alike. A phone number is expected in one and a violation in another, and only a listing has a price to check against its description. A template holds those choices for one kind of content, and each request names the template it is judged by: "template": "listing".

You create and edit templates in the dashboard, under Templates. The API reads them and tests them. No endpoint creates or changes one.

Read a template to see what its requests are held to.

curl https://api.useinfrared.com/v1/templates/listing \
  -H "Authorization: Bearer $INFRARED_KEY"
200 OK, trimmedJSON
{
  "object": "template",
  "id": "tpl_64mYq4nD3NXNfu0gcdaMZa",
  "slug": "listing",
  "name": "Listing",
  "description": null,
  "status": "active",
  "built_in": false,
  "version": 2,
  "context": "A public listing on a marketplace: an item, a service, a property or a vehicle for sale or rent, with a price and photos of what is offered. Buyers contact the seller through the platform.",
  "fields": [
    {
      "key": "title",
      "name": "Title",
      "type": "text",
      "required": true,
      "triggers": [
        { "effect": "flag", "policy": "hate_speech" },
        { "effect": "flag", "policy": "links_contact" }
      ],
      "validation": { "max_length": 120, "min_length": 5 },
      "description": "Short headline naming what is offered."
    } // description, price and photos follow
  ],
  "policies": [
    { "key": "toxicity", "mode": "trigger" },
    { "key": "links_contact", "mode": "trigger", "options": { "off_platform_phrases": true } },
    { "key": "gibberish", "mode": "trigger", "effect": "review" },
    { "key": "made_with_ai", "mode": "trigger", "effect": "review", "threshold": 0.9 },
    { "key": "guideline/no-off-site-deals", "mode": "trigger" } // 14 more
  ],
  "triggers": [
    { "effect": "flag", "policy": "hate_speech" },
    { "effect": "review", "policy": "duplicate" } // 5 more
  ],
  "rules": [
    {
      "id": "r6",
      "name": "Links from new accounts",
      "action": "review",
      "enabled": true,
      "conditions": [
        { "op": "at_most", "type": "author_trust", "value": "new" },
        { "type": "policy_flagged", "value": true, "policy": "links_contact" }
      ]
    } // r1 to r5 come first
  ],
  "severity": { "reject": 0.8, "review": 0.4 },
  "ai_instructions": "Check that the title, description, price and photos describe the same offer, ...", // trimmed
  "settings": {},
  "created_at": "2026-10-08T08:44:31.624Z",
  "updated_at": "2026-10-08T09:28:01.454Z"
}

The response is the published version of the template. Each part of it is a tab of the editor in the dashboard.

What a template holds
Sample data

Listinglistingv2The published version

Fieldschecked first, with no model

  • titleText, required5 to 120 charactersTriggers: hate_speechlinks_contact
  • descriptionText, requiredup to 5,000 charactersTriggers: profanitytoxicity
  • priceNumber, optionalat least 0validated only
  • photosImage, optionalup to 10 filesTrigger: made_with_aiat 0.90, review

Policiesscore the content19 on

  • toxicityTrigger0.70flag
  • links_contactTriggerany matchflag
  • gibberishTrigger0.70review
  • made_with_aiTrigger0.90review
  • guideline/no-off-site-dealsTrigger0.70flag
  • 14 more

AI instructionsjudged once, across all fields

Check that the title, description, price and photos describe the same offer …

instructionsflags from 0.70

Content rulesthe first match decides

  1. Block banned authorsReject
  2. Zero tolerance for hateReject
  3. Illicit goodsReject
  4. No sexual contentReject
  5. Allow established authorsAllow
  6. Links from new accountsReview

Severity triagewhen no rule matches

0.400.80AllowReviewReject

Sample data

The parts of one template, in the order a submission meets them.

What a template holds

In the responseTab in the editorWhat it sets
fieldsFieldsThe parts of a submission, each with a type, a rule, validation and its own triggers. See Fields and validation.
policiesPoliciesWhich policies score the content, and each one's mode, threshold, effect, weight and options.
triggersPoliciesWhat a score sets off for the whole template. See Triggers.
rules, severityRulesContent rules, where the first match decides, and the two thresholds of severity triage.
context, ai_instructionsInstructionsWhat this content is, and plain-language AI instructions judged across all fields.
settingsInstructionsThe run settings: a review deadline, a language hint, storage and cache.
versionHistoryThe number of the published version. See Versions, testing and diff.

The Test tab holds no configuration. It runs a sample through the template and shows the verdict and the JSON your integration would receive.

The templates of a project: the built-in basic check first, then Listing, which is active and has a draft, Review, which is active, and Comment, a draft.
Dashboard, TemplatesThe templates of a project, with the built-in basic check first. Choosing one opens its editor beside the list.

Create a template

  1. Name it

    Open Templates and choose New. Give the template the name of the content it moderates: Listings, Reviews, Messages. The slug your requests use is generated from that name.

  2. Pick a starting point

    Under Start from, choose one of the eight presets or Blank template. A preset fills in fields, policies, triggers and rules for that kind of content. Listing is selected until you choose another. Then choose Create template.

    The New template drawer: a name, a description and the list of presets to start from, ending with a blank template.
    Dashboard, TemplatesA new template starts from a preset or from nothing.
  3. Shape it, test it, publish it

    The editor opens on a draft, and nothing runs yet: a request that names the template answers 409 template_not_published. Adjust the tabs, try a sample in Test, then choose Publish version. From then on every edit goes to a new draft and waits for the next publication, as Versions, testing and diff describes.

The slug

  • It is generated from the name when the template is created: lowercase letters, digits and hyphens, 2 to 80 characters. "Job postings" becomes job-postings.
  • It is unique in the project. A slug that is taken gets a number: listing-2. An archived template keeps its slug, and basic belongs to the basic check.
  • It never changes. Rename, in the More menu beside the editor's buttons, changes the name and the description only, so requests keep working.
  • You cannot type or edit a slug. Create the template under the name that gives the slug you want, then rename it.

Draft, active, archived

StatusMeansA request that names it
DraftCreated, never published.Answers 409 template_not_published.
ActiveHas a published version.Runs the published version.
ArchivedTaken out of use. Nothing is deleted.Answers 404 template_not_found.

Editing an active template does not change its status. The edits wait in a draft, marked with a second Draft badge in the list, and requests keep running the published version.

A template cannot be deleted. Archive template, in the More menu, takes it out of use and keeps every version. Switch on Show archived above the list to see it again, and choose Restore template to put it back to work.

Which template a request runs

  1. The template the request names.
  2. With no template, the project's default template.
  3. With no default, the basic check.

The default is set in Settings, Project, under Default template. The list there also offers templates that were never published: with one of those as the default, every request that names no template answers 409 template_not_published. A default that is archived later is skipped without an error, and those requests run the basic check.

A named template is never swapped for another one. When it cannot run, the request fails.

StatuscodeWhen
404template_not_foundNo template of the project has this slug, or it is archived.
409template_not_publishedThe template exists and has no published version.
403plan_limitThe plan does not include templates. Every name except basic answers this, whether or not the template exists.

A request that names listings in a project whose template is listing:

404 Not FoundJSON
{
  "error": {
    "code": "template_not_found",
    "message": "Template listings not found",
    "details": [],
    "request_id": "req_cc04a628577f4e5a92c4f8b683c73b6b"
  }
}

Every moderation says which template and version judged it, in template: { "slug": "listing", "version": 2 }.

Templates over the API

EndpointKey scopeReturns
GET /v1/templatesreadEvery template of the project: the basic check first, then yours from oldest to newest.
GET /v1/templates/{slug}readOne template with its published configuration.
POST /v1/templates/{slug}/testmoderateThe moderation of a sample, with nothing stored or charged.

Three things to know when you read templates:

  • The list is not paginated. limit and cursor are accepted, and every template still comes back in one response. Archived templates are left out unless you ask with status=archived.
  • GET /v1/templates/{slug} returns an archived template too, with "status": "archived".
  • A template that was never published comes back with "version": null and none of the configuration keys. The API never returns a draft.

Plans and roles

LimitFreeStarterGrowthBusiness
Templates, per projectNot included520100

The limit counts the templates of one project that are not archived. The basic check is not counted.

Owners, Admins, Project admins and Developers can create, edit, publish and archive templates. A Moderator can open them and sees Read only. Choosing the default template takes an Owner, an Admin or a Project admin. Members and roles has the full table.

Next

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