O envio é feito com POST /v1/messages. A API envia mensagens apenas para leads que já existem na sua empresa — se o destinatário não for um lead, a resposta é 404 lead_not_found. Para registrar um lead novo antes do envio, use POST /v1/leads.
O destinatário (to)
O campo to aceita dois formatos:
| Formato | Exemplo | Quando usar |
|---|
| Telefone E.164 | +5511999999999 | Caso comum: o lead tem telefone conhecido. |
| BSUID | BR.1349120865... | Leads que chegaram por username do WhatsApp, sem telefone exposto. |
Números brasileiros: a API resolve automaticamente a variação do nono dígito. Se o lead foi salvo sem o 9 (ou com), o envio funciona nas duas formas — você não precisa normalizar.
Tipos de mensagem
O campo type define o corpo que acompanha a requisição:
type | Corpo | Observações |
|---|
text | text.body | Texto livre, até 4096 caracteres. Requer janela de 24h aberta. |
template | template.name, template.language.code, template.components | Único tipo permitido fora da janela de 24h. |
image, video, audio, document, sticker | {tipo}.link (+ caption/filename) | Mídia por URL pública. Requer janela de 24h aberta. |
location | location.latitude, location.longitude | Coordenadas, com name/address opcionais. |
contacts | contacts[] | Cartões de contato. |
interactive | interactive | Botões e listas do WhatsApp. |
reaction | reaction.message_id, reaction.emoji | Reação a uma mensagem existente. |
Exemplo com template e variáveis:
curl -X POST https://api.superlead.app/v1/messages \
-H "Authorization: Bearer sl_live_SUA_CHAVE" \
-H "Content-Type: application/json" \
-d '{
"to": "+5511999999999",
"type": "template",
"template": {
"name": "confirmacao_consulta",
"language": { "code": "pt_BR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "João" },
{ "type": "text", "text": "quinta, 10h" }
]
}
]
}
}'
Liste os templates aprovados da sua conta com GET /v1/templates — o nome e o idioma precisam bater exatamente com o template aprovado na Meta.
Enviando mídia
Mídia é enviada por link: você hospeda o arquivo e passa a URL — o WhatsApp baixa do seu servidor no momento do envio.
curl -X POST https://api.superlead.app/v1/messages \
-H "Authorization: Bearer sl_live_SUA_CHAVE" \
-H "Content-Type: application/json" \
-d '{
"to": "+5511999999999",
"type": "image",
"image": { "link": "https://seusite.com/arquivos/orcamento.jpg", "caption": "Seu orçamento" }
}'
Requisitos do link:
- Público — sem autenticação, token ou página intermediária; a URL deve apontar direto para o arquivo.
- Content-Type correto — o servidor deve responder com o MIME type real do arquivo.
Limites impostos pelo WhatsApp, por tipo:
| Tipo | Tamanho máximo | Formatos aceitos |
|---|
image | 5 MB | JPEG, PNG (WebP não — use sticker) |
video | 16 MB | MP4/3GPP (vídeo H.264, áudio AAC) |
audio | 16 MB | AAC, MP3, M4A, AMR, OGG (opus) |
document | 100 MB | PDF, Office, texto e afins (use filename) |
sticker | 100 KB (500 KB animado) | WebP |
Como no caso da janela de 24h, a validação da mídia pode ser assíncrona: o envio retorna 201 accepted e, se o arquivo for grande demais, o formato não for suportado ou o link estiver inacessível, a mensagem vira failed com error.code: media_unsupported (código 131052/131053 da Meta). Acompanhe pelo webhook ou por GET /v1/messages/{id}.
A janela de 24 horas
O WhatsApp só permite mensagens de formato livre (texto, mídia) se o lead enviou mensagem para você nas últimas 24 horas. Fora dessa janela, apenas templates aprovados.
A Meta pode aceitar um envio fora da janela (você recebe 201 com status: accepted) e falhá-lo de forma assíncrona segundos depois. Um 201 não garante entrega — consulte o status da mensagem antes de considerar o envio concluído.
Quando a rejeição é síncrona, você recebe 422 outside_24h_window na hora. Quando é assíncrona, a mensagem aparece como failed na consulta de status, com o motivo em error.
Acompanhar o status da mensagem
O ciclo de vida de uma mensagem enviada:
accepted → sent → delivered → read
└→ failed
O jeito recomendado de acompanhar é por webhook: o evento whatsapp.message.status chega na sua URL a cada transição, incluindo as falhas assíncronas, sem polling. Para consultas pontuais ou reconciliação, use o id retornado no envio:
curl https://api.superlead.app/v1/messages/msg_SEU_ID \
-H "Authorization: Bearer sl_live_SUA_CHAVE"
Mensagens com status: failed trazem o motivo no campo error, com o código estável do catálogo de erros e o código numérico original da Meta:
{
"id": "msg_9f8e7d6c-1a2b-3c4d-5e6f-7a8b9c0d1e2f",
"status": "failed",
"error": {
"code": "outside_24h_window",
"upstream_code": 131047
}
}
Para reconciliar envios com o seu sistema, mande um external_id (por exemplo, o id do pedido) no corpo do envio — ele volta na resposta e na consulta de status. Use o header Idempotency-Key para poder repetir a requisição com segurança; veja Idempotência.
O que aparece no painel
Mensagens enviadas pela API entram no histórico de conversa do lead no painel da Superlead com o selo via API, o status real de entrega e, em caso de falha, o motivo. Templates aparecem com o corpo renderizado (variáveis substituídas), não apenas o nome.