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"- Buyer
user_17RegularHi, is the camera still available?
AllowPublishedSeverity triage
Not flagged
- Seller
user_42NewIt is. More photos here: https://t.me/seller
Screening - Buyer
user_17RegularBuyer is typingNot 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.
preset: "message"Fields ยท 1
bodyTextRequired1 to 5,000 charactersTemplate triggersPolicies ยท 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
- 01Threats are rejectedif Violence is at least 0.80Reject
- 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.
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.
I can hold it for you until Friday. Send half now as a gift card code and I will ship the same day.
The sender asks for prepayment as a gift card code before shipping.
Payment sent, see the receipt. My bank holds it for three days, so please ship today.
The sender claims a payment that cannot be checked and presses for shipping.
You will get a six digit code by text in a minute. Read it to me so I can confirm the order.
The sender asks for a login code that was sent to the other member.
This is tradely support. Your payout is on hold until you confirm your card details in this chat.
The sender poses as platform staff and asks for card details.
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.
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.
- POSTmoderation.completedWebhookThe rejected threat, with the rule that decided
- POST/v1/actions/block_author/executeYour requestYour server blocks the sender, user_17
- POSTauthor.blockedWebhookuser_17 went from enabled to blocked
- POSTaction.executedWebhookThe action, as it was logged
{
"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.