Skip to content
couryo

Developer guideMigration

Migrate to Couryo

How to switch email providers without losing delivery or data. The safe order of the migration, what to copy first (suppressions and contacts), the DNS change without stopping your current sending and the guides for SendGrid, Resend, Mailgun, Locaweb and SMTP.

View as Markdown

Switching email providers is safe when it follows an order: Couryo goes in next to your current provider, you check everything with test keys and only then move the traffic, little by little. Nothing Couryo asks for in DNS conflicts with your current provider's records, so both work at the same time during the switch.

Guides per provider, with the API and field mapping:

The safe order#

  1. Create the account and a test key. Under API keys, create a ck_test_ and a ck_live_ key with scope send. The test key never delivers: use it to validate the integration with no risk (test mode).
  2. Add the domain and publish Couryo's records, without deleting anything of your current provider. There are three: two DKIM CNAMEs (couryo1._domainkey and couryo2._domainkey), the return path CNAME (bounces) and DMARC, if you do not have one yet (domains and DNS). With Cloudflare connected, Couryo creates them for you. If your current provider already uses the bounces subdomain, see what to do.
  3. Wait for the domain to be verified. The domain page checks DNS live and tells what is missing in each record.
  4. Switch the code in staging with the test key. Emails show up under Emails with the content and the review link for your team. The bounced@, complained@ and deferred@ addresses simulate the hard cases, with real events and webhooks.
  5. Copy the suppressions before the first live send. Export hard bounces, complaints and unsubscribes from your current provider and add them to Couryo (see below). This is the step that protects your reputation the most: emailing again people who bounced or complained hurts delivery on day one.
  6. Import your marketing contacts from CSV, with the consent confirmation (import from CSV). Suppressed addresses are left out on their own.
  7. Recreate the webhooks in Couryo and adjust your receiver to the Standard Webhooks format and to Couryo's event names (each guide has the table).
  8. Move the traffic little by little, starting with the emails people expect the most (sign-in, password, order confirmation). One key per stream or a flag in your code lets you roll back in seconds.
  9. Keep the old provider on for at least 7 days after all traffic moved: scheduled emails, retries and DKIM signatures of messages still in transit depend on it. Then delete its DNS records (DKIM and the SPF include:, if nothing else uses it), never the MX of your mailboxes.

Volume and trust levels#

Every new account starts with the trust levels: with the domain verified, level 1 sends up to 100 a day and 3,000 a month; level 2 (7 clean days and a checked company tax ID or a payment method) starts at 1,000 a day and doubles every clean week; level 3 unlocks the plan volume. Plan the migration in steps from there: move the smaller transactional flows first and keep the rest on your current provider until the level goes up.

A domain new to Couryo, with no sending history, also goes through the warm-up: its marketing campaigns and sequences start at 50 a day and double every day with sending. Transactional email never waits.

Copy the suppressions#

Couryo does not take a suppression file at once: add each address with POST /v1/suppressions (scope admin). A simple loop does it, from a CSV exported from your current provider with an email column:

Suppressions from a CSV (one row per address)
tail -n +2 bounces.csv | cut -d, -f1 | while read -r email; do
  curl -s https://api.couryo.com/v1/suppressions \
    -H "Authorization: Bearer $COURYO_ADMIN_KEY" \
    -H "Content-Type: application/json" \
    -d "{ \"email\": \"$email\", \"stream\": \"all\" }" > /dev/null
done
  • Hard bounces and complaints: stream: "all" (nothing goes to that address).
  • Marketing unsubscribes: stream: "marketing" (transactional, like password and billing, keeps coming).
  • A repeated address answers 409 already_suppressed, which you can ignore.

What changes in the code#

At your current provider At Couryo
an API key Authorization: Bearer ck_live_... (live) or ck_test_... (test)
a success answer with no queue guarantee 202 { id, status } only after the email is in the queue
retrying with the fear of duplicates Idempotency-Key on every POST: the repeat returns the same answer
different errors per endpoint always { error: { type, code, message, param, doc_url, request_id } }, with stable codes
events with their own names queued, sent, delivered, deferred, bounced, complained, opened, clicked, suppressed, failed, cancelled (events)

After the migration#

  • Follow the Deliverability page: the agent checks DNS, block lists, bounces and complaints by provider and tells what to fix.
  • DMARC reports start reaching Couryo through rua=mailto:reports@dmarc.couryo.com, if you use the suggested record. After 30 clean days, the agent suggests moving DMARC to p=quarantine.
  • Export the log as CSV whenever you need (GET /v1/emails/export, see export as CSV).