Migrating from another provider
Endpoint mapping from Mailgun, SendGrid and Postmark.
Moving from Mailgun, SendGrid or Postmark is mostly a mapping exercise. This is the map, plus the two steps people skip.
Do these first
1. Bring your suppression list. Your current provider has spent months learning which addresses bounce and who has complained. Export it and import it before your first send.
Skipping this means re-learning all of it by mailing every bad address again, from a domain with no reputation, in one burst. It is close to the worst possible first impression to make on a receiving server.
2. Expect to warm up. A new sending domain starts with no reputation and ramps over days. Do not schedule the cutover for the morning of your biggest campaign of the year.
Endpoint mapping
Mailgun
| Mailgun | Mailyte |
|---|---|
POST /v3/{domain}/messages |
POST /api/v1/messages |
POST /v3/{domain}/messages with recipient variables |
POST /api/v1/messages/batch |
GET /v3/{domain}/events |
GET /api/v1/email-logs |
GET /v3/{domain}/bounces |
GET /api/v1/email-suppressions |
POST /v3/{domain}/bounces |
POST /api/v1/email-suppressions |
GET /v3/domains |
GET /api/v1/domains |
POST /v3/domains/{domain}/verify |
POST /api/v1/domains/{domain}/verify |
POST /v3/domains/{domain}/webhooks |
POST /api/v1/webhooks |
GET /v3/{domain}/templates |
GET /api/v1/email-templates |
GET /v3/lists |
GET /api/v1/contact-lists |
Differences that will catch you:
- Auth is a bearer token, not HTTP Basic with
api:key-…. - Responses are wrapped in
{ message, data, success, code }. The result you want isdata. - No domain in the path. Your key already names the organization, and
fromnames the domain. - Recipient variables become
messages[].variablesin a batch call, rather than arecipient-variablesJSON string.
SendGrid
| SendGrid | Mailyte |
|---|---|
POST /v3/mail/send |
POST /api/v1/messages |
personalizations[] |
messages[] on POST /api/v1/messages/batch |
GET /v3/suppression/bounces |
GET /api/v1/email-suppressions |
GET /v3/messages |
GET /api/v1/email-logs |
GET /v3/whitelabel/domains |
GET /api/v1/domains |
POST /v3/templates |
POST /api/v1/email-templates |
GET /v3/marketing/contacts |
GET /api/v1/contacts |
Differences:
- A much flatter send payload. No
personalizationsarray for a single message —to,from,subject,html. - Template variables are
{{ name }}, not{{{ handlebars }}}, with one filter:default. - Categories become
tags.
Postmark
| Postmark | Mailyte |
|---|---|
POST /email |
POST /api/v1/messages |
POST /email/batch |
POST /api/v1/messages/batch |
POST /email/withTemplate |
POST /api/v1/messages with template_id |
GET /messages/outbound |
GET /api/v1/email-logs |
GET /bounces |
GET /api/v1/email-suppressions |
GET /domains |
GET /api/v1/domains |
| Message streams | stream: "marketing", or campaigns |
Differences:
X-Postmark-Server-TokenbecomesAuthorization: Bearer.HtmlBody/TextBodybecomehtml/text— lower case throughout.- Message streams are simpler. Transactional is the default; pass
stream: "marketing"on a send, or use campaigns, which do it for you.
Payload shape, side by side
Mailgun:
curl -s --user "api:$MG_KEY" \
https://api.mailgun.net/v3/yourdomain.com/messages \
-F from='hello@yourdomain.com' \
-F to='ada@example.com' \
-F subject='Hello' \
-F html='<p>Hi</p>'Mailyte:
curl -X POST "$MAILYTE_BASE/api/v1/messages" \
-H "Authorization: Bearer $MAILYTE_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"from": "hello@yourdomain.com",
"to": "ada@example.com",
"subject": "Hello",
"html": "<p>Hi</p>"
}'JSON rather than form fields, and no domain in the URL.
Cutting over
- Verify the domain here while your current provider still handles production.
- Import suppressions.
- Send test traffic and confirm events arrive.
- Move a small share of real traffic. Watch bounces and complaints for a few days.
- Increase gradually. Keep the old provider configured until you have a full week of clean numbers.
- Only then remove the old provider's SPF
include.
Step 6 last, always. Removing it early breaks the path you are still falling back to.
Next
Send your first email if you have not yet, or Handling delivery events to wire up monitoring before you move real traffic.