Test mode
Simulate deliveries, bounces, and complaints without touching real email.
Test mode lets you exercise the full pipeline — validation, suppression checks, events, webhooks — without ever calling SES. Nothing is queued for real delivery, and no email leaves the building.
Enabling test mode
Either send the header:
-H "X-Relay-Test: true"or set the body field:
{ "test_mode": true }Both have the same effect on POST /v1/email and POST /v1/email/batch.
Simulating outcomes
Recipient local-parts at relay.dev decide what happens (case-insensitive;
+labels such as delivered+ci@relay.dev are stripped first). Any other
address defaults to delivered:
| Recipient | Result |
|---|---|
delivered@relay.dev | sent + delivery event |
bounced@relay.dev | failed + bounce event + auto-suppression |
complained@relay.dev | sent + complaint event + auto-suppression |
| anything else in test mode | sent + delivery event |
curl https://api.emitd.com/v1/email \
-H "Authorization: Bearer $EMITD_API_KEY" \
-H "X-Relay-Test: true" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@yourdomain.com",
"to": ["bounced@relay.dev"],
"subject": "Simulate a bounce",
"html_body": "<p>Oops</p>"
}'Inspecting results
Simulated events are recorded like real ones and readable at
GET /v1/email/test-events (paginated with ?limit= / ?cursor=), joined
against messages flagged test_mode = 1. Your webhook endpoints fire too —
signatures verify exactly as they do in production, so end-to-end webhook
handling can be tested in CI.
Same pipeline, no delivery
Test-mode sends run the full path — validation, suppression checks, quota, and rate limits all apply exactly as in production. What's skipped is the SES call and the send queue. Treat a test send as a real send minus the delivery.