Para desenvolvedores
Envie e-mail pelo seu código, do jeito que você já faz.
API REST com os mesmos formatos da Resend, SMTP, SDKs para Node.js, PHP e Laravel e uma CLI. Para migrar, em geral basta trocar a URL base e a chave.
Crie uma chave
Use uma chave por sistema e por ambiente. O checkout, o WordPress ou o ERP só precisam enviar: dê a eles uma chave só de envio, presa ao domínio certo.
- Se uma chave só de envio vazar, ela só envia e vê o que ela mesma enviou
- A chave aparece uma única vez, na criação
- Chaves só de envio e presas a um domínio dependem do plano
Envie o primeiro e-mail
Todos os caminhos passam pelas mesmas regras: domínio verificado, cotas, lista de supressão e os mesmos eventos. Escolha por onde enviar.
A API que você já conhece
Um POST em /emails e o e-mail sai. Os nomes dos campos e os formatos de resposta e de erro são os da Resend, então o que você já sabe continua valendo.
- Envio em lote, com até 100 e-mails por requisição
- Agendamento de até 30 dias e cancelamento (lote e agendamento dependem do plano)
- Idempotency-Key para repetir uma chamada sem duplicar o envio
curl -X POST https://api.postal.so/emails \
-H "Authorization: Bearer $POSTAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Aurora Cosméticos <[email protected]>",
"to": ["[email protected]"],
"subject": "Seu pedido #10482 saiu para entrega",
"html": "<p>O pedido <b>#10482</b> está a caminho.</p>"
}'SDK para Node.js e TypeScript
O pacote postal-so tem tipos, erros tipados, retentativa com espera crescente e a conferência de assinatura dos webhooks. Funciona no Node 18 ou mais novo, sem dependências.
- npm install postal-so
- Lê a chave de POSTAL_API_KEY
- Inclui a CLI postal para testar pelo terminal
import { Postal } from 'postal-so';
const postal = new Postal(); // lê POSTAL_API_KEY
const { id } = await postal.emails.send(
{
from: 'Aurora Cosméticos <[email protected]>',
to: '[email protected]',
subject: 'Seu pedido #10482 saiu para entrega',
html: '<p>O pedido <b>#10482</b> está a caminho.</p>',
},
{ idempotencyKey: 'order-10482-shipped' },
);SDK para PHP e transporte para o Laravel
O pacote postal-so/postal-php exige PHP 8.2 ou mais novo. No Laravel, ele cria o cliente sozinho e traz o transporte postal: basta declarar o mailer em config/mail.php e usar MAIL_MAILER=postal, e o Mail::to() continua igual.
- composer require postal-so/postal-php
- Mailables, notificações, anexos e etiquetas seguem funcionando
- Prefere SMTP? O Laravel também funciona com o servidor SMTP da Postal
use Postal\Client;
$postal = new Client(); // lê POSTAL_API_KEY
$result = $postal->emails->send([
'from' => 'Aurora Cosméticos <[email protected]>',
'to' => '[email protected]',
'subject' => 'Seu pedido #10482 saiu para entrega',
'html' => '<p>O pedido <b>#10482</b> está a caminho.</p>',
], 'order-10482-shipped'); // chave de idempotência
echo $result['id'];SMTP para o que não fala com API
WordPress, ERPs, plataformas de loja e impressoras enviam pelo servidor SMTP da Postal, com uma chave de API como senha. As mesmas regras da API valem: domínio verificado, cotas e lista de supressão. O SMTP depende do plano.
- Porta 465 (recomendada) ou 587; 2465 e 2587 se a sua rede bloquear
- O código de resposta traz o id do e-mail
- Até 40 MB e 50 destinatários por mensagem
Servidor smtp.postal.so
Porta 465 (TLS direto) ou 587 (STARTTLS)
Usuário postal
Senha uma chave de API (ps_...)
# Laravel, no .env
MAIL_MAILER=smtp
MAIL_SCHEME=smtps
MAIL_HOST=smtp.postal.so
MAIL_PORT=465
MAIL_USERNAME=postal
MAIL_PASSWORD=ps_sua_chaveAcompanhe nos logs
Cada requisição feita com uma chave de API e cada mensagem enviada por SMTP aparece em Logs, com o corpo enviado e a resposta. Os logs ficam guardados por 30 dias.
Receba os eventos
Receba cada evento de e-mail no seu servidor, com assinatura no padrão Standard Webhooks, até 8 tentativas e reenvio manual. O SDK confere a assinatura em uma linha.
- 30 tipos de evento, de e-mails a contatos e inboxes
- Mesmo webhook-id em todas as tentativas, para descartar duplicatas
- Evento de teste e endereços de teste, como [email protected]
import express from 'express';
import {
verifyWebhook,
PostalWebhookVerificationError,
} from 'postal-so';
const app = express();
// O corpo precisa chegar cru (Buffer)
app.post(
'/webhooks/postal',
express.raw({ type: 'application/json' }),
(req, res) => {
try {
const event = verifyWebhook(
req.body,
req.headers,
process.env.POSTAL_WEBHOOK_SECRET,
);
if (event.type === 'email.bounced') {
// descarte o endereço
}
res.sendStatus(200);
} catch (error) {
if (error instanceof
PostalWebhookVerificationError) {
return res.sendStatus(400);
}
throw error;
}
},
);Teste sem enviar de verdade
Os endereços de teste geram eventos e webhooks reais, não usam a cota e não afetam a reputação. Dependem do plano. A CLI ajuda a testar pelo terminal, com saída JSON para scripts.
| Endereço de teste | Eventos que ele gera |
|---|---|
[email protected] | email.sent e email.delivered |
[email protected] | email.sent e email.bounced, com bounce permanente |
[email protected] | email.sent, email.delivered e email.complained |
[email protected] | Só email.suppressed |
[email protected] | email.sent e email.delivery_delayed |
npm install --global postal-so postal login postal emails send \ --from [email protected] \ --to [email protected] \ --subject "Teste" --text "Funcionou"
Migre da Resend
A API da Postal usa os mesmos recursos, nomes de campos e formatos de resposta, então a migração costuma ser trocar a URL base e a chave. O SDK da Resend continua funcionando se você apontar a URL base para a Postal.
- Testado com o pacote resend 6.34 para Node.js
- O que muda: o segredo e as regras de assinatura dos webhooks, os limites e as cotas
- curl -X POST https://api.resend.com/emails \- -H "Authorization: Bearer re_..."- - # ou, com o SDK da Resend, no .env- RESEND_BASE_URL=https://api.resend.com+ curl -X POST https://api.postal.so/emails \+ -H "Authorization: Bearer ps_..."+ + # ou, com o SDK da Resend, no .env+ RESEND_BASE_URL=https://api.postal.so| Ponto | Na Postal |
|---|---|
| URL base e chave | https://api.postal.so e Authorization: Bearer ps_… |
| Envio e erros | POST /emails devolve {"id"} e os erros seguem {statusCode, name, message}. Igual. |
| Nomes dos eventos | Os mesmos (email.delivered, email.bounced…), mais outros, como email.replied e contact.*. |
| Webhooks | Padrão Standard Webhooks: cabeçalhos webhook-* e svix-*. O segredo (whsec_…) é o de cada endpoint. |
| Endereços de teste | [email protected] vira [email protected], e assim por diante. |
| Limites e cotas | Por time e por plano. Veja Limites. |
Antes de virar a chave
- Domínio verificado na Postal (dá para manter o mesmo nas duas plataformas ao mesmo tempo)
- Chave de API criada: só de envio e presa ao domínio, para quem só envia
- Lista de supressão importada, 100 endereços por requisição
- Webhook criado e assinatura conferida antes de virar o tráfego
- URL base e chave trocadas primeiro no ambiente de testes
Códigos que o app preenche
O cabeçalho OTP-Token leva o código e o site de origem. Ainda é um rascunho na IETF e nem todo cliente de e-mail o lê; quem não conhece, ignora.
From: Aurora Cosméticos <[email protected]> Subject: Seu código de acesso OTP-Token: "123456"; origin="https://app.exemplo.com.br"
Documentação
Tudo na documentação
Guias, referência completa da API e exemplos em cURL, Node.js, Python e PHP.
Documentação
Primeiros passos, guias e conceitos.
Abrir a documentaçãoReferência da API
Cada rota, com exemplos e respostas.
Ver a referênciaSDKs e CLI
Node.js, PHP, Laravel e linha de comando.
Ver os SDKsSMTP
Servidor, portas, usuário e códigos de resposta.
Ver o SMTPMigrar da Resend
O que continua igual, o que muda e como virar o tráfego.
Ler o guiaCabeçalho OTP-Token
Formato, envio, leitura e segurança.
Ler o guiaPerguntas frequentes
Posso continuar usando o SDK da Resend?
Pode. Aponte a URL base para https://api.postal.so e use a chave da Postal. Testamos o pacote resend 6.34 para Node.js; outros SDKs que aceitam trocar a URL falam o mesmo formato, mas não foram testados um a um.
Quando usar SMTP e quando usar a API?
Use o SMTP em sistemas que não falam com APIs, como WordPress e ERPs. Use a API quando precisar de etiquetas, agendamento ou templates, que o SMTP não tem.
Qual é o limite de requisições?
É por time e por segundo, e depende do plano. Passou do limite, a resposta é 429, com o cabeçalho Retry-After. Os SDKs esperam e repetem sozinhos. Veja Limites.
Como testo sem enviar e-mail de verdade?
Mande para os endereços de teste, como [email protected], se o seu plano incluir. O e-mail é simulado, não usa a cota e gera eventos e webhooks reais.