# Migrar do Resend

> Guia para sair do Resend e ir para o Couryo. A chamada de envio é quase igual (from, to, subject, html, text, tags, scheduled_at, Idempotency-Key, lote de 100), com o mapeamento de eventos, webhooks, audiences, React Email e a troca de DNS.

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

Quem vem do Resend reconhece quase tudo: o corpo do envio, o lote de 100, a `Idempotency-Key`, o agendamento com cancelamento e os webhooks assinados. As diferenças estão nos detalhes abaixo. 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="Resend: POST https://api.resend.com/emails"
curl https://api.resend.com/emails \
  -H "Authorization: Bearer $RESEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Loja <pedidos@exemplo.com.br>",
    "to": ["ana@exemplo.com.br"],
    "subject": "Pedido 1042 confirmado",
    "html": "<p>Obrigado, Ana!</p>",
    "tags": [{ "name": "categoria", "value": "pedido" }]
  }'
```

```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@exemplo.com.br"],
    "subject": "Pedido 1042 confirmado",
    "html": "<p>Obrigado, Ana!</p>",
    "text": "Obrigado, Ana!",
    "tags": { "categoria": "pedido" }
  }'
```

O Resend responde `{ "id": "..." }`; o Couryo responde `202 { "id": "msg_...", "status": "queued" }`, só depois de o e-mail entrar na fila.

## Campos

| Resend | Couryo | Observação |
|---|---|---|
| `from`, `to`, `cc`, `bcc`, `reply_to`, `subject`, `html`, `text` | os mesmos nomes | até 50 destinatários somando `to`, `cc` e `bcc` |
| `react` (SDK) | `html` e `text` | renderize com o `render` do React Email antes de enviar (veja abaixo) |
| `tags: [{ name, value }]` | `tags: { name: value }` | objeto, não lista |
| `headers` | `headers` | cabeçalhos da plataforma são ignorados |
| `attachments[]` (`filename`, `content`, `path`, `content_type`) | `attachments[]` (`filename`, `content` em Base64, `content_type`, `content_id`) | sem `path`: baixe o arquivo e mande o conteúdo |
| `scheduled_at` (ISO ou texto como "in 1 hour") | `scheduled_at` (ISO 8601 com fuso, até 30 dias) | só a data em ISO |
| `PATCH /emails/{id}` e `POST /emails/{id}/cancel` | `PATCH /v1/emails/{id}` e `POST /v1/emails/{id}/cancel` | o [mesmo desenho](https://couryo.com/docs/sending.md#reagendar-ou-cancelar) |
| `POST /emails/batch` (até 100) | `POST /v1/emails/batch` (até 100) | o Couryo valida cada item sozinho e devolve um resultado por item |
| `Idempotency-Key` | `Idempotency-Key` | 24 horas; mesmo corpo devolve a mesma resposta, corpo diferente `409` |
| (sem equivalente) | `metadata` | dados seus que voltam em todo webhook, como `{ "pedido_id": "1042" }` |
| (sem equivalente) | `stream: "marketing"` | descadastro em um clique incluído e supressão separada do transacional |

## React Email

O Couryo recebe HTML pronto. Com React Email, renderize antes:

```ts title="Node.js"
import { render } from "@react-email/render";
import { PedidoConfirmado } from "./emails/pedido-confirmado";

const html = await render(<PedidoConfirmado nome="Ana" />);
const text = await render(<PedidoConfirmado nome="Ana" />, { plainText: true });

await fetch("https://api.couryo.com/v1/emails", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.COURYO_API_KEY}`, "Content-Type": "application/json", "Idempotency-Key": "pedido-1042" },
  body: JSON.stringify({ from: "Loja <pedidos@exemplo.com.br>", to: "ana@exemplo.com.br", subject: "Pedido 1042 confirmado", html, text }),
});
```

Para e-mails que o time edita sem deploy, crie [templates salvos](https://couryo.com/docs/templates.md) ou use o [editor visual](https://couryo.com/docs/template-editor.md) e mande `template` com `variables`.

## Eventos e webhooks

| Resend | Couryo |
|---|---|
| `email.sent` | `sent` |
| `email.delivered` | `delivered` |
| `email.delivery_delayed` | `deferred` |
| `email.bounced` | `bounced` |
| `email.complained` | `complained` |
| `email.opened` | `opened` |
| `email.clicked` | `clicked` |
| `email.failed` | `failed` |

Os dois assinam no padrão Standard Webhooks: o Couryo usa os cabeçalhos `webhook-id`, `webhook-timestamp` e `webhook-signature` (HMAC-SHA256 com o segredo `whsec_...`). Se o seu receptor confere a assinatura com uma biblioteca do padrão, troque o segredo e o prefixo dos cabeçalhos. O `type` do corpo vem sem o prefixo `email.` (por exemplo, `"type": "bounced"`) e o `data` traz `email_id`, `recipient`, o código SMTP, a resposta crua do destino e a explicação em linguagem simples, no idioma da conta ([webhooks](https://couryo.com/docs/webhooks.md)).

## Audiences, contatos e tópicos

- Exporte cada audience em CSV e [importe no Couryo](https://couryo.com/docs/contacts.md#importar-por-csv), com a confirmação de consentimento. Quem já tinha se descadastrado: cadastre como supressão de marketing antes ([copiar as supressões](https://couryo.com/docs/migration.md#copiar-as-supressoes)).
- Os tópicos do Resend existem no Couryo com o mesmo nome: crie em **Contatos > Tópicos** ou em `POST /v1/topics`. O rodapé de marketing leva à [página de preferências](https://couryo.com/docs/contacts.md#topicos-e-preferencias).
- Broadcasts viram [campanhas](https://couryo.com/docs/campaigns.md), com público por tag, atributo ou tópico.

## DNS

O Resend publica a chave DKIM num registro próprio (`resend._domainkey`) e o return path no subdomínio `send`. Nenhum deles conflita 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; 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 o `resend._domainkey` e os registros do subdomínio `send`. Não mexa no MX nem no SPF das suas caixas de e-mail.
