WhatsApp APIAPI

WhatsApp: enviar mensagens pela API

Envie texto, imagem, vídeo, áudio, documento, figurinha, localização, botões e lista no WhatsApp pela API da XBASE, na janela de 24 horas.

Atualizado em

POST /whatsapp/messages envia uma mensagem livre a um contato, dentro da janela de 24 horas. Fora dela, envie um template.

Enviar uma mensagem

POST https://api.xbase.app/api/external/v1/whatsapp/messages
CampoTipoObrigatórioRegra
numberIdtextosimNúmero que envia (listar os números)
totextosimTelefone do contato com DDI, 8 a 15 dígitos. +, espaços, hífens e parênteses são removidos
typetextosimtext, image, video, audio, document, sticker, location, buttons, list ou flow
objeto do tipoobjetosimUm campo com o mesmo nome do type, como "text": { "body": "…" }. Veja cada tipo abaixo
curl -X POST https://api.xbase.app/api/external/v1/whatsapp/messages \
  -H "Authorization: Bearer $XBASE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
    "to": "5521999990000",
    "type": "text",
    "text": { "body": "Seu pedido saiu para entrega e chega hoje até as 18h." }
  }'

A resposta está em Resposta. Campo a mais no corpo é recusado com 400.

Texto

{
  "numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
  "to": "5521999990000",
  "type": "text",
  "text": { "body": "Olá, Maria! Como posso ajudar?" }
}

text.body tem de 1 a 4.096 caracteres. Links no texto aparecem clicáveis no WhatsApp.

Mídia

Imagem, vídeo, áudio, documento e figurinha vão por URL https pública: a Meta baixa o arquivo dela. URL http, com usuário e senha, ou de endereço interno ou de rede privada responde 400.

{
  "numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
  "to": "5521999990000",
  "type": "image",
  "image": {
    "link": "https://cdn.minhaempresa.com.br/catalogo/tenis-azul.jpg",
    "caption": "Tênis azul, tamanhos 38 a 44"
  }
}
typeObjetoRegras da Meta
imagelink, captionJPEG ou PNG, até 5 MB
videolink, captionMP4 ou 3GP, até 16 MB
audiolink, voiceAAC, MP3, MP4 ou OGG, até 16 MB. "voice": true mostra como nota de voz, e o arquivo tem de ser OGG com codec Opus
documentlink, filename, captionQualquer arquivo, até 100 MB. filename (até 240 caracteres) é o nome que o contato vê
stickerlinkWebP de 512 × 512 pixels

caption é opcional, com até 1.024 caracteres.

Localização

{
  "numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
  "to": "5521999990000",
  "type": "location",
  "location": {
    "latitude": -23.5614,
    "longitude": -46.6559,
    "name": "Loja Paulista",
    "address": "Av. Paulista, 1000, São Paulo"
  }
}
CampoRegra
location.latitudeDe −90 a 90
location.longitudeDe −180 a 180
location.name · location.addressOpcionais, até 1.000 caracteres

Botões

{
  "numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
  "to": "5521999990000",
  "type": "buttons",
  "buttons": {
    "header": "Pedido 12345",
    "body": "Podemos confirmar a entrega para amanhã?",
    "footer": "Toque numa opção",
    "buttons": [
      { "id": "confirmar", "title": "Confirmar" },
      { "id": "remarcar", "title": "Remarcar" }
    ]
  }
}
CampoRegra
buttons.bodyTexto da mensagem, até 1.024 caracteres
buttons.header · buttons.footerOpcionais, até 60 caracteres
buttons.buttonsDe 1 a 3 botões. id (até 256 caracteres, sem repetir) volta quando o contato toca; title tem até 20 caracteres

Lista

{
  "numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
  "to": "5521999990000",
  "type": "list",
  "list": {
    "body": "Escolha o horário da entrega.",
    "button": "Ver horários",
    "rows": [
      { "id": "manha", "title": "Manhã", "description": "Das 8h às 12h" },
      { "id": "tarde", "title": "Tarde", "description": "Das 13h às 18h" }
    ]
  }
}
CampoRegra
list.bodyTexto da mensagem, até 1.024 caracteres
list.buttonTexto do botão que abre a lista, até 20 caracteres
list.rowsDe 1 a 10 linhas. id (até 200 caracteres, sem repetir) volta quando o contato escolhe; title até 24 caracteres; description opcional, até 72
list.header · list.footerOpcionais, até 60 caracteres

O botão tocado ou a linha escolhida chega como whatsapp.message.received nos webhooks do workspace, com o id que você mandou.

Flow

Para abrir um WhatsApp Flow (formulário dentro do WhatsApp), use "type": "flow". Os campos e um exemplo estão em Flows.

Resposta

Resposta 200:

{
  "status": "accepted",
  "messageId": "wamid.HBgNNTUyMTk5OTk5MDAwMBUCABEYEjQ1QzM1RkQ2RDhGNjZBMDQ3MwA=",
  "threadId": "c1d7f0b2-5a4e-4f3d-9c2b-1a0e9d8c7b6a",
  "dialogId": "5a0e4c31-7b2d-4e8f-a1c3-9d6b5e4f3a21"
}
CampoDescrição
statusaccepted: a Meta aceitou o envio. Entrega e leitura chegam depois, nos eventos de webhook
messageIdId da mensagem na Meta (wamid.…). Vai na reação e aparece nos eventos
threadIdConversa do contato na XBASE
dialogIdMensagem na conversa

Erros

StatuscodeQuando
400(sem code)Campo inválido: telefone, type desconhecido, texto vazio ou longo demais, URL http ou interna, campo a mais. A message diz qual
404NUMBER_NOT_FOUNDO número não existe neste workspace
422NUMBER_DISCONNECTEDO número está desconectado
422WINDOW_CLOSEDFora da janela de 24 horas. Envie um template
422SEND_REJECTEDA XBASE recusou antes de enviar. A message diz o motivo
422META_ERRORA Meta recusou, por exemplo, mídia que ela não conseguiu baixar. details.metaCode traz o código da Meta

No WINDOW_CLOSED, details.reason diz por que a janela está fechada: no_contact_message (o contato nunca escreveu para este número), window_expired (a última mensagem dele tem mais de 24 horas) ou awaiting_template_reply (o último envio foi um template e o contato ainda não respondeu). details.lastContactMessageAt traz a data da última mensagem do contato.

{
  "statusCode": 422,
  "message": "Janela de atendimento de 24h expirada. Envie apenas templates aprovados pelo WhatsApp.",
  "code": "WINDOW_CLOSED",
  "details": { "reason": "window_expired", "lastContactMessageAt": "2026-11-03T14:02:11.000Z" }
}

Perguntas frequentes

Veja também

Nesta página