Docs / Integrations / Marketing

Marketing & Migration

Replace your existing ESP in an afternoon. Migrate templates, contacts, and suppressions — then connect your marketing tools.

Machine translation available — choose your language in the top bar.

Every migration script is a self-contained Node.js ESM module. Install the one you need, set two environment variables, and run it. Nothing is deleted from your old provider — the scripts are read-only against the source and write-only against Mailgrid.

Migrate from SendGrid

The SendGrid migration script pulls your transactional templates, marketing contacts, global suppressions, and verified sending domains and recreates them in Mailgrid.

Install

terminal
npx mailgrid-migrate@latest integrations/migrate-sendgrid/

Run

migrate-sendgrid
SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxxxxxx \
MAILGRID_API_KEY=mb_live_xxxxxxxxxxxxxxxxxxxx \
node migrate.mjs

What migrates

Estimated time

Under 5 minutes for < 100k contacts. Large lists (> 500k) may take 15–30 minutes due to SendGrid's paginated contacts API.

After migration

Re-add DKIM CNAMEs for any migrated domains — SES issues new DKIM tokens. Update your application's SENDGRID_API_KEY references to MAILGRID_API_KEY and swap the base URL to https://api.mailgrid.space/api.

Template variable syntax

SendGrid uses {{"{{"}}variable{{"}}"}} (Handlebars-like) but with their own substitution tag format. The script auto-converts {{"{{"}}variable{{"}}"}} tags to Mailgrid Handlebars. Review complex conditional blocks manually.

Migrate from Mailchimp

Exports all Mailchimp audiences, their members, merge fields, and tags into Mailgrid contacts and lists.

Install & run

migrate-mailchimp
npx mailgrid-migrate@latest integrations/migrate-mailchimp/

MAILCHIMP_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us21 \
MAILGRID_API_KEY=mb_live_xxxxxxxxxxxxxxxxxxxx \
node migrate.mjs

What migrates

Estimated time

~3 minutes per 50k members. The Mailchimp export API is rate-limited to 10 requests/second.

Transactional email

Mailchimp Transactional (formerly Mandrill) templates are not included in the standard Mailchimp API. Run the SendGrid migration script against your Mandrill account instead (Mandrill exposes a compatible API).

Migrate from Brevo (Sendinblue)

Migrates contacts, contact lists, email templates, and transactional suppressions from Brevo.

Install & run

migrate-brevo
npx mailgrid-migrate@latest integrations/migrate-brevo/

# Dry run first — prints a summary without writing anything
BREVO_API_KEY=xkeysib-xxxxxxxxxxxxxxxxxxxx \
MAILGRID_API_KEY=mb_live_xxxxxxxxxxxxxxxxxxxx \
node migrate.mjs --dry-run

# Full migration
BREVO_API_KEY=xkeysib-xxxxxxxxxxxxxxxxxxxx \
MAILGRID_API_KEY=mb_live_xxxxxxxxxxxxxxxxxxxx \
node migrate.mjs

What migrates

Estimated time

~10 minutes for a typical Brevo account. Use --dry-run first to verify counts before committing.

SMS contacts

Brevo contacts with only a phone number (no email) are skipped. The script prints a count of skipped records at the end.

Migrate from Mailgun

Migrates Mailgun sending domains, mailing lists, and mailing list members to Mailgrid.

Install & run

migrate-mailgun
npx mailgrid-migrate@latest integrations/migrate-mailgun/

MAILGUN_API_KEY=key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
MAILGUN_DOMAIN=mg.yourdomain.com \
MAILGRID_API_KEY=mb_live_xxxxxxxxxxxxxxxxxxxx \
node migrate.mjs

What migrates

Estimated time

2–5 minutes. Mailgun's API supports bulk exports, so member migration is fast regardless of list size.

EU region

If your Mailgun account is on the EU region, set MAILGUN_API_URL=https://api.eu.mailgun.net in addition to your API key.

Migrate from Postmark

Migrates Postmark email templates and suppression lists into Mailgrid.

Install & run

migrate-postmark
npx mailgrid-migrate@latest integrations/migrate-postmark/

POSTMARK_SERVER_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
MAILGRID_API_KEY=mb_live_xxxxxxxxxxxxxxxxxxxx \
node migrate.mjs

What migrates

Estimated time

Under 3 minutes for most accounts. Postmark templates are small and the suppressions endpoint paginates efficiently.

