Skip to content
Docs

Guide

Move from SendGrid to Emailit. Map concepts, API fields, SMTP settings and Event Webhook names, then bring over suppressions, dynamic templates and DNS.

Updated Oct 1, 2026

This guide maps SendGrid concepts, API calls, webhooks, suppressions and templates to their Emailit equivalents. Read Migrate to Emailit first for the overall order and how to run both providers in parallel.

Concepts

SendGrid Emailit
Account and subusers Account and workspaces. Each workspace has its own domains, keys, members and credits.
API key with permissions API key: Full Access, or Sending Only optionally restricted to one domain
Domain authentication Sending domain with SPF, DKIM and return path records
Link branding Tracking subdomain, a CNAME such as go.acme.com
Single sender verification Not available. Every From address must be on a verified domain.
Dynamic templates Templates with an alias and versions, rendered with Temple
Event Webhook Webhooks
Inbound Parse Inbound email
Suppressions Suppressions
Unsubscribe groups Not available. Use audiences and campaign unsubscribe links.
Marketing contacts and lists Contacts and audiences
Single Sends Campaigns
Email Activity Email APIEmails and Email APILogs
Categories and custom args meta
Dedicated IPs and IP pools Dedicated IPs on request
Email address validation Email verification

Update your API calls

SendGrid’s POST /v3/mail/send becomes POST /v2/emails. The request is flatter: there are no personalizations, and addresses are plain strings.

Before: SendGrid
curl https://api.sendgrid.com/v3/mail/send \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "personalizations": [{ "to": [{ "email": "ada@example.com" }] }],
    "from": { "email": "hello@acme.com", "name": "Acme" },
    "subject": "Your receipt",
    "content": [
      { "type": "text/plain", "value": "Thanks for your order." },
      { "type": "text/html", "value": "<p>Thanks for your order.</p>" }
    ]
  }'
After: Emailit
curl https://api.emailit.com/v2/emails \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <hello@acme.com>",
    "to": "ada@example.com",
    "subject": "Your receipt",
    "text": "Thanks for your order.",
    "html": "<p>Thanks for your order.</p>"
  }'
SendGrid Emailit
Authorization: Bearer SG.… Authorization: Bearer secret_…
from: { email, name } from: "Name <email>"
personalizations[].to[] to, a string or an array of up to 50 addresses
personalizations[].cc[], bcc[] cc, bcc
reply_to: { email } reply_to
subject subject
content[] with text/plain and text/html text and html
template_id template, a template ID or alias
personalizations[].dynamic_template_data variables
attachments[] with content, filename, type, content_id attachments[] with content, filename, content_type, content_id, or a url instead of content
headers headers
custom_args, categories meta, an object of string values returned in webhook events
send_at (Unix time) scheduled_at, which accepts the same Unix time, ISO 8601 or plain English
tracking_settings.open_tracking and click_tracking tracking: { "loads": true, "clicks": true }
asm (unsubscribe groups) Not available
202 Accepted with an X-Message-Id header 200 with a JSON body: id, status: "accepted", and ids with one ID per recipient

Each recipient in an Emailit request becomes its own email with its own ID. To send different variables to different people, which SendGrid does with several personalizations, send one request per recipient. Add an Idempotency-Key header so retries are safe. See Send an email.

Switch SMTP settings

Setting SendGrid Emailit
Host smtp.sendgrid.net smtp.emailit.com
Port 587, 465, 2525 or 25 587 (STARTTLS), 465 (TLS), 2525, 2587 or 25
Username apikey emailit
Password Your SendGrid API key Your Emailit API key

Emailit doesn’t read the X-SMTPAPI header. Remove it, and set tracking on the domain instead. See SMTP settings.

Map webhook events

SendGrid event Emailit event
processed email.accepted (API only)
deferred email.attempted
delivered email.delivered
bounce email.bounced
dropped email.suppressed when the recipient is on the suppression list
open email.loaded
click email.clicked
spamreport email.complained
unsubscribe, group_unsubscribe email.unsubscribed, for campaign email only
Inbound Parse POST email.received, then fetch the content with GET /emails/{id}

Like SendGrid, Emailit posts a JSON array of events. The fields differ:

  • The event name is in type, and the email is in data.object. Use data.object.id (the em_ ID from the send response) instead of sg_message_id, and data.object.to instead of email.
  • Your meta values come back in data.object.meta.
  • Emailit signs requests with HMAC-SHA256 instead of SendGrid’s ECDSA public key. Verify X-Emailit-Signature with your whsec_ secret. See Request signature.
JavaScript
for (const event of req.body) {
  const email = event.data.object;
  if (event.type === 'email.bounced') markBounced(email.to, email.id);
  if (event.type === 'email.complained') unsubscribe(email.to);
}

Move suppressions

  1. In SendGrid, export your Bounces, Spam Reports, Invalid Emails and Global Unsubscribes, from the suppression pages or with the /v3/suppression/* API endpoints. Blocks are usually temporary, so you can leave them out.

  2. Build one CSV with the columns email,type,reason:

    CSV
    email,type,reason
    old-address@example.com,recipient,sendgrid bounce
    angry@example.com,recipient,sendgrid spam report

    Use the type recipient for addresses that must never receive email. It blocks API, SMTP and campaign sends. The types bounce, complaint and unsubscribe only stop campaigns.

  3. In Email APISuppressions, select Import and upload the file. Each file can have up to 10,000 rows and can be at most 8 MB, so split larger lists. Duplicates are skipped.

For group unsubscribes from marketing email, import those people as contacts with unsubscribed set, rather than suppressing them from all email. See Manage suppressions.

Move templates

Export each dynamic template’s HTML from SendGrid, then import it in Email MarketingTemplates or create it with the Templates API. Give each template an alias, such as receipt, and send it with "template": "receipt".

Both use double curly braces, but Temple is smaller than Handlebars:

SendGrid (Handlebars) Emailit (Temple)
{{first_name}} {{first_name}}
{{{html_block}}} {{html_block}}. Temple never escapes HTML, so escape user input yourself.
{{insert name "default=there"}} {{name|"there"}}
{{#if plan}}…{{else}}…{{/if}} The same
{{#each items}}…{{/each}} Not supported. Render the list in your code and pass it as one variable.
{{#equals plan "pro"}}…{{/equals}} Not supported. Pass a boolean such as is_pro and use {{#if is_pro}}.

See Temple and Import and export templates.

Change DNS

Add your domain in Email APIDomains and publish the Emailit records. They use their own names (emailit._domainkey, emailit.<domain>, and optionally go and inbound), so they don’t conflict with SendGrid’s domain authentication or link branding CNAMEs. Keep your DMARC record. After the cutover, remove the SendGrid CNAMEs. See DNS records.

If you used Inbound Parse, point the MX record of your parse hostname at Emailit instead. To keep the same hostname, such as parse.acme.com, set the domain’s inbound_key to parse with the API. See Set up inbound.

Next steps

Was this page helpful?

Thanks for the feedback.

Thanks, we read every message.