Markdown
Guia · integração

Do envio à confirmação de entrega

Um aviso de pedido com referência própria, proteção contra duplicação e atualização de status pelo webhook.

Os dados e nomes de template são ilustrativos. As funções de banco e fila representam operações que você implementa no seu sistema; não são endpoints da Patrocinio Tech.

O fluxo em quatro etapas (link para esta seção)

EtapaResultado
1. PrepararTelefone normalizado, template compatível e operação gravada antes do envio.
2. EnviarAceite da Meta associado ao seu pedido e ao message_id.
3. Receber eventosStatus confirmado no seu banco, sem aplicar eventos repetidos.
4. Recuperar eventosEntregas do webhook que falharam reenfileiradas após corrigir o receptor.

1. Prepare a operação (link para esta seção)

Consulte o template do número de envio. Confira o consentimento do contato e salve sua operação com uma chave única antes de chamar a API.

No seu registroExemplo
Referência da operaçãopedido-8421-aviso-entrega
Chave de idempotênciapedido-8421-aviso-entrega-v1
Dados de envioDestinatário, phone_number_id, template, idioma e variáveis.
Estado inicialPendente. Registre o resultado de cada tentativa sem substituir a chave original.
Normalizar o telefone antes de enviar
cURL · validar telefone
curl -X POST https://api.patrociniotech.com/public/v1/validate \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{"to": "(21) 99999-9999", "country": "BR"}'

Quando data.valid for true, use o telefone de data.to. Em caso contrário, corrija o cadastro. A validação confirma o formato, não a existência no WhatsApp.

2. Envie e registre o aceite (link para esta seção)

O modelo abaixo usa duas variáveis numeradas: nome e pedido. Mantenha o mesmo corpo e a mesma chave ao repetir esta operação.

cURL · enviar aviso
curl -X POST https://api.patrociniotech.com/public/v1/messages \
  -H "Authorization: Bearer SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-8421-aviso-entrega-v1" \
  -d '{
    "to": "5521999999999",
    "phone_number_id": "SEU_NUMERO_ID",
    "template": "aviso_entrega",
    "language": "pt_BR",
    "variables": ["Maria", "8421"],
    "client_ref": "pedido-8421-aviso-entrega"
  }'
JSON · envio aceito
{
  "success": true,
  "data": {
    "message_id": "wamid.EXEMPLO",
    "status": "sent",
    "to": "5521999999999",
    "client_ref": "pedido-8421-aviso-entrega"
  }
}

Associe message_id à operação gravada. client_ref volta no webhook para ajudar na conciliação, mas não substitui a chave de idempotência.

sent significa aceite da Meta. O relatório só deve contar como entregue após o evento correspondente. Em falha de conexão ou resultado incerto, preserve a operação e use a política de novas tentativas.

Para uma fila de envios, aplique o limite de 600 requisições por minuto por chave ao conjunto dos workers. Somar vários processos com limites separados pode ultrapassar o teto.

3. Receba e processe o webhook (link para esta seção)

Configure o endpoint em Integrações. Verifique a assinatura sobre o corpo original, grave o evento em uma fila durável e só então responda 200.

JSON · confirmação de entrega
{
  "event": "message.status",
  "occurred_at": "2026-10-06T14:02:11Z",
  "delivery_id": "8814",
  "data": {
    "message_id": "wamid.EXEMPLO",
    "status": "delivered",
    "status_rank": 3,
    "to": "5521999999999",
    "phone_number_id": "SEU_NUMERO_ID",
15 linhas
Node.js · recepção com fila durável
// Configure req.rawBody e assinaturaValida conforme a página Webhook.
app.post("/webhooks/patrociniotech", async (req, res) => {
  if (!assinaturaValida(req, process.env.PT_WEBHOOK_SECRET)) return res.sendStatus(401);
  const { delivery_id, event } = req.body;
  if (!delivery_id || !["message.status", "message.received"].includes(event)) {
    return res.sendStatus(400);
  }
  try {
    await inserirEventoSeNovo({
      integracao: "patrociniotech",
18 linhas
Node.js · processamento da fila
async function processarEvento(evento) {
  await transacao(async (tx) => {
    const item = await tx.bloquearEvento(evento.id);
    if (item.processado) return;
    const { event, data } = item.corpo;
    if (event === "message.status" && !data.test) {
      // Atualize por message_id, client_ref e número da empresa.
      // sent < delivered < read; failed pode substituir sent,
      // mas não pode apagar uma entrega ou leitura confirmada.
      await tx.atualizarStatusSemRegressao(data);
16 linhas
Implemente os índices únicos, a fila e as transações no seu banco. Se o evento chegar antes da resposta do envio, mantenha-o para conciliação posterior. Efeitos externos, como emitir um bilhete, precisam de uma operação própria com idempotência.

4. Recupere eventos que falharam (link para esta seção)

A fila tenta entregar os eventos por cerca de 31 horas, com pausas progressivas. Se as tentativas esgotarem, corrija o receptor antes de solicitar o reenvio.

cURL · consultar eventos com falha
curl "https://api.patrociniotech.com/public/v1/deliveries?status=failed&limit=200" \
  -H "Authorization: Bearer SUA_CHAVE"
cURL · reenfileirar eventos com falha
curl -X POST "https://api.patrociniotech.com/public/v1/deliveries/retry-failed" \
  -H "Authorization: Bearer SUA_CHAVE"
Reenviar uma entrega do webhook repete o evento para o seu servidor. Isso não envia outra mensagem ao contato. O receptor deve reconhecer o mesmo delivery_id. Veja paginação e reenvio de entregas.

Estados no seu sistema (link para esta seção)

EstadoEvidência
AceitaResposta do envio com message_id e status sent.
Entregue / lidaEvento message.status com delivered ou read, conciliado com a operação.
FalhouRecusa confirmada ou evento failed. Guarde error.code e error.reason quando presentes.
Aguardando confirmaçãoSem evidência suficiente do resultado. Preserve a operação e investigue; não presuma falha nem gere outro envio.