Message streams

Postmark message streams map to Mailgrid's transactional/broadcast split. Suppressions from broadcast streams are imported to Mailgrid's marketing suppression list; transactional stream suppressions go to the transactional list.

Migrate from Resend

Migrates Resend domains, audiences, and audience contacts to Mailgrid.

Install & run

migrate-resend
npx mailgrid-migrate@latest integrations/migrate-resend/

RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxxxxxxxxxx \
MAILGRID_API_KEY=mb_live_xxxxxxxxxxxxxxxxxxxx \
node migrate.mjs

What migrates

Estimated time

Under 5 minutes. Resend's audience API is fully paginated and the script batches contact imports at 500/request.

Migrate from MailerLite

Migrates MailerLite subscriber groups to Mailgrid lists and subscribers to Mailgrid contacts.

Install & run

migrate-mailerlite
npx mailgrid-migrate@latest integrations/migrate-mailerlite/

MAILERLITE_API_KEY=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9... \
MAILGRID_API_KEY=mb_live_xxxxxxxxxxxxxxxxxxxx \
node migrate.mjs

What migrates

Estimated time

~5 minutes per 100k subscribers. MailerLite's API rate limit is 120 requests/minute; the script respects this with automatic back-off.

MailerLite Classic vs New

The script targets the new MailerLite API (api.mailerlite.com). If you're on MailerLite Classic, set MAILERLITE_CLASSIC=true to use the legacy endpoint instead.

Klaviyo

A Cloudflare Worker receives Klaviyo Flow webhook events and forwards them to Mailgrid as transactional sends. Use this to trigger order confirmation, shipment, and cart-recovery emails from Klaviyo Flows without changing your ESP.

Install the worker

deploy klaviyo worker
npx mailgrid-migrate@latest integrations/klaviyo/

# Configure secrets
npx wrangler secret put MAILGRID_API_KEY
npx wrangler secret put KLAVIYO_SIGNING_SECRET

# Deploy
npx wrangler deploy

Supported Klaviyo Flow events

Configure the Klaviyo Flow action

In your Klaviyo Flow, add a Webhook action after the trigger:

klaviyo flow webhook payload
{
  "event":  "{{ event.MetricName }}",
  "email":  "{{ person.EmailAddress }}",
  "name":   "{{ person.FirstName }}",
  "data":   {{ event|json }}
}

Set the webhook URL to your deployed Worker URL (e.g. https://klaviyo-mailgrid.youraccount.workers.dev). The Worker validates the X-Klaviyo-Signature header before forwarding.

Template mapping

Edit template-map.js in the worker directory to customize which Mailgrid template ID is triggered for each Klaviyo event type. The default map covers the three events above.

Customer.io

A Cloudflare Worker handles Customer.io webhook delivery events and a sync script keeps suppressions in both platforms consistent.

Deploy the worker

deploy customer.io worker
npx mailgrid-migrate@latest integrations/customer-io/

npx wrangler secret put MAILGRID_API_KEY
npx wrangler secret put CUSTOMERIO_WEBHOOK_SECRET

npx wrangler deploy

In Customer.io, go to Settings → Reporting Webhooks and add your Worker URL. Enable the email.bounced, email.unsubscribed, and email.spam_complaint event types.

Suppression sync

The included sync script exports contacts from Customer.io and imports unsubscribes/bounces into Mailgrid — and vice versa — keeping suppression lists aligned across both platforms.

suppression sync
CUSTOMERIO_APP_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
MAILGRID_API_KEY=mb_live_xxxxxxxxxxxxxxxxxxxx \
node sync-suppressions.mjs

# Run direction: customerio→mailgrid (default), mailgrid→customerio, or both
DIRECTION=both node sync-suppressions.mjs

Contact export / import

contact export
# Export Customer.io segment to Mailgrid list
CUSTOMERIO_SEGMENT_ID=12345 \
MAILGRID_LIST_ID=lst_xxxxxxxxxxxxxxxxxxxx \
node export-segment.mjs

The Worker also accepts inbound Mailgrid webhook events (email.bounced, email.unsubscribed) and calls the Customer.io /unsubscribe endpoint to keep both platforms in sync without the manual sync script.

Dual-sending during cutover

During migration, you can run Customer.io and Mailgrid in parallel. The Worker deduplicates sends using a 24-hour idempotency key so the same message is not delivered twice.