Skip to main content

Enviar botões interativos

Não existe um endpoint separado /messages/interactive. Os botões são campos extras (buttons, header, footer) do único endpoint de envio:

Onde os botões são permitidos

  • Envios de template (templateId) — buttons sobrescrevem os botões do próprio template e podem ser combinados com a mídia do template (incluindo video / document; a Meta Cloud API pode rejeitar algumas combinações de botões com vídeo/documento no momento da entrega).
  • Envios de texto livre (text) — buttons junto com o texto; header e footer exigem buttons.
  • Não permitidos no modo de mídia direta pura (media + mediaType sem templateId/text) — veja Enviar uma mensagem.
Até 3 botões por mensagem. Tipos: reply, url, call, copy.
Em números Meta Cloud API, não misture url com reply num envio FREE-FORM. O WhatsApp não tem forma suportada de combinar botão de link com botões de resposta fora de um template — o CTA URL é um tipo próprio de mensagem interativa, e leva um único botão.As duas ordens falham, e uma delas falha em silêncio:Medido em 15/08/2026 na mesma conversa, uma variável por vez: texto puro entregou, só reply entregou, só url foi lido — só a mistura falhou.O que fazer: mande duas mensagens (uma com o botão de link, outra com os de resposta), ou use um template aprovado, onde o conjunto de botões é validado na aprovação. A restrição não vale para números não oficiais (Pilot Status web).

Exemplo: template + botões

Carrossel

Um carrossel de sessão anexa uma fileira horizontal e deslizável de 2 a 10 cartões a um envio de texto livre — sem template e sem aprovação. É um objeto carousel mais um text no nível da mensagem, que se torna o corpo do carrossel. Cada cartão carrega sua própria imagem, um corpo opcional e seus próprios botões de resposta rápida. Carrosséis de sessão funcionam em ambos os tipos de número — Meta Cloud API e não oficiais (Pilot Status web); em números Meta, porém, só são enviados dentro da janela de atendimento de 24 h — fora dela, a Meta recusa texto livre, então use um carrossel de template aprovado (Modelos):
Em números Meta um botão de URL num carrossel de sessão é impossível — a Meta retorna 400; os botões do carrossel de sessão da Meta são somente QUICK_REPLY, e a mistura de QUICK_REPLY + URL num mesmo cartão é permitida apenas num carrossel de template (Modelos). Em números não oficiais (Pilot Status web) um botão URL funciona no avulso — ele vira um botão de link nativo.
  • cardTemplate é o esqueleto compartilhado que todo cartão deve seguir — uma única decisão de hasBody e uma única lista de botões (tipos e ordem). Cada cartão preenche apenas sua própria media, seu body e os valores dos botões (text, payload).
  • hasBody é tudo ou nada: se cardTemplate.hasBody for true, todo cartão precisa de um body; se false, nenhum pode ter. Os buttons de cada cartão devem corresponder a cardTemplate.buttons em quantidade, tipo e ordem (os tipos do esqueleto — QUICK_REPLY na Meta, ou URL em números não oficiais).
  • Limites (validados — 422/400 em caso de violação): 2 a 10 cartões; body do cartão até 160 caracteres (em todos os cartões ou em nenhum); até 2 botões por cartão; text do botão (rótulo) até 20 caracteres; payload do botão (id) até 256 caracteres; text obrigatório no nível da mensagem, até 1024 caracteres (o corpo do carrossel).
  • Regra de mídia: media.format é IMAGE; media.url deve ser uma URL https pública terminada em .png, .jpg, .jpeg ou .webp, sem query string. Uma URL inacessível é recusada antes do disparo, com um erro tipado que nomeia o cartão — caso contrário a Meta a aceitaria com 200 e não entregaria nada.
  • Exclusão mútua: carousel exige text e não pode ser combinado com templateId, list, buttons ou um envio de mídia direta (media + mediaType); um header não é permitido (a mídia fica em cada cartão).
  • O toque num botão de resposta rápida do cartão chega como um webhook de entrada normal, exatamente como um botão de resposta — veja Como as respostas de botão chegam abaixo.
Exemplo funcional:

Resposta (202)

Como as respostas de botão chegam

Quando o contato toca em um botão de resposta (reply), você recebe um webhook de entrada normalmessage.reply (ou message.received) — cujo content é o texto do botão (ex.: "Confirmar"), com quotedMessageId apontando para a sua mensagem original.
Não existe um evento ou tipo de mensagem button_reply nem um campo button_id — o id que você define no botão de resposta não é devolvido. Identifique o toque no botão pelo texto em content mais o quotedMessageId (e o correlationId quando presente).
Veja os payloads completos em Eventos de webhook e a lista completa de parâmetros (formato dos objetos de botão, regras de header/footer) em Enviar uma mensagem.