# Migrar do SendGrid

> Guia para sair do SendGrid e ir para o Couryo. Mapeamento do Mail Send v3 (personalizations, content, template_id, categories, custom_args, send_at), dos eventos do Event Webhook, das supressões, do SMTP e a troca de DNS sem parar o envio.

Fonte: https://couryo.com/docs/migrate-sendgrid

O SendGrid e o Couryo fazem a mesma coisa com formatos diferentes: no SendGrid um envio carrega `personalizations`; no Couryo cada e-mail é um objeto simples, e vários vão juntos no [lote](https://couryo.com/docs/sending.md#envio-em-lote). Siga a [ordem segura da migração](https://couryo.com/docs/migration.md) e use este guia para traduzir cada parte.

## A chamada de envio

```bash title="SendGrid: POST https://api.sendgrid.com/v3/mail/send"
curl https://api.sendgrid.com/v3/mail/send \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "personalizations": [{ "to": [{ "email": "ana@exemplo.com.br", "name": "Ana" }] }],
    "from": { "email": "pedidos@exemplo.com.br", "name": "Loja" },
    "subject": "Pedido 1042 confirmado",
    "content": [
      { "type": "text/plain", "value": "Obrigado, Ana!" },
      { "type": "text/html", "value": "<p>Obrigado, Ana!</p>" }
    ],
    "categories": ["pedido"],
    "custom_args": { "pedido_id": "1042" }
  }'
```

```bash title="Couryo: POST https://api.couryo.com/v1/emails"
curl https://api.couryo.com/v1/emails \
  -H "Authorization: Bearer $COURYO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-1042-confirmacao" \
  -d '{
    "from": "Loja <pedidos@exemplo.com.br>",
    "to": "Ana <ana@exemplo.com.br>",
    "subject": "Pedido 1042 confirmado",
    "text": "Obrigado, Ana!",
    "html": "<p>Obrigado, Ana!</p>",
    "tags": { "categoria": "pedido" },
    "metadata": { "pedido_id": "1042" }
  }'
```

O SendGrid responde `202` sem corpo e com o cabeçalho `X-Message-Id`. O Couryo responde `202 { "id": "msg_...", "status": "queued" }`, só depois de o e-mail entrar na fila.

## Campos

| SendGrid | Couryo | Observação |
|---|---|---|
| `from: { email, name }` | `from: "Nome <email>"` | texto, num domínio verificado |
| `personalizations[].to/cc/bcc` | `to`, `cc`, `bcc` (texto ou lista) | até 50 destinatários por e-mail; cada personalização vira um item do lote |
| `reply_to` / `reply_to_list` | `reply_to` | |
| `subject` | `subject` | |
| `content` (`text/plain`, `text/html`) | `text`, `html` | mande os dois: a parte em texto ajuda a entrega |
| `template_id` + `dynamic_template_data` | `template` + `variables` | o template precisa existir no Couryo (veja abaixo) |
| `attachments[]` (`content`, `filename`, `type`, `content_id`) | `attachments[]` (`content`, `filename`, `content_type`, `content_id`) | Base64, até 20 |
| `headers` | `headers` | cabeçalhos da plataforma (`From`, `Message-ID`, `List-Unsubscribe`...) são ignorados |
| `categories` | `tags` | chave e valor, por exemplo `{ "categoria": "pedido" }` |
| `custom_args` | `metadata` | volta em todo webhook |
| `send_at` (Unix, até 72 h) | `scheduled_at` (ISO 8601, até 30 dias) | dá para [reagendar e cancelar](https://couryo.com/docs/sending.md#reagendar-ou-cancelar) pelo id do e-mail |
| `batch_id` + cancelar agendados | `POST /v1/emails/{id}/cancel` | um por e-mail |
| `asm.group_id` (grupos de descadastro) | `stream: "marketing"` + [tópicos](https://couryo.com/docs/contacts.md#topicos-e-preferencias) | o descadastro em um clique entra sozinho no marketing |
| `tracking_settings` | [rastreio do projeto](https://couryo.com/docs/tracking.md) | ligado no marketing, desligado no transacional por padrão |
| `mail_settings.sandbox_mode` | chave `ck_test_` | captura sem entregar, com eventos simulados |

## Templates dinâmicos

Os templates do SendGrid usam Handlebars. No Couryo, as variáveis são `{{nome}}` e `{{pedido.total}}`, com valor padrão opcional (`{{nome|cliente}}`); blocos como `{{#if}}` e `{{#each}}` não existem. Recrie cada template em **Templates** (HTML, MJML ou o editor visual) e mande `template` com o nome ou o id:

```json title="Corpo com template"
{ "from": "Loja <pedidos@exemplo.com.br>", "to": "ana@exemplo.com.br", "template": "pedido-confirmado", "variables": { "nome": "Ana", "pedido": { "numero": "1042" } } }
```

Lista de produtos e partes condicionais: monte o trecho em HTML no seu código e passe como variável, ou use um template por caso.

## Eventos do Event Webhook

| SendGrid | Couryo |
|---|---|
| `processed` | `accepted` e `queued` |
| `delivered` | `delivered` |
| `deferred` | `deferred` |
| `bounce` (e `blocked`) | `bounced` |
| `dropped` | `suppressed` (endereço suprimido) ou `failed` (barrado antes do envio) |
| `spamreport` | `complained` |
| `open` | `opened` (com `machine: true` quando foi o programa de e-mail, não a pessoa) |
| `click` | `clicked` (com a `url`) |
| `unsubscribe`, `group_unsubscribe` | não vira evento: o endereço entra na supressão de marketing (`GET /v1/suppressions?reason=unsubscribe`) |

O Event Webhook manda vários eventos num array e assina com ECDSA. O Couryo manda **um evento por chamada**, no padrão [Standard Webhooks](https://couryo.com/docs/webhooks.md) (HMAC-SHA256 com os cabeçalhos `webhook-id`, `webhook-timestamp` e `webhook-signature`), com novas tentativas por até 3 dias.

## Supressões e contatos

- Exporte do SendGrid (Suppressions) as listas **Bounces**, **Spam Reports**, **Invalid Emails** e **Blocks** permanentes, e cadastre no Couryo com `stream: "all"`. **Unsubscribes** e **Group Unsubscribes** entram com `stream: "marketing"`. O laço está em [copiar as supressões](https://couryo.com/docs/migration.md#copiar-as-supressoes).
- Contatos do Marketing Campaigns: exporte em CSV e [importe no Couryo](https://couryo.com/docs/contacts.md#importar-por-csv), com a confirmação de consentimento. Listas viram tags ou [tópicos](https://couryo.com/docs/contacts.md#topicos-e-preferencias).

## SMTP

Se você usa o relay do SendGrid (`smtp.sendgrid.net`, usuário `apikey`), troque só as credenciais: servidor `smtp.couryo.com`, porta `587`, usuário `couryo` e a chave do Couryo como senha. O cabeçalho `X-SMTPAPI` não existe no Couryo: use `X-Couryo-Tags` e `X-Couryo-Stream` ([SMTP](https://couryo.com/docs/smtp.md#opcoes-por-cabecalho)).

## DNS

O SendGrid usa registros próprios (os CNAMEs `em…`, `s1._domainkey` e `s2._domainkey`, e os de link branding). Eles não conflitam com os do Couryo (`couryo1._domainkey`, `couryo2._domainkey` e `bounces`), então os dois ficam publicados juntos durante a migração.

1. Publique os registros do Couryo e espere o domínio ficar verificado.
2. Mantenha o DMARC que você já tem: o Couryo respeita o seu registro. Para receber os relatórios no [agente de entregabilidade](https://couryo.com/docs/deliverability.md), acrescente `mailto:reports@dmarc.couryo.com` ao `rua`.
3. Depois que todo o tráfego estiver no Couryo e se passarem 7 dias, apague os CNAMEs do SendGrid. Não mexa no MX nem no SPF das suas caixas de e-mail.
