Começando

Primeiros passos

Do zero ao primeiro e-mail entregue: verifique um domínio, crie uma chave e faça um POST /emails.

#1. Verifique um domínio

A Postal só envia de domínios que você comprovou controlar. No painel, em Domínios, adicione o domínio (por exemplo, lojaexemplo.com.br) e crie no seu provedor de DNS os registros mostrados: um TXT de DKIM e um MX e um TXT para o Return-Path. A verificação costuma levar poucos minutos. Detalhes em Domínios e DNS.

#2. Crie uma chave de API

Em Chaves de API, crie uma chave só de envio e copie o token (ele aparece uma vez). Guarde-o numa variável de ambiente:

Terminal
export POSTAL_API_KEY="ps_sua_chave"

#3. Envie o primeiro e-mail

Troque o remetente por um endereço do seu domínio verificado e o destinatário pelo seu e-mail:

POST /emails

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');

A resposta traz o ID do e-mail. Se algo estiver errado, você recebe um erro com o motivo, como 422 validation_error ou 403 para um domínio não verificado.

200Resposta
{
  "id": "019a1b2c-4d5e-7f60-8a9b-0c1d2e3f4a5b"
}

Laravel com o Mail do framework

Prefere continuar usando Mail::to() e Mailables? Configure o mailer SMTP com a sua chave e nada mais muda no código.

#4. Acompanhe a entrega

Consulte o e-mail para ver o status e os eventos (sent, delivered, opened…):

GET /emails/{id}

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);

Em produção, em vez de consultar, cadastre um webhook e receba cada evento assim que ele acontece. Para consultar o status pela API, a chave precisa de acesso total.

#Próximos passos

  • Evite envios duplicados em novas tentativas com a Idempotency-Key.
  • Monte o conteúdo no painel e envie com templates e variáveis.
  • Envie até 100 e-mails por requisição com o envio em lote.
  • Conheça os limites do seu plano.