API REST simples ou SMTP Relay com o token como senha. Cada mensagem deixa rastro completo: sent → delivered → opened → clicked → bounced. Webhooks HMAC com retry. Sandbox pra rodar CI/CD sem queimar crédito.
Todos os emails enviados pela API com timeline de eventos
Quando o cliente compra, esquece a senha ou recebe uma notificação crítica, o email precisa chegar em segundos. Não é hora de descobrir que o provedor caiu, que o IP foi blacklistado ou que o webhook não disparou.
Password reset que demora 5 minutos vira ticket no suporte. Recibo que não chega vira chargeback.
"O email foi enviado?" sem timeline real, sem webhook de delivered/bounced, vira chute.
CI rodando 200x por dia, cada teste subindo um envio real no contador. No fim do mês, surpresa na fatura.
POST JSON ou SMTP autenticado, você escolhe. O mesmo token Bearer funciona nos dois canais. Idempotency-Key opcional pra retry seguro: se sua rede caiu no meio, o segundo POST retorna o mesmo message_id sem reenviar.
# Password reset, 1 request
curl -X POST https://api.ravimail.com.br/v1/transactional/send \
-H "Authorization: Bearer rvm_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pwd-reset-9382" \
-d '{
"to": "joao@empresa.com.br",
"from": "noreply@seudominio.com.br",
"subject": "Redefina sua senha",
"html": "<a href=\"https://app.io/reset/abc\">Resetar</a>",
"tags": {"category": "password_reset", "user_id": "9382"}
}'
# Resposta síncrona
{ "data": { "message_id": "msg_8aJ9w2x", "status": "sent" } }
// composer require ravisystems/ravimail-php
use Ravimail\Client;
$rm = new Client('rvm_live_...');
$rm->transactional->send([
'to' => 'joao@empresa.com.br',
'from' => 'noreply@seudominio.com.br',
'subject' => 'Recibo do pedido #4729',
'html' => $html,
'tags' => ['order_id' => '4729'],
'attachments' => [
['file_id' => 'file_abc123'],
],
], idempotencyKey: 'order-4729-receipt');
// fetch nativo, sem SDK
await fetch('https://api.ravimail.com.br/v1/transactional/batch', {
method: 'POST',
headers: {
'Authorization': 'Bearer rvm_live_...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
messages: [
{ to: 'ana@a.com', subject: 'Recibo', html: '...' },
{ to: 'bruno@b.com', subject: 'Recibo', html: '...' }
// até 1000 mensagens, retorno 207 Multi-Status
]
})
});
# Não quer mexer no código? Use SMTP Relay direto.
# Mesmo token, autenticação SASL PLAIN.
Host: smtp.ravimail.com.br
Porta: 587 (STARTTLS)
Username: api
Password: rvm_live_... # token completo no campo senha
# Pronto. Funciona em qualquer cliente: Laravel,
# WordPress, n8n, Zapier, Postfix, Sendmail, etc.
# Limite por mensagem: 30 MB.
Clique em qualquer linha do Activity Feed e veja exatamente o que aconteceu, em que ordem, e quais webhooks foram disparados.
msg_8aJ9w2x
RJ-01200.221.x.12seudominio.com.brcategory: password_resetuser_id: 9382Tudo o que aparece nesse painel também volta na resposta da API e nos webhooks. Mesma fonte de dados, três canais de leitura.
Recursos reais do RaviMail, validados em produção.
POST JSON ou SMTP autenticado. O mesmo token vale pros dois. Você escolhe sem retrabalho.
POST /v1/transactional/send · smtp.ravimail.com.br:587
Envie até mil mensagens em um único request. Retorno 207 Multi-Status com sucesso e erro por linha.
POST /v1/transactional/batch
Header opcional. Retry seguro: chamadas duplicadas retornam o mesmo message_id sem reenvio.
Header: Idempotency-Key
Suba arquivos via /v1/files e referencie pelo file_id. Suporta PDF, imagens, ZIP, CSV.
attachments: [{file_id}]
Pixel de open e rewrite de links automático. Subdomínio per-user isola sua reputação dos outros.
i{userId}.ravimail.com.br/track/*
Assinatura SHA-256 ou SHA-512. 12 retries com backoff exponencial (1s até 24h). Log completo.
X-Ravimail-Signature: t=...,v2=...
Quer ver os eventos chegando ao vivo? GET /v1/events/stream entrega via Server-Sent Events.
GET /v1/events/stream
Token só com transactional:send? Pode. Token só com webhooks:read? Pode. IP whitelist por token em CIDR.
transactional:send · suppression:write
Força um domínio, IP ou nó específico via campo route. Útil pra A/B de infraestrutura.
route: { domain_id, ip_id, node_id }
Rodar CI/CD em provedor de email cobrava por cada teste, ou pior: nem reproduzia bounce.
No RaviMail, endereços pré-definidos do simulator retornam eventos determinísticos.
Todo token rvm_test_* roda em sandbox isolado: não cobra crédito, não envia, mas registra tudo (e dispara webhooks reais).
# Endereços determinísticos pra CI/CD
success@simulator.ravimail.com.br # delivered
bounce@simulator.ravimail.com.br # hard bounce
soft-bounce@simulator.ravimail.com.br # soft bounce + retry
complaint@simulator.ravimail.com.br # marca como spam
suppress@simulator.ravimail.com.br # vai pra supressão
opened@simulator.ravimail.com.br # delivered + open
clicked@simulator.ravimail.com.br # delivered + open + click
# Trigger manual via API (sandbox token)
curl -X POST https://api.ravimail.com.br/v1/sandbox/trigger-event \
-H "Authorization: Bearer rvm_test_..." \
-d '{"message_id":"msg_sb_xy","event":"bounced"}'
# Webhook chega assinado mesmo em sandbox
POST /seu-webhook
X-Ravimail-Signature: t=1700000000,v2=...
{
"event": "transactional.bounced",
"message_id": "msg_sb_xy",
"reason": "mailbox_full",
"_sandbox": true
}
Dashboard por endpoint com success rate de 7 dias, latência média, sparkline visual e log de cada delivery individual com replay.
https://app.io/webhooks/ravimail
passe o mouse na linha amarela pra ver a cadeia de retry
| Status | Event | Try | HTTP | Lat | Quando |
|---|---|---|---|---|---|
| # |
transactional.sent
transactional.delivered
transactional.opened
transactional.clicked
transactional.bounced
transactional.complained
Rotacionar emite novo segredo. O anterior continua válido por 24h pra atualizar o handler sem downtime
(header extra X-Ravimail-Signature-Prev).
Não precisa trocar nada no seu código existente. O SMTP Relay do RaviMail aceita o mesmo token Bearer como senha SASL PLAIN. Tracking, webhooks, suppression list, tudo continua funcionando: a infraestrutura é a mesma da API REST.
# config/mail.php usa essas variáveis
MAIL_MAILER=smtp
MAIL_HOST=smtp.ravimail.com.br
MAIL_PORT=587
MAIL_USERNAME=api
MAIL_PASSWORD=rvm_live_xxxxxxxxxxxxxx
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="noreply@seudominio.com.br"
MAIL_FROM_NAME="Meu App"
# Pronto. Mail::send() funciona normal.
Dúvidas técnicas comuns antes de migrar pro RaviMail.
Cadastro em 30 segundos. Token sandbox liberado na hora. Sem cartão de crédito pra começar.