Para desarrolladores
Envía correos desde tu código, como ya lo haces.
API REST con los mismos formatos de Resend, SMTP, SDK para Node.js, PHP y Laravel y una CLI. Para migrar, en general basta con cambiar la URL base y la clave.
Crea una clave
Usa una clave por sistema y por entorno. La tienda en línea, WordPress o el ERP solo necesitan enviar: dales una clave solo de envío, ligada al dominio correcto.
- Si una clave solo de envío se filtra, solo puede enviar y ver lo que ella misma envió
- La clave aparece una única vez, al crearla
- Las claves solo de envío y ligadas a un dominio dependen del plan
Envía el primer correo
Todos los caminos pasan por las mismas reglas: dominio verificado, cuotas, lista de supresión y los mismos eventos. Elige por dónde enviar.
La API que ya conoces
Un POST a /emails y el correo sale. Los nombres de los campos y los formatos de respuesta y de error son los de Resend, así que lo que ya sabes sigue valiendo.
- Envío por lotes, con hasta 100 correos por petición
- Programación de hasta 30 días y cancelación (el lote y la programación dependen del plan)
- Idempotency-Key para repetir una llamada sin duplicar el envío
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": "Tu pedido #10482 salió para la entrega",
"html": "<p>El pedido <b>#10482</b> está en camino.</p>"
}'SDK para Node.js y TypeScript
El paquete postal-so incluye tipos, errores tipados, reintento con espera creciente y la comprobación de la firma de los webhooks. Funciona en Node 18 o superior, sin dependencias.
- npm install postal-so
- Lee la clave de POSTAL_API_KEY
- Incluye la CLI postal para probar desde la terminal
import { Postal } from 'postal-so';
const postal = new Postal(); // lee POSTAL_API_KEY
const { id } = await postal.emails.send(
{
from: 'Aurora Cosméticos <[email protected]>',
to: '[email protected]',
subject: 'Tu pedido #10482 salió para la entrega',
html: '<p>El pedido <b>#10482</b> está en camino.</p>',
},
{ idempotencyKey: 'order-10482-shipped' },
);SDK para PHP y transporte para Laravel
El paquete postal-so/postal-php requiere PHP 8.2 o superior. En Laravel, crea el cliente solo y trae el transporte postal: basta con declarar el mailer en config/mail.php y usar MAIL_MAILER=postal, y Mail::to() sigue igual.
- composer require postal-so/postal-php
- Los Mailables, las notificaciones, los adjuntos y las etiquetas siguen funcionando
- ¿Prefieres SMTP? Laravel también funciona con el servidor SMTP de Postal
use Postal\Client;
$postal = new Client(); // lee POSTAL_API_KEY
$result = $postal->emails->send([
'from' => 'Aurora Cosméticos <[email protected]>',
'to' => '[email protected]',
'subject' => 'Tu pedido #10482 salió para la entrega',
'html' => '<p>El pedido <b>#10482</b> está en camino.</p>',
], 'order-10482-shipped'); // clave de idempotencia
echo $result['id'];SMTP para lo que no habla con una API
WordPress, ERP, plataformas de tienda e impresoras envían por el servidor SMTP de Postal, con una clave de API como contraseña. Valen las mismas reglas de la API: dominio verificado, cuotas y lista de supresión. El SMTP depende del plan.
- Puerto 465 (recomendado) o 587; 2465 y 2587 si tu red los bloquea
- El código de respuesta trae el id del correo
- Hasta 40 MB y 50 destinatarios por mensaje
Servidor smtp.postal.so
Puerto 465 (TLS directo) o 587 (STARTTLS)
Usuario postal
Contraseña una clave de API (ps_...)
# Laravel, en .env
MAIL_MAILER=smtp
MAIL_SCHEME=smtps
MAIL_HOST=smtp.postal.so
MAIL_PORT=465
MAIL_USERNAME=postal
MAIL_PASSWORD=ps_sua_chaveSigue el envío en los registros
Cada petición hecha con una clave de API y cada mensaje enviado por SMTP aparece en Registros, con el cuerpo enviado y la respuesta. Los registros se guardan durante 30 días.
Recibe los eventos
Recibe cada evento de correo en tu servidor, con firma en el estándar Standard Webhooks, hasta 8 intentos y reenvío manual. El SDK comprueba la firma en una línea.
- 30 tipos de evento, de correos a contactos y buzones de entrada
- El mismo webhook-id en todos los intentos, para descartar duplicados
- Evento de prueba y direcciones de prueba, como [email protected]
import express from 'express';
import {
verifyWebhook,
PostalWebhookVerificationError,
} from 'postal-so';
const app = express();
// El cuerpo debe llegar crudo (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') {
// descarta la dirección
}
res.sendStatus(200);
} catch (error) {
if (error instanceof
PostalWebhookVerificationError) {
return res.sendStatus(400);
}
throw error;
}
},
);Prueba sin enviar de verdad
Las direcciones de prueba generan eventos y webhooks reales, no usan la cuota y no afectan la reputación. Dependen del plan. La CLI ayuda a probar desde la terminal, con salida JSON para scripts.
| Dirección de prueba | Eventos que genera |
|---|---|
[email protected] | email.sent y email.delivered |
[email protected] | email.sent y email.bounced, con rebote permanente |
[email protected] | email.sent, email.delivered y email.complained |
[email protected] | Solo email.suppressed |
[email protected] | email.sent y email.delivery_delayed |
npm install --global postal-so postal login postal emails send \ --from [email protected] \ --to [email protected] \ --subject "Teste" --text "Funcionou"
Migra desde Resend
La API de Postal usa las mismas funciones, nombres de campos y formatos de respuesta, así que la migración suele consistir en cambiar la URL base y la clave. El SDK de Resend sigue funcionando si apuntas la URL base a Postal.
- Probado con el paquete resend 6.34 para Node.js
- Qué cambia: el secreto y las reglas de firma de los webhooks, los límites y las cuotas
- 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| Aspecto | En Postal |
|---|---|
| URL base y clave | https://api.postal.so y Authorization: Bearer ps_… |
| Envío y errores | POST /emails devuelve {"id"} y los errores siguen {statusCode, name, message}. Igual. |
| Nombres de los eventos | Los mismos (email.delivered, email.bounced…), más otros, como email.replied y contact.*. |
| Webhooks | Estándar Standard Webhooks: encabezados webhook-* y svix-*. El secreto (whsec_…) es el de cada endpoint. |
| Direcciones de prueba | [email protected] pasa a ser [email protected], y así sucesivamente. |
| Límites y cuotas | Por equipo y por plan. Consulta Límites. |
Antes de cambiar la clave
- Dominio verificado en Postal (puedes mantener el mismo en las dos plataformas al mismo tiempo)
- Clave de API creada: solo de envío y ligada al dominio, para quien solo envía
- Lista de supresión importada, 100 direcciones por petición
- Webhook creado y firma comprobada antes de pasar el tráfico
- URL base y clave cambiadas primero en el entorno de pruebas
Códigos que la app rellena
El encabezado OTP-Token lleva el código y el sitio de origen. Todavía es un borrador en la IETF y no todos los clientes de correo lo leen; quien no lo conoce, lo ignora.
From: Aurora Cosméticos <[email protected]> Subject: Tu código de acceso OTP-Token: "123456"; origin="https://app.exemplo.com.br"
Documentación
Todo en la documentación
Guías, referencia completa de la API y ejemplos en cURL, Node.js, Python y PHP.
Documentación
Primeros pasos, guías y conceptos.
Abrir la documentaciónReferencia de la API
Cada ruta, con ejemplos y respuestas.
Ver la referenciaSDK y CLI
Node.js, PHP, Laravel y línea de comandos.
Ver los SDKSMTP
Servidor, puertos, usuario y códigos de respuesta.
Ver el SMTPMigrar desde Resend
Qué sigue igual, qué cambia y cómo pasar el tráfico.
Leer la guíaEncabezado OTP-Token
Formato, envío, lectura y seguridad.
Leer la guíaPreguntas frecuentes
¿Puedo seguir usando el SDK de Resend?
Sí. Apunta la URL base a https://api.postal.so y usa la clave de Postal. Probamos el paquete resend 6.34 para Node.js; otros SDK que permiten cambiar la URL hablan el mismo formato, pero no se probaron uno por uno.
¿Cuándo usar SMTP y cuándo usar la API?
Usa SMTP en sistemas que no hablan con APIs, como WordPress y los ERP. Usa la API cuando necesites etiquetas, programación o plantillas, que el SMTP no tiene.
¿Cuál es el límite de peticiones?
Es por equipo y por segundo, y depende del plan. Si pasas el límite, la respuesta es 429, con el encabezado Retry-After. Los SDK esperan y repiten solos. Consulta Límites.
¿Cómo pruebo sin enviar un correo de verdad?
Envía a las direcciones de prueba, como [email protected], si tu plan lo incluye. El correo se simula, no usa la cuota y genera eventos y webhooks reales.