Dry run and re-moderation
Run your rules on real traffic without enforcing them, and run stored content again after a template changes. What each one records and what it costs.
Two tools help when your rules change. A dry run screens real content and records everything, while telling your platform not to act on the result. It is how you watch a new template on live traffic before it decides anything. Re-moderation runs content Infrared already holds once more, against the template as it is now. It is how a change reaches what was already posted.
Dry run one request
Send dry_run: true.
curl https://api.useinfrared.com/v1/moderations \
-H "Authorization: Bearer $INFRARED_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "text",
"input": "Worst seller ever. You are a complete idiot.",
"author_id": "user_42",
"dry_run": true
}'const response = await fetch("https://api.useinfrared.com/v1/moderations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.INFRARED_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
type: "text",
input: "Worst seller ever. You are a complete idiot.",
author_id: "user_42",
dry_run: true,
}),
});
const moderation = await response.json();import os
import requests
response = requests.post(
"https://api.useinfrared.com/v1/moderations",
headers={"Authorization": f"Bearer {os.environ['INFRARED_KEY']}"},
json={
"type": "text",
"input": "Worst seller ever. You are a complete idiot.",
"author_id": "user_42",
"dry_run": True,
},
)
moderation = response.json(){
"object": "moderation",
"id": "mod_4QbdMYt4bEakebt8ax1yaE",
"status": "completed",
"flagged": true,
"recommendation": "reject",
"triggered": ["toxicity"],
"reasons": ["trigger:toxicity:flag", "triage:reject"],
"dry_run": true
}The response is the ordinary one, with dry_run set. Your code reads that flag and does not enforce the recommendation: it publishes as it would have, and you compare what Infrared would have done.
Dry run a whole project
Open Settings, Project and turn on Dry run under Storage and enforcement. From then on every moderation of the project is a dry run. A request cannot switch it off: dry_run: false is ignored while the project's switch is on.
The dashboard marks the project and every moderation and queue item made this way with Dry run, so nobody mistakes them for enforced decisions.
What a dry run does and does not do
A dry run is a full moderation. It still:
- uses checks, exactly as the same request would without the flag,
- creates a review queue item when the recommendation is
review, with the reason Dry run. Anallowor arejectcreates none, as on enforced traffic, - sends the
moderation.completedwebhook event, withdry_run: truein the moderation, - shows in the Live console and counts in usage,
- counts as earlier content when a later submission is checked for duplicates.
One thing is left alone: the author's history. A dry run adds nothing to the author's counters and does not move their trust level, so a rule you are still tuning cannot demote anyone.
Re-moderate stored content
Call remoderate on a moderation to run its stored content again. The request takes no body.
curl -X POST https://api.useinfrared.com/v1/moderations/mod_0X7lqCg6kqvuRBCfKEPXxa/remoderate \
-H "Authorization: Bearer $INFRARED_KEY"const response = await fetch("https://api.useinfrared.com/v1/moderations/mod_0X7lqCg6kqvuRBCfKEPXxa/remoderate", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.INFRARED_KEY}` },
});
const moderation = await response.json();import os
import requests
response = requests.post(
"https://api.useinfrared.com/v1/moderations/mod_0X7lqCg6kqvuRBCfKEPXxa/remoderate",
headers={"Authorization": f"Bearer {os.environ['INFRARED_KEY']}"},
)
moderation = response.json(){
"object": "moderation",
"id": "mod_01qsbB3LTXRzoZQh7DDEYL",
"template": { "slug": "basic", "version": 1 },
"type": "text",
"status": "completed",
"flagged": false,
"recommendation": "allow",
"usage": { "checks": 0, "cached": true }, // a test key, and scores from the result cache
"metadata": { "remoderated_from": "mod_0X7lqCg6kqvuRBCfKEPXxa" }
}The answer is a new moderation with its own id. The original stays as it was. The new one runs on the version of the template that is published now, and its metadata gains remoderated_from with the id of the original.
It carries over the template, the content, field, content_id, author_id, context_id, metadata and the dry-run flag of the original. It does not carry over mode, store or client_action, so text is answered in the same response and images answer 202.
In every other way it is an ordinary moderation: it uses checks, can enter the review queue, sends its webhook event and counts in the author's history. Called with a test key it is a test moderation, whatever the original was. The Re-moderate button on a moderation in the Live console does the same and uses checks.
What cannot be re-moderated
- Content that was not stored. The request answers 409
input_not_storedwhen the original was sent withstore: false, when the project, the template or the plan stores no content, and after the moderation's retention date. - One field of a form. A child answers 409
is_child. Re-moderate the parent.
Three more things to expect:
- Re-moderating a form rebuilds it from its content fields. Number, boolean, enum, URL and JSON values are not sent again, so a form with a required field of one of those types comes back
invalid, and content rules that test such a field see no value. - Within six hours, on an unchanged template version, the scores come from the result cache and do not change.
- The call does not honour
Idempotency-Key. Two calls make two moderations.
Choose the right tool
Dry run is one of three ways to run content without consequences for your users, and they record different things.
| Dry run | Test key | Template test | |
|---|---|---|---|
| Creates a moderation with an id | Yes | Yes | No |
| Uses checks | Yes | No | No |
Fills the review queue on review | Yes | Yes | No |
| Sends webhook events | Yes | Yes | No |
| Updates the author's history | No | No | No |
| Marked in the response by | dry_run: true | test: true | test: true and id: null |
Use a test key while you build the integration, the template test while you edit a template, and a dry run when the template is ready and you want to see it on real traffic first. To replay the last seven days against a draft without calling a model, use simulation.
Next
- Test modeA test key runs the whole pipeline and uses no checks. It is not a sandbox: its moderations still reach the review queue and your webhooks.
- SimulationReplay the last seven days of a template's decisions against its draft and count what would change before you publish. Nothing is charged.
- Review queueContent your rules send to review waits in the queue until a person, or your own code, allows it, rejects it or runs another action on it.
- Content rulesOrdered rules on a template turn scores, author trust and field values into allow, review or reject. Severity triage decides when no rule matches.
Something missing or unclear on this page? Write to support@useinfrared.com.