Mensagens

Um endpoint só, para os dois casos: texto livre dentro da janela de 24h e template aprovado fora dela. O que decide é o corpo que você manda.

POST/public/v1/messages

Texto livre (janela de 24h) (link para esta seção)

Vale quando o contato escreveu para você nas últimas 24 horas. É a regra da Meta, não nossa, e existe para você não virar canal de spam.

curl
curl -X POST https://api.patrociniotech.com/public/v1/messages \
  -H "Authorization: Bearer ptk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "5521999999999",
    "text": "Seu pedido saiu para entrega.",
    "client_ref": "pedido-8421"
  }'

Template aprovado (fora da janela) (link para esta seção)

É o caso de campanha, cobrança e aviso que parte de você. Crie e aprove o template no painel, em Templates, e mande o nome dele aqui. variables preenche {{1}}, {{2}} e assim por diante, na ordem.

curl
curl -X POST https://api.patrociniotech.com/public/v1/messages \
  -H "Authorization: Bearer ptk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "5521999999999",
    "template": "aviso_entrega",
    "language": "pt_BR",
    "variables": ["Maria", "8421"],
    "client_ref": "pedido-8421"
  }'

Campos do corpo (link para esta seção)

CampoObrigatórioO que é
tosimNúmero do destinatário, só dígitos, com país e DDD. Ex.: 5521999999999.
textum dos doisTexto livre. Só funciona dentro da janela de 24h. Até 4096 caracteres.
templateum dos doisNome do template aprovado. Use fora da janela.
languagenãoIdioma do template. Padrão pt_BR.
variablesnãoValores de {{1}} em diante, na ordem. Até 20.
phone_number_idnãoNúmero seu que dispara. Sem ele, usa o número padrão da conta.
client_refnãoSeu identificador (id do pedido, do cliente, da linha da campanha). Volta em todo evento de status.

client_ref: o campo mais útil daqui (link para esta seção)

Sem ele, para saber quem recebeu o quê você precisaria guardar uma tabela de-para entre o id do WhatsApp e o seu registro. Com ele, o seu próprio identificador volta em todo evento do webhook, e o de-para deixa de existir.

Numa campanha, mande a linha da campanha em client_ref. Quando o status chegar, você marca aquela linha direto, sem consultar nada.

Resposta (link para esta seção)

200
{
  "success": true,
  "data": {
    "message_id": "wamid.HBgNNTUyMT...",
    "status": "sent",
    "to": "5521999999999",
    "client_ref": "pedido-8421"
  }
}
status: sent quer dizer que a Meta aceitou o envio, não que a pessoa recebeu. Entrega, leitura e falha chegam depois, pelo webhook. Nunca conte entrega pela resposta deste endpoint.

Não enviar duas vezes (link para esta seção)

Mande o header Idempotency-Key com um valor único por mensagem (um uuid serve). Se a mesma chamada chegar de novo, devolvemos a resposta original em vez de enviar outra vez. Vale por 24 horas.

header
Idempotency-Key: 6f1c2b7e-1f0a-4c3d-9a2b-5e8d1f0a4c3d

Isso existe por um motivo concreto: a resposta só volta depois que falamos com a Meta. Se a sua conexão cair nesse meio, o seu retry natural faria a pessoa receber duas vezes, e a conversa ser cobrada duas vezes. Com a chave, repetir é inofensivo. A resposta repetida vem com idempotent_replay: true.

Validar o número antes (link para esta seção)

POST/public/v1/validate

Confere o formato do número (DDI errado, tamanho errado, digitação) e devolve normalizado, pronto para usar no envio. Útil antes de importar uma lista grande.

curl
curl -X POST https://api.patrociniotech.com/public/v1/validate \
  -H "Authorization: Bearer ptk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"to": "(21) 99999-9999", "country": "BR"}'
Valida o FORMATO, não a existência no WhatsApp: a Cloud API não expõe esse teste. Saber se o número existe de verdade só vem do envio somado ao status que chega no webhook.