Skip to content

Screen private messages before they are delivered

Infrared reads each chat message for threats, scams and links from new accounts, and returns allow, review or reject.

  • One check per message
  • Templates on Starter and up
POST/v1/moderationstemplate: "messages"
Sample data
ConversationWhat the template decided
  1. Buyeruser_17Regular

    Hi, is the camera still available?

    AllowPublished

    Severity triage

    Not flagged

  2. Selleruser_42New

    It is. More photos here: https://t.me/seller

    Screening
  3. Buyeruser_17Regular
    Buyer is typing
    Not sent yet

Sample data

A preset tuned for private chat

The Message preset sets three policies to observe, so they are scored and never decide.

  • Personal dataThe response carries a masked copy of the message. A phone number or email still counts under Links & contact details.

  • Meaningless textShort or playful messages are normal in a chat.

  • Duplicate contentScored for the same sender's repeats within a day.

Message preset
Preset as shippedpreset: "message"

Fields ยท 1

FieldTypeRuleValidationTriggers
MessagebodyTextRequired1 to 5,000 charactersTemplate triggers

Policies ยท 13

Flag7The message becomes FLAGGED.
Hate speechToxicityViolenceSexual contentIllicit & regulated goodsSwear wordsSelf-harm
Review3Adds a review signal without flagging.
Spam & advertisingLinks & contact detailsLookalike characters
Observe3Scored and returned, never affects the verdict.
Personal dataMeaningless textDuplicate content

Rules ยท 2

  1. 01Threats are rejectedif Violence is at least 0.80Reject
  2. 02Links from new accountsif trust level is at most new and Links & contact details is flaggedReview

When no rule matches, severity triage decides: review from 0.40, reject from 0.80. A link from an account above New matches no rule, so triage rejects it.

Preset as shipped

The AI instructions name the scams

Each message is checked against the preset's AI instructions, and the result is a score, a quote and an explanation.

AI instructions
Sample data
Flag scams and fraud: requests for money, gift cards, crypto or prepayment; fake payment or delivery confirmations; requests for login codes, passwords or card details; impersonation of platform staff. Flag unsolicited sexual content and any attempt to groom or exploit a minor.
From the Message preset, word for word

I can hold it for you until Friday. Send half now as a gift card code and I will ship the same day.

AI instructionsTriggered0.88
"Send half now as a gift card code"

The sender asks for prepayment as a gift card code before shipping.

FlaggedSeverity triageRejectedReject

Payment sent, see the receipt. My bank holds it for three days, so please ship today.

AI instructionsTriggered0.74
"My bank holds it for three days"

The sender claims a payment that cannot be checked and presses for shipping.

FlaggedSeverity triageSent to reviewReview

You will get a six digit code by text in a minute. Read it to me so I can confirm the order.

AI instructionsTriggered0.91
"Read it to me"

The sender asks for a login code that was sent to the other member.

FlaggedSeverity triageRejectedReject

This is tradely support. Your payout is on hold until you confirm your card details in this chat.

AI instructionsTriggered0.95
"confirm your card details"

The sender poses as platform staff and asks for card details.

FlaggedSeverity triageRejectedReject

Sample data

The answer comes back in the same request

Your send handler can wait for the complete result before anything reaches the other member.

recommendation
allow, review or reject.
rule
The content rule that decided, or null when severity triage did.
send-message.jsJavaScript
export async function sendMessage(message) {
  const res = await fetch("https://api.useinfrared.com/v1/moderations", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.INFRARED_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      template: "messages",
      type: "text",
      input: message.body,
      author_id: message.senderId,
    }),
  });
  if (!res.ok) {
    throw new Error(`${res.status}`);
  }
  const mod = await res.json();

  switch (mod.recommendation) {
    case "allow":
      return deliver(message);
    case "review":
      return hold(message, mod.rule);
    default:
      return refuse(message, mod.rule);
  }
}

Block the sender after a threat

One request runs the built-in Block author action. The Message preset has no rule on author status, so add one at the top and the sender's next message is rejected.

After a rejected threat
Sample data
  1. POSTmoderation.completedWebhookThe rejected threat, with the rule that decided
  2. POST/v1/actions/block_author/executeYour requestYour server blocks the sender, user_17
  3. POSTauthor.blockedWebhookuser_17 went from enabled to blocked
  4. POSTaction.executedWebhookThe action, as it was logged
author.blocked, trimmedJSON
{
  "type": "author.blocked",
  "api_version": "2026-09-01",
  "data": {
    "author": {
      "external_id": "user_17",
      "status": "blocked",
      "trust_level": "new"
    },
    "previous_status": "enabled",
    "reason": "threats",
    "source": "api"
  }
}

Sample data

Start moderating your users' content

Create an API key, send your first request and get a verdict back.