sent without any provider hearing of it, and counted against nothing. Sent to one of the sink addresses, it also gets the answer a provider would have given, with the webhooks that go with it.
Create a test key
Settings → API tokens → New token, then switch on Test key before Create. The list shows it with a Test badge. A key is a test key from birth and stays one: to go live, create a live key and swap it in your configuration. Your application can ask which one it holds:What a test key changes
In the log, Transactional, a test e-mail carries a Test badge.
GET /v1/transactional-mails?sandbox=true lists only those, ?sandbox=false only the real ones.
The sink addresses
Write to these addresses to get a provider’s answer without one. The part after+ is free: bounced+signup-form@sink.lekalao.dev is a bounce too, so that several tests can be told apart.
The webhooks are the real ones, signed, retried and logged like any other, with
"sandbox": true in their data. A simulated bounce or complaint puts nothing on the suppression list: the same test runs again tomorrow.
Any other address is logged and marked sent, and nothing more happens to it.
An e-mail written only to sink addresses never reaches a provider,
whatever the key: it would bounce off a domain that receives nothing, at
the expense of your sender’s name. Mixed with real addresses, with a live
key, it is sent like any other.
Try it from a terminal
No collection to import, no account elsewhere:curl and a test key are enough.
1
A test key
Create one as above, then:
2
An endpoint for the webhooks
Your application’s, reachable from the internet; on your machine, through a tunnel such as ngrok or Cloudflare Tunnel. Register it for the transactional events, and keep the Skip this step to see the calls only in Settings → Outgoing webhooks: the log shows what would have been sent, and its answer.
secret of the answer:3
An e-mail that bounces
201, "status": "sent", "sandbox": true. Keep its id.4
What your application received
transactional.sent, then transactional.bounced with "type": "hard_bounce" and the address. Check each signature as Webhooks shows: a handler that refuses a forged call is part of the test.Read the e-mail again: bounced_at is set.5
The other answers
The same call to
delivered@, complained@, opened@, clicked@ and failed@sink.lekalao.dev: each of your handlers runs once. Then swap the test key for a live one.GET /v1/openapi.json (?lang=fr for the French one). It is the same document as the API reference.