Skip to content
WeZend

Transactional email

How to switch from SendGrid

Move transactional email without dropping a single receipt: suppression groups over first, parallel domain authentication, the v3 mail/send diff, and event-webhook remapping.

Half a day of code; DNS + a cautious cutover sets the pace (about a week)

SendGridWeZend
POST /v3/mail/sendPOST /v1/messages/send (channel: email)
API key (Bearer)X-API-Key header
Domain authenticationEmail domains + live DNS verify
Dynamic templates ({{handlebars}})Templates + variables
Suppression groups + global suppressionsSuppression list + preference topics
Event WebhookDelivery webhooks (signed)
Marketing CampaignsCampaigns + journeys

The stakes, stated plainly

Transactional email is unforgiving: a dropped password reset is a support ticket, a dropped receipt is a legal problem. So this guide is built around one principle — both providers stay fully operational until WeZend has delivered your real traffic for days, not minutes.

Step 1 — Suppressions and bounces first

Export SendGrid's suppression data: global unsubscribes, per-group unsubscribes, bounces, spam reports and invalid addresses (all downloadable under Suppressions in the SendGrid console, or via their API). Import the lot into WeZend (Audience → Suppressions, POST /v1/account/unsubscribes/api/import). Bounced and complaining addresses must never be retried from a fresh platform — that's how new domains get burned.

If you use suppression groups (newsletter vs. product updates), recreate them as preference-center topics — same concept, and subscribers manage them on one hosted page.

Step 2 — Authenticate your domain in parallel

Add your domain under Settings → Email domains. WeZend's DKIM selector coexists with SendGrid's — you do not remove SendGrid's DNS records yet. Both platforms stay fully authenticated side by side, which is what makes a gradual, reversible cutover possible. The live DNS checker confirms each record.

Step 3 — The code diff

SendGrid:

await fetch("https://api.sendgrid.com/v3/mail/send", {
  method: "POST",
  headers: { Authorization: `Bearer ${SENDGRID_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    personalizations: [{ to: [{ email: "anna@example.com" }], dynamic_template_data: { name: "Anna" } }],
    from: { email: "receipts@mail.acme.com" },
    template_id: "d-abc123",
  }),
});

WeZend — flatter body, same idea:

await fetch("https://api.wezend.com/v1/messages/send", {
  method: "POST",
  headers: { "X-API-Key": process.env.WEZEND_API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    to: "anna@example.com",
    channel: "email",
    sender: "receipts@mail.acme.com",
    template_id: "tpl_receipt",
    variables: { name: "Anna" },
    category: "transactional",
    webhook_url: "https://api.yourapp.com/email-events",
  }),
});

Port your dynamic templates first: copy each template's HTML into a WeZend template — Handlebars {{name}} syntax carries over almost unchanged (conditionals become template defaults or separate templates; most transactional templates use none).

Step 4 — Remap the Event Webhook

SendGrid's Event Webhook events map onto WeZend's delivery webhooks: processed→queued, delivered→delivered, bounce/dropped→failed (reason attached), open→opened, click→clicked, spamreport→complaint, unsubscribe→unsubscribed. Verify the X-WeZend-Signature header instead of SendGrid's signed-webhook ECDSA — the webhooks doc has the five-line check. Bounces and complaints also feed the suppression list automatically, so your own bookkeeping can shrink.

Step 5 — Cut over by mail stream

Migrate one stream at a time, lowest risk first: internal notifications → user-facing but recoverable (digests) → critical (receipts, password resets). At each step compare delivery and bounce rates in the deliverability report against your SendGrid baseline. Transactional volume warms up much faster than marketing volume — recipients expect and open these mails — so a week of phased cutover is typically enough.

Keep SendGrid alive for a full week after 100% cutover, then remove its DNS records and close.

If you also use Marketing Campaigns

Follow the Mailchimp-style playbook for the marketing side: contacts in the safe order, campaigns as campaigns, automations as journeys. The pleasant surprise: transactional and marketing then share one suppression list, one domain reputation view and one balance.

Go-live checklist

  • All SendGrid suppressions exported (global, groups, bounces, spam reports) and imported
  • Suppression groups recreated as preference-center topics
  • Domain authenticated in WeZend — SendGrid DNS records left in place
  • Dynamic templates ported; variables render with defaults
  • Event-webhook consumer remapped and signature-verified
  • Streams cut over lowest-risk first, rates compared per step
  • SendGrid kept alive one week past 100%, then DNS cleaned up

Frequently asked about switching from SendGrid

Do you support dedicated IPs like SendGrid?

For most senders, well-managed shared infrastructure plus your own authenticated domain outperforms a neglected dedicated IP — your domain reputation is what inbox providers weigh most. If your volume genuinely warrants dedicated sending infrastructure, contact us and we'll set it up as part of onboarding.

Our receipts must not break for even an hour. Is that realistic?

Yes — that's exactly what the stream-by-stream cutover with both domains authenticated in parallel is for. At no point is there a moment where the old path is off and the new one unproven: you shift a stream, watch it deliver, then shift the next. Rollback is a config change, not a DNS wait.

Start free in minutes

  • No credit card
  • EU data residency
  • 6 channels, one API
  • GDPR built in

One platform. Every customer interaction.

Replace your patchwork of messaging APIs, CDP and automation tools with a single engagement platform built for scale.

No credit card required · EU data residency · 99.99% uptime SLA