# 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.

Source: https://couryo.com/en/docs/migration

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:

- [SendGrid](https://couryo.com/en/docs/migrate-sendgrid.md)
- [Resend](https://couryo.com/en/docs/migrate-resend.md)
- [Mailgun](https://couryo.com/en/docs/migrate-mailgun.md)
- [Locaweb](https://couryo.com/en/docs/migrate-locaweb.md)
- [Any provider over SMTP](https://couryo.com/en/docs/migrate-smtp.md)

## 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](https://couryo.com/en/docs/test-mode.md)).
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](https://couryo.com/en/docs/domains.md)). With Cloudflare connected, Couryo creates them for you. If your current provider already uses the `bounces` subdomain, see [what to do](https://couryo.com/en/docs/migrate-smtp.md#dns).
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](https://couryo.com/en/docs/test-mode.md#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](https://couryo.com/en/docs/contacts.md#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](https://couryo.com/en/docs/webhooks.md) 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](https://couryo.com/en/docs/limits.md#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](https://couryo.com/en/docs/campaigns.md): 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:

```bash title="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](https://couryo.com/en/docs/errors.md) |
| events with their own names | `queued`, `sent`, `delivered`, `deferred`, `bounced`, `complained`, `opened`, `clicked`, `suppressed`, `failed`, `cancelled` ([events](https://couryo.com/en/docs/events.md)) |

## 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](https://couryo.com/en/docs/sending.md#export-as-csv)).
