Skip to content

Test mode

A 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.

A test key lets you build and run your integration against the real pipeline without spending checks. Use it in development, in CI and on staging, and switch to a live key when real users' content starts to flow.

Test mode is a property of the key, not a separate environment. A test key works on the same project, the same templates and the same data as a live key. Create one in Settings, API keys by picking Test as the environment.

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."
  }'
200 OK, trimmedJSON
{
  "object": "moderation",
  "id": "mod_4Vy9b9w1MRrTGXH5RXlSnO",
  "template": { "slug": "basic", "version": 1 },
  "status": "completed",
  "flagged": true,
  "recommendation": "reject",
  "usage": { "checks": 0, "cached": false },
  "dry_run": false,
  "test": true,
  "created_at": "2026-10-08T08:46:24.485Z",
  "completed_at": "2026-10-08T08:46:26.682Z"
}

The verdict is real. Two fields say it came from a test key: usage.checks is 0, and test is true. A moderation made with a live key has no test field at all.

A test key and a live key
The same requestPOST /v1/moderationsSame project, same templates, same data.
The moderation
Test keyir_test_…
Live keyir_live_…
Runs the whole pipeline
Yes
Yes
Uses checks
Nousage.checks: 0
Yesusage.checks: 1
Counted in usage
Under Test
Under Live, and in GET /v1/usage
Updates author history
No
Yes
Enters the review queue on review
Yes
Yes
Fires webhooks
Yes
Yes
Marked in the response
Yes"test": true
NoNo test field
The same request with a test key and with a live key: what each one does.

What a test key changes

  • No checks. A test moderation costs nothing and is never refused with 402 quota_exceeded.
  • Usage is counted apart. Test traffic has its own view on the Usage page and is left out of GET /v1/usage.
  • No author history. A test moderation does not move the author's counters or trust level. The author's current status and trust still feed the decision, and an author_id the project has not seen still creates the author.
  • Not a duplicate. The duplicate policy does not count test moderations as earlier copies, and a simulation leaves them out.

What stays the same

  • The review queue. A test moderation whose recommendation is review goes into the review queue like any other.
  • Webhooks. moderation.completed and the queue events are sent to your webhook endpoints.
  • Storage. Test content is stored and removed on the same terms as live content. See Data retention and privacy.
  • The plan. A named template on the Free plan is still refused, and the batch size still applies.
  • The rate limit. A test key gets the plan's requests a minute, the same as a live key.
  • Scopes. They work the same on both kinds of key.

Tell test traffic apart

  • In a webhook, read data.moderation.test. A queue_item.created event carries no flag of its own: look the moderation up by its moderation_id.
  • In the API, GET /v1/moderations returns test and live moderations together, and each test one carries test: true.
  • In the dashboard, the Live console labels test rows and has a Test switch that hides them. The Usage page switches between Live and Test.

The Overview shows live traffic only. A first request made with a test key appears in the Live console and not on the Overview, and the second step of the setup checklist there stays open until a live request arrives.

The test console

To try a template and leave nothing behind, use the test console: the Test tab of a template in the dashboard, or this endpoint. It runs every stage and then stores nothing. No moderation, no queue item, no webhook, no usage and no author are created.

curl https://api.useinfrared.com/v1/templates/basic/test \
  -H "Authorization: Bearer $INFRARED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",
    "input": "Worst seller ever. You are a complete idiot."
  }'
200 OK, trimmedJSON
{
  "object": "moderation",
  "id": null,
  "template": { "slug": "basic", "version": 1 },
  "status": "completed",
  "flagged": true,
  "recommendation": "reject",
  "usage": { "checks": 0, "estimated": 1, "cached": false },
  "dry_run": false,
  "test": true
}
  • id is null, because nothing was saved.
  • usage.estimated is what the same request would cost with a live key.
  • Add "draft": true to the body to run a template's unpublished draft instead of its published version.
  • The answer always comes with the request, images included.
  • The console works with a live key too, needs the moderate scope and counts toward the key's rate limit.
  • A test of a whole form differs from a real form in two more ways, listed under How the answer differs from a moderation.
The Test tab of a template: a sample description on the left, and on the right the verdict card and the JSON response of the test.
Dashboard, TemplatesThe Test tab of a template: a sample on the left, the verdict and the JSON on the right.

Test keys on the Free plan

The Free plan has one key in total, so it holds a test key or a live key, never both. Start with a test key. When you go live, revoke it and create a live one.

Next

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