Sendara gives you two ways to test. The sandbox uses a test key to simulate every outcome — delivered, bounced, complained — without sending real mail or being billed, while still firing your webhooks. Verified test recipients go one step further: they send real email to a handful of your own addresses, for free, so you can validate production against a real verified domain before launch.
Test keys
Every account has live and test API keys. A test key (sk_test_…) runs the full pipeline — idempotency, suppression, templates, events, webhooks — but stops short of handing the message to a real provider. Nothing is sent and nothing is billed. Live keys (sk_live_…) send real mail and are billed.
Swapping a single environment variable from sk_test_… to sk_live_… is all it takes to go from sandbox to production — the request shape is identical.
Simulated outcomes
In the sandbox, the recipient address drives the simulated outcome — specifically the local-part (the bit before the @), so the domain can be anything. Send to bounced@ to drive a bounce, complained@ to drive a complaint, or anything else to get a clean delivery.
| Recipient local-part | Final status | Events fired |
|---|---|---|
delivered@ | delivered | accepted → delivered |
bounced@ / bounce@ | bounced | bounced (recipient suppressed) |
complained@ / complaint@ | complained | complained (recipient suppressed) |
anything else | delivered | accepted → delivered |
The example below drives a simulated bounce. Swap the local-part to steer the outcome — the rest of the request stays the same.
bounced or complained outcome suppresses that recipient on the account, exactly as in production. If a later send to the same address returns recipient_suppressed(409), that's expected — remove the suppression to send again.Webhooks in the sandbox
Sandbox sends fire the same webhook events as production, so you can test your handler against a real signed payload. Each event is delivered as a POST with a JSON body and these headers:
Sendara-Event-Id— unique per event; reused across retries of the same event, so use it to dedupe.Sendara-Event-Type— e.g.delivered,bounced,complained.Sendara-Timestamp— Unix epoch seconds when the signature was computed.Sendara-Signature— the HMAC signature (see below).
{
"id": "ev_2",
"type": "delivered",
"message_id": "msg_a1b2c3",
"channel": "email",
"occurred_at": "2026-06-14T10:00:12Z"
}Verifying the signature
Verify every webhook before trusting it. The signature is HMAC-SHA256(secret, "{timestamp}.{raw_body}"), hex-encoded. Build the signed string by concatenating the Sendara-Timestamp header, a literal ., and the exact raw request body — then compare in constant time.
Treat handlers as idempotent — an event may be delivered more than once, and retries reuse the same Sendara-Event-Id. Failed deliveries are retried with backoff. Respond 2xx to acknowledge.
Verified test recipients
The sandbox simulates; it never puts a real email in a real inbox. When you need to confirm rendering, deliverability, and your verified domain in production — without spending money or risking your live list — register verified test recipients. These are your own addresses, verified by email, that you can send real mail to for free.
The guardrails:
- Up to 3 test recipients per account.
- Each verified address accepts at most 10 test sends per day (per UTC day).
- Sends use a live key with
test_send: trueand are never billed.
Register & verify
Register an address with POST /v1/test-recipients (requires the admin scope). Sendara emails that address a verification link; once the recipient clicks it, the address flips to verified and is eligible for test sends.
curl https://api.sendara.dev/v1/test-recipients \
-H "Authorization: Bearer sk_live_admin_xxx" \
-H "Content-Type: application/json" \
-d '{ "email": "you@yourcompany.com" }'{
"id": "tr_4f1a8c2d9e",
"email": "you@yourcompany.com",
"status": "pending",
"created_at": "2026-06-14T10:00:00Z"
}List your recipients with GET /v1/test-recipients (requires read) to check verification status. You can re-send the verification email with POST /v1/test-recipients/{id}/resend, or remove an address with DELETE /v1/test-recipients/{id} (both require admin).
{
"recipients": [
{ "id": "tr_4f1a8c2d9e", "email": "you@yourcompany.com",
"status": "verified", "verified_at": "2026-06-14T10:02:30Z",
"created_at": "2026-06-14T10:00:00Z" }
]
}Sending a real test email
Once an address is verified, send to it with a normal POST /v1/send using a live key and test_send: true. The destination must be a verified test recipient on your account, the per-day cap applies, and — because the send is free — the spend cap is skipped entirely.
Errors
Two error codes are specific to this flow:
recipient_not_verified(403) — the destination isn't a verified test recipient on your account. Register and verify it first, or droptest_sendto send normally.test_send_daily_limit(429) — this address has used its 10 free test sends for the current UTC day. Wait for the next day or use a different verified address.
Registering a fourth address returns too_many_test_recipients (422) — delete one first.
From sandbox to production
A reliable path to your first real production send:
- Build against
sk_test_…and drivedelivered@,bounced@, andcomplained@to exercise every branch and your webhook handler. - Verify your sending domain (see Domains & deliverability).
- Register a verified test recipient and send a real
test_send: trueemail to confirm rendering and inbox placement on your verified domain — for free. - Swap to
sk_live_…and ship.