Guia do desenvolvedorIntegrações
SDKs oficiais
SDKs oficiais do Couryo para Node.js, PHP (com Laravel) e Python (com Django), com Idempotency-Key automático, novas tentativas, erros tipados e verificação de webhook.
Os três SDKs oficiais fazem a mesma coisa do mesmo jeito. Qualquer um deles poupa o trabalho repetitivo de falar com a API REST:
Idempotency-Keyautomático em todo POST, repetido nas novas tentativas: um envio que deu tempo esgotado mas passou nunca sai duplicado.- Novas tentativas com espera crescente para erro de rede,
5xxerate_limited, respeitando oRetry-After. Erros que falhariam de novo (domain_not_verified,daily_limit_reached...) voltam na hora. - Erros tipados com o
codeestável da API, amessageno idioma escolhido (pt-BRpor padrão) e orequest_idpara o suporte. - Verificação de webhook (Standard Webhooks, segredo
whsec_) numa chamada. - E-mails, lote, templates, domínios, contatos, eventos, campanhas, supressões e webhooks.
| Linguagem | Pacote | Instalar | Integração pronta |
|---|---|---|---|
| Node.js 20.3+ | @couryo/node |
npm install @couryo/node |
Next.js e Express (guia) |
| PHP 8.1+ | couryo/couryo-php |
composer require couryo/couryo-php |
transporte de e-mail do Laravel (guia) |
| Python 3.9+ | couryo |
pip install couryo |
backend de e-mail do Django (guia) |
Não usa nenhuma dessas linguagens? A API é REST com JSON: qualquer cliente HTTP funciona, e o SMTP serve para qualquer ferramenta que já envia e-mail.
Enviar um e-mail#
Todos leem a chave da variável COURYO_API_KEY quando você não passa nenhuma. Use uma chave ck_test_ enquanto testa: nada é entregue e o e-mail aparece no painel (modo de teste).
import { Couryo } from "@couryo/node";
const couryo = new Couryo(); // lê COURYO_API_KEY
const { id } = await couryo.emails.send({
from: "Loja Exemplo <pedidos@exemplo.com.br>",
to: "ana@exemplo.com.br",
subject: "Pedido 1042 confirmado",
html: "<p>Obrigado pela compra!</p>",
text: "Obrigado pela compra!",
});<?php
require 'vendor/autoload.php';
$couryo = new Couryo\Couryo(getenv('COURYO_API_KEY'));
$email = $couryo->emails->send([
'from' => 'Loja Exemplo <pedidos@exemplo.com.br>',
'to' => 'ana@exemplo.com.br',
'subject' => 'Pedido 1042 confirmado',
'html' => '<p>Obrigado pela compra!</p>',
'text' => 'Obrigado pela compra!',
]);
echo $email['id']; // msg_...from couryo import Couryo
couryo = Couryo() # lê COURYO_API_KEY
email = couryo.emails.send({
"from": "Loja Exemplo <pedidos@exemplo.com.br>",
"to": "ana@exemplo.com.br",
"subject": "Pedido 1042 confirmado",
"html": "<p>Obrigado pela compra!</p>",
"text": "Obrigado pela compra!",
})
print(email["id"]) # msg_...Sua própria chave de idempotência#
Quando o mesmo evento do seu sistema pode disparar duas vezes (um webhook de pagamento repetido, um job que roda de novo), passe uma chave que identifica o evento. A segunda chamada recebe a mesma resposta, sem enviar de novo.
await couryo.emails.send(corpo, { idempotencyKey: "pedido-1042-confirmacao" });$couryo->emails->send($corpo, ['idempotency_key' => 'pedido-1042-confirmacao']);couryo.emails.send(corpo, idempotency_key="pedido-1042-confirmacao")Tratar erros#
import { CouryoError } from "@couryo/node";
try {
await couryo.emails.send(corpo);
} catch (e) {
if (e instanceof CouryoError && e.code === "domain_not_verified") {
// e.status, e.message (em português), e.param, e.requestId
}
}use Couryo\Exception\CouryoException;
try {
$couryo->emails->send($corpo);
} catch (CouryoException $e) {
if ($e->getErrorCode() === 'domain_not_verified') {
// $e->getStatus(), $e->getMessage(), $e->getParam(), $e->getRequestId()
}
}from couryo import CouryoError
try:
couryo.emails.send(corpo)
except CouryoError as e:
if e.code == "domain_not_verified":
... # e.status, e.message, e.param, e.request_idA lista de códigos, com causa e correção, está em Erros.
Verificar um webhook#
Passe o corpo cru, exatamente como chegou. O SDK confere a assinatura e o horário (até 5 minutos) e devolve o evento.
import { verifyWebhook } from "@couryo/node";
const evento = verifyWebhook({ secret: process.env.COURYO_WEBHOOK_SECRET!, headers: req.headers, body: corpoCru });$evento = Couryo\Webhook::verify(getenv('COURYO_WEBHOOK_SECRET'), getallheaders(), file_get_contents('php://input'));from couryo import verify_webhook
evento = verify_webhook(os.environ["COURYO_WEBHOOK_SECRET"], request.headers, corpo_cru)Detalhes do formato em Webhooks.
Contatos, eventos e campanhas#
await couryo.contacts.create({ email: "ana@exemplo.com.br", attributes: { nome: "Ana", plano: "pro" }, tags: ["cliente"] });
await couryo.events.track({ contact: { email: "ana@exemplo.com.br" }, name: "user.signed_up" });
const campanha = await couryo.campaigns.create({ name: "Novidades de outubro", audience: { type: "all" }, template_id: "novidades" });
await couryo.campaigns.preflight(campanha.id); // contagem real e revisão antes de dispararOs eventos iniciam as sequências com esse gatilho; as campanhas passam por uma checagem antes do disparo. Os mesmos métodos existem no PHP e no Python, com os nomes no estilo de cada linguagem.
Código aberto#
Os SDKs têm licença MIT. Os modelos de e-mail brasileiros (Pix, boleto, recuperação de senha e outros) também saem como um pacote React Email independente, que funciona com qualquer provedor.