Migration from SendGrid

Move transactional sends from SendGrid to Groundmail — receipts, password resets, alerts, and invites still go out over POST /emails with a simpler JSON body than SendGrid's v3 mail send payload.


Why teams switch

  • Straightforward HTTP API — one POST /emails instead of nested personalizations / content arrays
  • Owned transactional mail infrastructure, separate from cold/outbound reputation
  • Sandbox → Pool → Dedicated — test for free, run production on a shared transactional network, isolate on managed servers when you need allowlists

Quick mapping

SendGrid Groundmail
SG. API key gm_… API key (Authorization: Bearer)
https://api.sendgrid.com/v3/mail/send https://api.groundmail.dev/emails
personalizations[].to[] to (string or array)
from.email + from.name from (single address string)
content[] with type / value html and/or text
Dynamic templates (template_id) Template alias on send
Event Webhook Webhooks + dashboard activity
ASM / unsubscribe groups Managed unsubscribe + suppressions

Minimal send

SendGrid (v3):

curl -X POST https://api.sendgrid.com/v3/mail/send \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "personalizations": [{ "to": [{ "email": "user@example.com" }] }],
    "from": { "email": "you@yourdomain.com" },
    "subject": "Hello",
    "content": [{ "type": "text/html", "value": "<p>It works.</p>" }]
  }'

Groundmail:

curl -X POST https://api.groundmail.dev/emails \
  -H "Authorization: Bearer $GROUNDMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "you@yourdomain.com",
    "to": "user@example.com",
    "subject": "Hello",
    "html": "<p>It works.</p>"
  }'

Node.js

SendGrid:

import sgMail from '@sendgrid/mail'
sgMail.setApiKey(process.env.SENDGRID_API_KEY!)
await sgMail.send({
  to: 'user@example.com',
  from: 'you@yourdomain.com',
  subject: 'Hello',
  html: '<p>It works.</p>',
})

Groundmail:

import { Groundmail } from 'groundmail'

const client = new Groundmail(process.env.GROUNDMAIL_API_KEY!)
await client.emails.send({
  from: 'you@yourdomain.com',
  to: 'user@example.com',
  subject: 'Hello',
  html: '<p>It works.</p>',
})

Webhooks

SendGrid Event Webhook posts JSON arrays of events. Groundmail sends one signed JSON object per delivery with Groundmail-Signature (HMAC-SHA256). Map event names as follows:

SendGrid event Groundmail
processed email.sent
delivered email.delivered
deferred email.delivery_delayed
bounce email.bounced
dropped email.failed or email.suppressed
open email.opened
click email.clicked
spamreport email.complained

Use Send test event on the dashboard webhooks page (or POST /emails/test) to verify your handler before cutover.


Checklist

  1. Create a Groundmail API key (gm_…)
  2. Add and verify your sending domain (SPF, DKIM, return-path)
  3. Swap the client to api.groundmail.dev and map fields per table above
  4. Recreate webhook endpoints and update signature verification
  5. Send from Sandbox, then production after domain verify

Compare

Marketing overview: SendGrid alternative.