
API integration for Resend
We build your Resend connector
We wire Resend into your product: confirmation, reset, PDF invoice. Each send is tied to a business intent, with no double send and no forced marketing campaigns.
- Senior product team
- email connectors in production
- from scoping to monitoring
What does the Resend API provide and when should you choose Resend for application emails?
Resend is a transactional email service designed for developers, with a simple API, real-time logs and native sending domain management. You choose it for emails triggered by your application: sign-up confirmation, magic link, event notification, when the priority is deliverability and traceability rather than marketing campaigns. The API's idempotency ensures that an email like a magic link is not sent twice, even in case of a retry. The platform supports sending from a European region for projects with data localisation requirements.
What our clients build on the Resend API
Magic links and password reset
Sign-in or reset link: the same send does not go out twice if the queue retries. The user gets one usable link.
Invoice PDFs as attachments
The invoice goes as an attachment. If delivery fails, the record is marked email not delivered, without manual watching.
Onboarding without a double welcome
Welcome and day-3 follow-up go out as a batch, without sending the same message twice to the same account.
Product alerts with European latency
Sending from Ireland improves European inbox time. We state plainly where logs live: this is not an EU account.
What it changes in your transactional email
Engineering in service of a measurable outcome: zero double magic links, reliable delivery status, residency stated plainly.
A retry is no longer a second email
Each intent (reset, invoice, welcome) has a business key. If the queue retries, the user does not get two links.
You know whether the email arrived
Delivery notifications are verified. You open access or close an account on a reliable status, not a hope.
Sending region is not residency
Picking Europe for inbox latency does not automatically move the logs. We write that clearly in scoping.
Marketing stays in the marketing tool
Resend covers transactional mail. Campaigns, lists and SMS stay with Mailjet or Brevo: no forced misuse.
How we ship your Resend connector
Scoping
Which emails, what volume, whether a US DPA is acceptable. We write down the residency decision, the sending region, and what stays in the ESP.
Development
An Idempotency-Key derived from the intent, one queue per team, Svix on the raw body, ratelimit-* and retry-after respected.
Acceptance testing
The resend.dev domain, never the production domain. 409 on a divergent payload, replay past 24 h, a webhook outside the window rejected.
Monitoring
Alerts on 429 and quota, an idempotency-key log, an inspectable dead letter queue. You see a saturated team bucket before your users do.
What the Resend API allows
- Idempotent single send
- POST /emails with an Idempotency-Key (1 to 256 characters), remembered for 24 hours. Same key + same payload = same response, no second send.
- Batch up to 100
- POST /emails/batch, one idempotency key for the batch, not for each row. SMTP: Resend-Idempotency-Key.
- Svix webhooks
- Headers svix-id, svix-timestamp, svix-signature. Verify the raw body with the signing secret. The secret is shown only at creation or read time.
- Sending regions, US residency
- us-east-1, eu-west-1, sa-east-1, ap-northeast-1. eu-west-1 improves European time-to-inbox. It does not move the logs.
The vocabulary of the Resend API
- Idempotency-Key
- A 1 to 256 character header, remembered for 24 hours. Derived from the intent, never a UUID regenerated in the queue retry. Past 24 h, the same key no longer exists.
- 409 invalid_idempotent_request
- Same key, different payload. Reusing welcome-user/123 for a different email (template change) is an error. The key identifies the payload, not the user.
- svix-signature
- Svix HMAC over the raw body, with svix-id and svix-timestamp. Parsing JSON then re-signing fails. Dedup on svix-id, reject outside the timestamp window.
- eu-west-1
- Ireland sending region. « It does not control where customer data is stored. » A « Resend Europe » page that implies logs live in Ireland is false.
- ratelimit-*
- IETF headers: limit, remaining, reset, plus retry-after. A follow-up cron and web traffic share the bucket. One queue per team.
- 10 rps / team
- Documented default, every key on the account. 429 daily_quota_exceeded or monthly_quota_exceeded on plans with email quotas.
The real constraints of the Resend API
Residency is in the United States
All account data stays in the United States. eu-west-1 means dispatch from Ireland. If the client requires EU storage, Mailjet or Brevo are the discussion, not a « Resend Europe » slogan.
The idempotency window lasts 24 h
Beyond that, a late replay sends again. Your send table has to live longer than Resend. 409 concurrent_idempotent_requests exists too.
10 requests per second per team
All keys combined. Two independent workers empty the bucket. We put one queue, we read retry-after, we do not run a cron in parallel with web traffic.
This is not an ESP
No lists, segments, SMS v4, inbound parse in the same way. Forcing mass marketing usage in Resend is a bad scope (contact quotas, product).
Resend or Mailjet for your email?
An idempotent sending API on one side, an ESP on the other. Choosing one or the other is a residency and product decision, not an SDK choice.
| Criterion | ResendThis page | MailjetESP |
|---|---|---|
| Product | Sending API, limited broadcasts | ESP: tx, marketing, contacts, SMS |
| Idempotency | Idempotency-Key, 24 h window | CustomID (correlation, not anti-duplicate) |
| Webhooks | Svix, HMAC, svix-* headers | eventcallbackurl v2, no HMAC in the guide |
| Sandbox | resend.dev domain / test keys | Root SandboxMode |
| Residency | US account, optional eu-west-1 sending | Account DPA to be reread |
| Documented throughput | 10 req/s per team, IETF headers | 429, figures not published |
| The right case | Idempotent SaaS transactional email | Tx + marketing + SMS in one account |
The two combine: Resend for the magic link, Mailjet for lifecycle and lists. It is a scoping trade-off, not a permanent choice.
What we measure on a Resend integration
The other sending APIs
If native idempotency is not the criterion, these options are worth discussing during scoping.
ResendWe build your Resend connectorThis page
TwilioA programmable carrier: SMS, WhatsApp, voice and OTP out of the box.
BrevoTransactional email and SMS in a French account, templates included.
RingoverFrench telephony: calls, screen pop and SMS from your business software.
MailjetWe build your Mailjet connectorWe combine Resend with
The stack that surrounds Resend on our projects.
Resend integration: your questions
Three steps. One re_ key per environment, in a vault, never shared between CI and production. A POST /emails connector whose Idempotency-Key is derived from the intent (reset/userId/tokenId), not from a UUID regenerated on retry, plus a send table that lives longer than 24 h. One queue per Resend team, reading ratelimit-* and retry-after: the default is 10 requests per second, all keys combined. Then Svix webhooks: raw body, signing secret, reject outside the timestamp window, dedup on svix-id. The sensitive part is not the SDK: it is US residency, to be written down before promising Europe.
A first useful flow, typically a magic link or an invoice with idempotency and a failure webhook, ships in two to three weeks. A complete chain with batch, multi-region domains, DNS rotation and a sharp boundary against the marketing ESP is closer to four to six weeks. DNS and the DPA often weigh more than POST /emails. We scope the perimeter up front and give a firm estimate before we start, including the residency decision.
No. eu-west-1 is a sending region (Ireland). The documentation is explicit: it does not control where customer data is stored. Metadata, logs and API records stay in the United States. GDPR goes through the DPA and SCCs, not through the sending hostname. If the questionnaire requires EU storage, we discuss Mailjet or Brevo, we do not write « Resend Europe » on a page. That is the seriousness test of scoping.
Resend is a sending API: Idempotency-Key 24 h, signed Svix webhooks, short DX, not an ESP. Mailjet is an ESP: CustomID, SandboxMode, lists, SMS v4, no webhook HMAC in the guide, no Idempotency-Key. You pick Resend when a retry must not resend the magic link, and US storage is accepted. You pick Mailjet when marketing and product share the list. The two combine. It is a scoping trade-off, not an SDK choice.
Because the key identifies the payload, not the user. Reusing welcome-user/123 after a template change is 409 invalid_idempotent_request. A fresh UUID on every queue retry cancels idempotency: Resend sees another send. 409 concurrent_idempotent_requests also exists if two workers leave together. We compute the key from the intent, we serialise retries, and we keep our table longer than 24 h, because past that Resend has forgotten the key.
A Resend integration project?
Let's talk. 30 minutes to scope your sends, check residency and idempotency, and tell you honestly what is feasible.
Discuss my Resend project