Three API calls. One template ID that has to carry through all of them.
Resend's API for sending a templated email is three steps:
- Create a template
- Publish the template
- Send an email using that template
Each step depends on the one before it.
The template ID from step 1 has to be passed into step 2. The published status from step 2 has to be confirmed before step 3 will actually send. And if you want to verify your integration end to end, you need the template.created webhook to fire after step 1.
That is a simple flow. But most developers do not actually test it as a flow.
How most people test this
The typical approach:
- Create a template in the Resend dashboard manually
- Copy the template ID into your code
- Call the send endpoint with that hardcoded ID
- Check your inbox
That tests one thing: can your code call POST /emails with a valid template ID?
It does not test:
- Whether your code correctly creates templates via the API
- Whether the publish step returns the right status
- Whether the template ID chains correctly from creation to sending
- Whether the template.created webhook fires and your handler processes it
- Whether the whole flow works when run programmatically, not manually
Hardcoding a template ID is not integration testing. It is calling one endpoint with a known parameter.
What the real flow looks like
POST /templates
→ 200: { id: "tpl_abc123", object: "template" }
→ webhook: template.created fires
POST /templates/tpl_abc123/publish
→ 200: { id: "tpl_abc123", status: "published" }
→ webhook: template.published fires
POST /emails
→ 200: { id: "email_xyz789" }
body: { template_id: "tpl_abc123", to: "user@example.com" }
Three calls. Two webhooks. The template ID threads through every step.
The question you should be able to answer before shipping is not "does POST /emails work?" It is "does my entire template-to-send pipeline work when the template is created, published, and referenced programmatically?"
The webhook part
Most email integrations skip webhook verification entirely.
That is understandable. For a simple "send one email" integration, you might not need webhooks at all.
But once you are building a system that creates templates dynamically — onboarding flows, transactional sequences, marketing automation — you probably want to know when a template was created and when it was published.
template.created tells your system the template exists. template.published tells your system it is safe to reference in send calls.
If your code sends an email with a template that has not finished publishing, you get a confusing error that looks like a bad template ID. The actual issue is a timing problem in your flow.
Testing the webhooks is how you catch this before production.
The testing setup problem
To test this flow against real Resend, you need:
- A Resend API key
- A verified sender domain
- A real email address to receive the test send
- A webhook endpoint reachable from the internet
That is reasonable for a production integration test.
It is less reasonable for the Tuesday afternoon when you just want to know if your template creation flow works before you wire it into your app.
Running it without any of that
I built a sandbox where you can run this exact flow without a Resend API key, without a verified domain, and without hosting a webhook endpoint.
You call POST /templates. The sandbox creates a template and returns a real ID. You call POST /templates/{id}/publish. The status updates. You call POST /emails with that template ID. The send succeeds. The webhooks fire automatically between steps.
The state persists. The IDs chain. The whole flow runs in about 30 seconds.
Try the Resend template workflow
Why this matters for email integrations specifically
Email is one of those integrations where "it worked in testing" and "it works in production" can be very different things.
Templates get created but not published. Send calls reference stale template IDs. Webhook handlers assume the template exists before the creation event arrives.
These are not exotic edge cases. They are the normal bugs that happen when you test endpoints in isolation instead of testing the flow.
The fix is not complicated. Run the whole chain once, in order, with state that carries between steps. If the template ID from step 1 appears correctly in step 3, your integration probably works. If it does not, you want to find out now, not when your onboarding emails start failing.
That is what FetchSandbox does. Turns any OpenAPI spec into a stateful sandbox with workflows.
Curious how other people handle email integration testing. Do you test against real Resend with test keys, use a mock, or mostly just trust the dashboard and check your inbox?
Top comments (0)