Migrate

Migrate from SendGrid

Everything that maps from SendGrid to Sendara: the concept map, a before/after send, your suppression list, webhook events, and a parallel-run cutover you can do without a deliverability scare.

Sendara mirrors the surface you already use in SendGrid: an API key, a verified sending domain, a send call shaped like { from, to, subject, html }, an event timeline, and signed webhooks. The migration is mostly mechanical. This page maps each piece. For the why and the overall strategy, start with Switch to Sendara.

Keep your SendGrid account live and verified throughout. You can verify the same sending domain in both at once and run them in parallel, so nothing here is a one-way door until you decide to decommission.

Why switch

You send from your own domain with your own DKIM, SPF, and DMARC, so your reputation moves with you. Switching providers neither resets nor repairs it. What changes is the developer experience around the send: idempotent requests, a full per-message event timeline, an open suppression model you import and control, and pricing that does not penalize growth. It is a clean API and an honest billing model. It is not a deliverability cure.

Concept map

Here is how the SendGridprimitives you rely on line up with Sendara's.

SendGridSendaraNotes
API key (SG.…)API key (sk_live_… / sk_test_…)Create a key in the dashboard. A test key simulates the delivery, and Sendara charges nothing for it.
Domain AuthenticationDomainPOST /v1/domains returns the 6 records to publish: 3 DKIM CNAMEs, an MX record and an SPF record on the MAIL FROM subdomain, and a DMARC record.
fromfromSendGrid takes { email, name } or a string. Sendara takes a bare address, or 'Acme <[email protected]>'. The SDK sends it as metadata.from_email.
sgMail.sendsendara.emails.sendTurn { to, from, subject, html } into { from, to, subject, html }.
Event WebhookWebhook eventsSubscribe at POST /v1/webhooks. Sendara signs each delivery with HMAC-SHA256.
Suppression Management (bounces/blocks/spam)Suppression listImport the addresses with POST /v1/suppressions/import.
Marketing Campaigns / ContactsContact lists / BroadcastsCall sendara.contacts.lists.* and sendara.broadcasts.*.

Swap the env vars & SDK

Install the Sendara SDK and point your code at a Sendara API key. Create one in the dashboard. Test keys (sk_test_…) simulate delivery and never bill, so you can wire everything up before sending a single real message.

npm install sendara
SendGridSendara
SENDGRID_API_KEYSENDARA_API_KEY

Before & after: sending

The send call keeps the same shape. Set the sender to an address on your verified domain with the SDK from parameter. On the wire, that value travels as metadata.from_email. Each SDK call generates an idempotency key. Automatic in-call retries reuse it; a retry started by your application must pass and reuse the same explicit key.

before.ts
import sgMail from "@sendgrid/mail";

sgMail.setApiKey(process.env.SENDGRID_API_KEY);

await sgMail.send({
  to: "[email protected]",
  from: "[email protected]",
  subject: "Welcome to Acme",
  html: "<strong>It works!</strong>",
});
To show a friendly name, pass a display-name address: from: "Acme <[email protected]>" (name first, address in angle brackets). See sender name.

DNS & domain verification

Verify your domain in Sendara with POST /v1/domains. Publish the 6 records that Sendara returns: 3 DKIM CNAMEs, an MX record and an SPF record on the MAIL FROM subdomain, and a DMARC record. Keep the domain authentication of SendGrid live, so that you can run both providers together. Move your traffic to Sendara when you are ready.

curl https://api.sendara.dev/v1/domains \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "mail.acme.com" }'
Verify in Sendara without removing anything from SendGrid. DKIM supports multiple selectors and SPF can include multiple senders, so both providers can be authorized for the same domain at the same time. See Domains & deliverability.

Import your suppression list

Export SendGrid bounces, blocks, spam reports, and unsubscribes. Import bounces/blocks/spam reports with state suppressed and unsubscribes with state unsubscribed. Sendara then suppresses every new hard bounce and complaint automatically.

Import in bulk with POST /v1/suppressions/import. It is an admin-scoped, idempotent endpoint that upserts each entry and returns { imported, skipped }, so re-running the import is safe. Use state: "suppressed" (the default) for hard bounces, complaints, and manual hard blocks; use state: "unsubscribed" for marketing opt-outs so transactional mail remains allowed. The import does not rewrite a matching contact record. After cutover, hard bounces and spam complaints are added to the list automatically. You can also manage individual entries with POST/DELETE /v1/suppressions.

curl https://api.sendara.dev/v1/suppressions/import \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "entries": [
      { "email": "[email protected]", "reason": "hard_bounce", "state": "suppressed" },
      { "email": "[email protected]", "reason": "provider_unsubscribe", "state": "unsubscribed" }
    ]
  }'
Import suppressions before your first production send on Sendara. A send to a suppressed address is recorded as suppressed and never enqueued or billed. That is the safety net that stops a fresh provider from re-mailing the addresses your old one already learned to avoid.

Map your webhook events

The Event Webhook of SendGrid posts an array of events. Map the `event` field of each one to the matching Sendara event type. Sendara signs an HMAC-SHA256 of `${timestamp}.${rawBody}` in hex. Check the signature with verifyWebhook().

SendGrid eventSendara event
delivereddelivered
bouncebounced
droppedfailed
deferreddelivery_delayed
openopened
clickclicked
spamreportcomplained
unsubscribeunsubscribed suppression stateSendara fires no webhook event. Import each marketing opt-out with POST /v1/suppressions/import and state unsubscribed. This blocks marketing but still permits transactional email; it does not rewrite the contact record.

Subscribe with POST /v1/webhooks, then verify each delivery with verifyWebhook() from the SDK. See Webhooks and Events & the message timeline for the full payload schemas and delivery guarantees.

Cutover checklist

Run this in order. You can stop at any step and stay there as long as you like. Nothing is irreversible until you decommission SendGrid.

  1. Verify the domain in Sendara and publish the DKIM, SPF, DMARC, and MAIL FROM records, leaving SendGrid verified.
  2. Import your suppression list via POST /v1/suppressions/import so no known-bad address is ever mailed.
  3. Wire up the SDK and webhooks against a test key, remapping the events from the table above.
  4. Mirror a low-stakes stream through Sendara and watch it in the message log. Confirm each send with GET /v1/messages?idempotency_key=… and compare delivered, bounced, and complained rates against SendGrid.
  5. Ramp traffic up as the numbers hold. There are no IPs to warm when you stay on the same domain, so move as fast as your confidence allows.
  6. Cut over the remainder, keep SendGrid verified for a week as a fallback, then decommission it.
The idempotency_key you already pass on each send is also your status handle. Behind a feature flag, you can replay a request against Sendara without double-sending, then look it up with GET /v1/messages?idempotency_key=… to confirm it delivered. See Message lifecycle.