Messages

Messages

POST /v1/messages (envia template/texto/mídia) e GET /v1/messages/{id} (consulta status).

POST /v1/messages

Envia uma mensagem: template, text, mídia (image/video/document/audio/sticker) ou mensagem interativa (reaction/location/contact/cta_url/buttons/list).

POST /v1/messages 201400401402403404409422429

Headers: Idempotency-Key (opcional, recomendado).

Body (JSON):

{
  "to": "+5511999990000",
  "type": "template",
  "account_id": "ckv...",
  "template": { "name": "boas_vindas", "language": "pt_BR", "components": [] }
}
Campo Tipo Obrigatório Regras
to string Sim E.164. Regex ^\+?[1-9]\d{7,14}$. Normalizado internamente
type enum Sim template | text | image | video | document | audio | sticker | reaction | location | contact | cta_url | buttons | list
account_id string Não Conexão; default = conexão padrão do usuário
template object Não Obrigatório se type=template. { name (≥1), language (≥1), components? }
text object Não Obrigatório se type=text. { body } — 1 a 4096 chars
media object Não Obrigatório para image/video/document/audio/sticker. { id (≥1), caption? (≤1024), filename? (≤255, só document) }. Sticker exige image/webp 512x512
reaction object Não Obrigatório se type=reaction. { messageId, emoji } — messageId é o id da mensagem recebida (não o meta_message_id); emoji vazio remove a reação
location object Não Obrigatório se type=location. { latitude, longitude, name?, address? }
contacts array Não Obrigatório se type=contact. [{ formattedName, firstName, phones: [{ phone, type? }] }] — firstName é obrigatório (a Meta rejeita formattedName sozinho)
ctaUrl object Não Obrigatório se type=cta_url. { body, displayText, url } — url precisa ser https://
buttons object Não Obrigatório se type=buttons. { body, buttons: [{ id, title }] } — máx 3 botões, title <=20 chars
list object Não Obrigatório se type=list. { body, buttonText, sections: [{ title?, rows: [{ id, title, description? }] }] } — máx 10 rows somando todas as sections
carousel object Não Opcional, só com type=template de template criado com componente CAROUSEL. { cards: [{ mediaId, type? }] } — type é image (default) ou video, 2 a 10 cards

media.id é o media_id obtido em POST /v1/media.

Carrossel: para enviar um template carrossel, primeiro crie o template com componente CAROUSEL (categoria MARKETING obrigatóriaUTILITY é rejeitado pela Meta com 400; templates MARKETING passam por revisão mais rigorosa, com PENDING >4h observado e sem SLA — planeje o tempo de aprovação). No envio, suba a mídia de cada card via POST /v1/media e passe os media_id em carousel.cards, na mesma ordem dos cards do template.

{
  "to": "+5511999990000",
  "type": "template",
  "template": { "name": "promo_carousel", "language": "pt_BR" },
  "carousel": { "cards": [{ "mediaId": "media_1" }, { "mediaId": "media_2" }] }
}

Checagens pré-envio (nesta ordem)

  1. Conta existe e pertence ao dono da chave → senão 404 ACCOUNT_NOT_FOUND.
  2. Assinatura ACTIVE ou GRACE válida → senão 402 SUBSCRIPTION_REQUIRED.
  3. Cap diário do tier não atingido → senão 429 TIER_DAILY_CAP_REACHED.
  4. Contato não optou por sair → senão 403 CONTACT_OPTED_OUT.
  5. Para não-template: houve inbound do contato nas últimas 24h → senão 409 WINDOW_CLOSED.

Templates aprovados ignoram a janela de 24h. Texto e mídia exigem janela aberta.

Resposta 201

Resposta 201

{
"id": "msg_ckv...",
"meta_message_id": "wamid.HBgM...",
"to": "+5511999990000",
"status": "sent"
}
CampoDescrição
idID interno (consultar em GET /v1/messages/{id})
meta_message_idID da mensagem na Meta (casa com os webhooks)
toTelefone normalizado (E.164)
statusSempre "sent". Mudanças de status chegam via webhook.

Exemplo

curl -X POST https://api.wablastmessage.com/v1/messages \
-H "Authorization: Bearer wak_sua_chave" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9f1c-7b22-aa01" \
-d '{
  "to": "+5511999990000",
  "type": "text",
  "text": { "body": "Olá! Sua entrega chegou." }
}'

GET /v1/messages/{id}

Consulta o status de uma mensagem.

GET /v1/messages/{id} 200401404429

Path: id (string, obrig.) — ID interno da mensagem.

Só consulta mensagens enviadas pela API pública. Mensagens disparadas pelo painel ou por campanhas retornam 404 MESSAGE_NOT_FOUND aqui — não é bug, é escopo do endpoint.

Resposta 200

Resposta 200

{
"id": "msg_ckv...",
"status": "DELIVERED",
"meta_message_id": "wamid.HBgM...",
"sent_at": "2026-06-22T14:03:11.000Z",
"error_code": null,
"error_message": null,
"created_at": "2026-06-22T14:03:10.000Z"
}

statusSENT | DELIVERED | READ | FAILED. error_code/error_message preenchidos só em falha.


POST /v1/messages/{id}/read

Marca uma mensagem recebida (inbound) como lida — o contato vê o duplo-check azul.

POST /v1/messages/{id}/read 200401404409429

Path: id (string, obrig.) — id da mensagem recebida (do webhook message.received), não o meta_message_id.

409 ACCOUNT_TOKEN_INVALID indica que o token da conexão está inválido — reconecte a conta antes de tentar de novo.

Resposta 200

Resposta 200

{ "success": true }

Exemplo

curl -X POST https://api.wablastmessage.com/v1/messages/msg_ckv.../read \
-H "Authorization: Bearer wak_sua_chave"

POST /v1/messages/{id}/typing

Mostra “digitando…” para o contato por até 25s ou até a próxima mensagem enviada.

POST /v1/messages/{id}/typing 200401404409429

Path: id (string, obrig.) — id da mensagem recebida.

A Meta exige marcar a mensagem como lida na mesma chamada — este endpoint já faz isso por você. 409 ACCOUNT_TOKEN_INVALID indica token da conexão inválido.

Resposta 200

Resposta 200

{ "success": true }

Exemplo

curl -X POST https://api.wablastmessage.com/v1/messages/msg_ckv.../typing \
-H "Authorization: Bearer wak_sua_chave"
Pular para o conteúdo