Primeros pasos
De cero al primer correo entregado: verifica un dominio, crea una clave y haz un POST /emails.
#1. Verifica un dominio
Postal solo envía desde dominios que has demostrado controlar. En el panel, en Dominios, añade el dominio (por ejemplo, lojaexemplo.com.br) y crea en tu proveedor de DNS los registros que se muestran: un TXT de DKIM y un MX y un TXT para el Return-Path. La verificación suele tardar pocos minutos. Detalles en Dominios y DNS.
#2. Crea una clave de API
En Claves de API, crea una clave solo de envío y copia el token (aparece una sola vez). Guárdalo en una variable de entorno:
export POSTAL_API_KEY="ps_sua_chave"
#3. Envía el primer correo electrónico
Cambia el remitente por una dirección de tu dominio verificado y el destinatario por tu correo:
cURL
curl -X POST https://api.postal.so/emails \
-H "Authorization: Bearer $POSTAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Loja Exemplo <[email protected]>",
"to": ["[email protected]"],
"subject": "Seu pedido #10482 saiu para entrega",
"html": "<p>O pedido <b>#10482</b> está a caminho.</p>"
}'
Node.js
const response = await fetch('https://api.postal.so/emails', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: 'Loja Exemplo <[email protected]>',
to: ['[email protected]'],
subject: 'Seu pedido #10482 saiu para entrega',
html: '<p>O pedido <b>#10482</b> está a caminho.</p>',
}),
});
const data = await response.json();
Python
import os
import requests
response = requests.post(
"https://api.postal.so/emails",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
json={
"from": "Loja Exemplo <[email protected]>",
"to": ["[email protected]"],
"subject": "Seu pedido #10482 saiu para entrega",
"html": "<p>O pedido <b>#10482</b> está a caminho.</p>",
},
timeout=10,
)
data = response.json()
PHP
<?php
$ch = curl_init('https://api.postal.so/emails');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('POSTAL_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'from' => 'Loja Exemplo <[email protected]>',
'to' => ['[email protected]'],
'subject' => 'Seu pedido #10482 saiu para entrega',
'html' => '<p>O pedido <b>#10482</b> está a caminho.</p>',
]),
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
echo $status === 200 ? $data['id'] : $data['message'];
Laravel
// config/services.php
'postal' => [
'key' => env('POSTAL_API_KEY'),
],
// Em qualquer lugar da aplicação
use Illuminate\Support\Facades\Http;
$response = Http::withToken(config('services.postal.key'))
->withHeaders(['Idempotency-Key' => 'order-10482-shipped'])
->post('https://api.postal.so/emails', [
'from' => 'Loja Exemplo <[email protected]>',
'to' => ['[email protected]'],
'subject' => 'Seu pedido #10482 saiu para entrega',
'html' => view('emails.order-shipped', ['order' => $order])->render(),
])
->throw();
$emailId = $response->json('id');
La respuesta trae el ID del correo. Si algo está mal, recibes un error con el motivo, como 422 validation_error o 403 para un dominio no verificado.
{
"id": "019a1b2c-4d5e-7f60-8a9b-0c1d2e3f4a5b"
}
Laravel con el Mail del framework
¿Prefieres seguir usando Mail::to() y Mailables? Configura el mailer SMTP con tu clave y no cambia nada más en el código.
#4. Sigue la entrega
Consulta el correo para ver el estado y los eventos (sent, delivered, opened…):
cURL
curl https://api.postal.so/emails/019a1b2c-4d5e-7f60-8a9b-0c1d2e3f4a5b \
-H "Authorization: Bearer $POSTAL_API_KEY"
Node.js
const response = await fetch('https://api.postal.so/emails/019a1b2c-4d5e-7f60-8a9b-0c1d2e3f4a5b', {
headers: {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
},
});
const data = await response.json();
Python
import os
import requests
response = requests.get(
"https://api.postal.so/emails/019a1b2c-4d5e-7f60-8a9b-0c1d2e3f4a5b",
headers={"Authorization": f"Bearer {os.environ['POSTAL_API_KEY']}"},
timeout=10,
)
data = response.json()
PHP
$client = new \GuzzleHttp\Client(['base_uri' => 'https://api.postal.so']);
$response = $client->get('emails/019a1b2c-4d5e-7f60-8a9b-0c1d2e3f4a5b', [
'headers' => ['Authorization' => 'Bearer '.getenv('POSTAL_API_KEY')],
]);
$data = json_decode($response->getBody(), true);
En producción, en lugar de consultar, registra un webhook y recibe cada evento en cuanto ocurre. Para consultar el estado por la API, la clave necesita acceso total.
#Próximos pasos
- Evita envíos duplicados en los reintentos con la
Idempotency-Key. - Arma el contenido en el panel y envía con plantillas y variables.
- Envía hasta 100 correos por solicitud con el envío en lote.
- Prueba la integración y los webhooks sin enviar de verdad, con las direcciones de prueba (
[email protected],[email protected]…). - Conoce los límites de tu plan.