Pular para o conteúdo
couryo

Guia do desenvolvedorMigração

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.

Ver em Markdown

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 e use este guia para traduzir cada parte.

A chamada de envio#

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" }]
  }'
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
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:

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 ou use o editor visual 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).

Audiences, contatos e tópicos#

  • Exporte cada audience em CSV e importe no Couryo, com a confirmação de consentimento. Quem já tinha se descadastrado: cadastre como supressão de marketing antes (copiar as supressões).
  • 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.
  • Broadcasts viram campanhas, 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, 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.