Error reference

test_mode_required

HTTP 403 retryable: false REST and MCP

The endpoint only exists for test projects, and the project or inbox you aimed it at is a live one.

Why it happens

Inbound simulation injects a message directly into a mailbox without it crossing a transport. Allowing that against a live inbox would mean live mail history could contain messages nobody sent, so the check runs twice: once on the project's environment and again on the specific inbox's environment, inside the same transaction that would write the message. The second check matters because a project and an inbox are separately recorded, and only the inbox row proves where the message would actually land.

Every condition below was read in the implementation at the file and line given. They are the branches that raise this code, not a summary of what the name suggests.

How to fix it

  1. Create a test project and a test inbox, then aim the simulation at those. Up to three active test inboxes are allowed per workspace.
  2. Check the key prefix. An efa_test_ key resolves only to test projects and test inboxes, so if your key is efa_live_ you are pointed at the wrong environment entirely.
  3. Do not look for a flag that relaxes this. Environment is carried in the key prefix and cannot be crossed, and a project's environment cannot be converted after creation.
  4. To exercise a live inbox end to end, send real mail to its address on agents.emailforagents.ai instead of simulating.

Why it works this way

There is no promotion path from a test project to a live one. That is a deliberate constraint rather than a missing feature: it keeps the environment of every message decidable from the row it is stored in, which is what lets a single check at the inbox level be trustworthy.

Messages you will see

The message field is written for a human reading a log and is not a contract value. Branch on code instead. These are the exact strings this code is sent with today, listed so that a search for one of them lands here.

Where it appears

These are the documented surfaces that raise it. The REST base is https://api.emailforagents.ai/v1, and the remote MCP endpoint is https://mcp.emailforagents.ai/mcp.

The response

Read request_id off the body or the x-request-id header before doing anything else. It is the only handle on one specific attempt, and for a 503 it is the only handle at all, because the underlying detail stays server-side.

HTTP/1.1 403
content-type: application/json
x-request-id: req_...

{
  "error": {
    "code": "test_mode_required",
    "message": "Simulation endpoints only work on test projects.",
    "request_id": "req_...",
    "retryable": false
  }
}

Verified against packages/domain/src/services.ts:2123. The status comes from ERROR_STATUS in packages/contracts/src/errors.ts, which is the one place a code is mapped to a status.

All error codes · Documentation · Quickstart