Switch
Move over in an afternoon.
Same concepts, mechanical changes. Below is the honest mapping — what transfers directly, what's better here, and the one thing we deliberately don't do.
| Concern | Typical provider | Calder |
|---|---|---|
| Sends | provider.emails.send() | POST /v1/emails — same fields, different envelope |
| Response | 200 + { id } | 202 + { id, status } — async by design, not by accident |
| Retries | Your code, your problem | Idempotency-Key — retry freely, send once |
| Webhooks | Fire-and-forget events | Same events, plus visible retries and replay |
| Broadcasts | Often bundled in | Not built, on purpose — transactional only |
| Pricing | USD, overages | NGN + USD, hard limits, no surprise bills |
The move
Three steps, zero downtime
Run both providers in parallel: new sends go to Calder with a fresh idempotency scheme while history drains from the old one. Verify your domain here (same DNS records, new values), flip traffic project by project, then cancel.
- Keep your HTML — any rendered template sends as-is
- Re-register webhook endpoints and secrets
- Export suppression lists and re-import manually
the shape of the change
// before
await provider.emails.send({ /* … */ });
// after
await fetch("https://api.calder.click/v1/emails", {
method: "POST",
headers: { /* key + Idempotency-Key */ },
body: JSON.stringify({ /* same fields */ }),
});Stuck? We help with migrations personally — send shape included, no sales call required.
Get started
Go get your first delivery.
Not your first signup form, not your first dashboard tour — your first email, landing in an inbox, with the webhook to prove it. Test keys are free and can’t hurt anything. The only thing standing between you and that little delivered tag is one POST request.