curl --request POST \
--url https://api.wppfy.com/send/menu \
--header 'Content-Type: application/json' \
--header 'token: <api-key>' \
--data '
{
"number": "5511999999999",
"type": "button",
"text": "Como podemos ajudar?",
"choices": [
"Suporte|suporte",
"Fazer pedido|pedido"
]
}
'{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"messageid": "<string>",
"chatid": "<string>",
"sender": "<string>",
"senderName": "<string>",
"isGroup": false,
"fromMe": false,
"messageType": "<string>",
"source": "<string>",
"messageTimestamp": 0,
"status": "<string>",
"text": "",
"quoted": "",
"edited": "",
"reaction": "",
"vote": "",
"convertOptions": "",
"buttonOrListid": "",
"owner": "",
"error": "",
"content": {},
"wasSentByApi": true,
"pinned": true,
"sendFunction": "<string>",
"sendPayload": {},
"fileURL": "<string>",
"callPeer": {
"jid": "<string>",
"name": "<string>",
"imagePreviewUrl": "<string>"
},
"send_folder_id": "<string>",
"track_source": "<string>",
"track_id": "<string>",
"ai_metadata": {
"agent_id": "<string>",
"turn": "<string>",
"flow_id": "<string>",
"request": {
"messages": "<array>",
"tools": "<array>",
"options": {
"model": "<string>",
"temperature": 123,
"maxTokens": 123,
"topP": 123,
"frequencyPenalty": 123,
"presencePenalty": 123
}
},
"response": {
"choices": "<array>",
"toolResults": "<array>",
"error": "<string>"
},
"outcome": {
"status": "sent",
"texts": 123,
"audio": true,
"menus": 123,
"files": 123,
"handoff": "<string>",
"lead": [
"<string>"
],
"detail": "<string>"
}
},
"sender_pn": "<string>",
"sender_lid": "<string>",
"sender_image_preview_url": "<string>",
"response": {
"status": "success",
"message": "Menú enviado correctamente"
}
}{
"error": "Faltan campos obligatorios o tipo de menú inválido"
}{
"error": "Token inválido"
}{
"error": "Límite de solicitudes excedido"
}{
"error": "Error al enviar el menú"
}Enviar menú interactivo (botones, carrusel, lista o encuesta)
Este endpoint ofrece una interfaz unificada para el envío de cuatro tipos principales de mensajes interactivos:
- Botones: Para acciones rápidas y directas
- Carrusel de botones: Para una lista horizontal de botones con imágenes
- Listas: Para menús organizados en secciones
- Encuestas: Para recopilar opiniones y votaciones
Soporte para campos de seguimiento: Este endpoint también admite track_source y track_id documentados en la tag “Enviar Mensaje”.
Estructura base del payload
Todas las solicitudes siguen esta estructura base:
{
"number": "5511999999999",
"type": "button|button_legacy|list|poll|carousel",
"text": "Texto principal da mensagem",
"choices": ["opções baseadas no tipo escolhido"],
"footerText": "Texto do rodapé (opcional para botões e listas)",
"listButton": "Texto do botão (para listas)",
"selectableCount": "Número de opções selecionáveis (apenas para enquetes)"
}
Tipos de mensajes interactivos
1. Botones (type: “button”)
Crea botones interactivos con diferentes funcionalidades de acción.
Campos específicos
footerText: Texto opcional mostrado debajo del mensaje principalchoices: Array de opciones que se convertirán en botones
Formatos de botones
Cada botón puede configurarse usando | (pipe) o \n (salto de línea) como separadores:
-
Botón de respuesta:
"texto|id"o"texto\nid"o"texto"(el ID será igual al texto)
-
Botón de copia:
"texto|copy:código"o"texto\ncopy:código"
-
Botón de llamada:
"texto|call:+5511999999999"o"texto\ncall:+5511999999999"
-
Botón de URL:
"texto|https://exemplo.com"o"texto|url:https://exemplo.com"
Botones con imagen, video o documento
El encabezado del botón puede llevar una imagen, un video o un documento en file, por URL o base64, como en
/send/media. El tipo se obtiene del propio archivo; para forzarlo, envíe mimetype: image, video, document o el MIME type del archivo (por ejemplo, video/mp4). El documento usa el
nombre de docName; sin él, el nombre del archivo.
El audio no se admite en el botón: WhatsApp no tiene audio en el encabezado, y la API responde 400. Envíe el audio antes,
con /send/media. Sin mimetype, la API reconoce el audio por la extensión de la URL o por el inicio del base64; en una
URL sin extensión, indique el mimetype.
{
"number": "5511999999999",
"type": "button",
"text": "Escolha um produto:",
"file": "https://exemplo.com/produto1.jpg",
"choices": [
"Produto A|prod_a",
"Mais Info|https://exemplo.com/produto-a",
"Produto B|prod_b",
"Ligar|call:+5511999999999"
],
"footerText": "Produtos em destaque"
}
{
"number": "5511999999999",
"type": "button",
"text": "Tabela de preços de outubro",
"file": "https://exemplo.com/tabela.pdf",
"docName": "Tabela de preços.pdf",
"choices": ["Quero comprar|comprar", "Falar com vendedor|vendedor"]
}
Si el medio no se descarga o no se sube a WhatsApp, el botón se envía sin él.
Botones en formato legado (type: “button_legacy”)
Use button_legacy solo cuando necesite enviar los botones de respuesta del
formato anterior. El formato de choices es:
"texto|id""texto\nid""texto|reply:id""texto"— el propio texto se usará como ID
Este modo crea solo botones de respuesta. Las acciones de URL, llamada y copia y
el medio en file siguen disponibles en el formato actual type: "button".
{
"number": "5511999999999",
"type": "button_legacy",
"text": "Deseja continuar?",
"choices": [
"Sim|confirmar",
"Não|reply:cancelar"
],
"footerText": "Escolha uma opção"
}
Ejemplo completo
{
"number": "5511999999999",
"type": "button",
"text": "Como podemos ajudar?",
"choices": [
"Suporte Técnico|suporte",
"Fazer Pedido|pedido",
"Nosso Site|https://exemplo.com",
"Falar Conosco|call:+5511999999999"
],
"footerText": "Escolha uma das opções abaixo"
}
Limitaciones y compatibilidad
Importante: Al combinar botones de respuesta con otros tipos (call, url, copy) en el mismo mensaje, se mostrará el aviso: “No es posible mostrar este mensaje en WhatsApp Web. Abra WhatsApp en su teléfono para verlo.”
2. Listas (type: “list”)
Crea menús organizados en secciones con elementos seleccionables.
Campos específicos
listButton: Texto del botón que abre la listafooterText: Texto opcional del pie de páginachoices: Array con las secciones y los elementos de la lista
Formato de las choices
"[Título da Seção]": Inicia una nueva sección"texto|id|descrição": Elemento de la lista con:- texto: Etiqueta del elemento
- id: Identificador único, opcional
- descrição: Texto descriptivo adicional y opcional
Ejemplo completo
{
"number": "5511999999999",
"type": "list",
"text": "Catálogo de Produtos",
"choices": [
"[Eletrônicos]",
"Smartphones|phones|Últimos lançamentos",
"Notebooks|notes|Modelos 2024",
"[Acessórios]",
"Fones|fones|Bluetooth e com fio",
"Capas|cases|Proteção para seu device"
],
"listButton": "Ver Catálogo",
"footerText": "Preços sujeitos a alteração"
}
3. Encuestas (type: “poll”)
Crea encuestas interactivas para votación.
Campos específicos
selectableCount: Número de opciones que pueden seleccionarse (predeterminado: 1)choices: Array simple con las opciones de voto
Ejemplo completo
{
"number": "5511999999999",
"type": "poll",
"text": "Qual horário prefere para atendimento?",
"choices": [
"Manhã (8h-12h)",
"Tarde (13h-17h)",
"Noite (18h-22h)"
],
"selectableCount": 1
}
4. Carousel (type: “carousel”)
Crea un carrusel de tarjetas con imágenes y botones interactivos.
Campos específicos
choices: Array con los elementos del carrusel en el siguiente orden:[Texto do cartão]: Texto de la tarjeta entre corchetes{URL ou base64 da imagem}: Imagen entre llaves- Botones de la tarjeta (uno por línea):
"texto|copy:código"para botón de copiar"texto|https://url"para botón de enlace"texto|call:+número"para botón de llamada
Ejemplo completo
{
"number": "5511999999999",
"type": "carousel",
"text": "Conheça nossos produtos",
"choices": [
"[Smartphone XYZ\nO mais avançado smartphone da linha]",
"{https://exemplo.com/produto1.jpg}",
"Copiar Código|copy:PROD123",
"Ver no Site|https://exemplo.com/xyz",
"Fale Conosco|call:+5511999999999",
"[Notebook ABC\nO notebook ideal para profissionais]",
"{https://exemplo.com/produto2.jpg}",
"Copiar Código|copy:NOTE456",
"Comprar Online|https://exemplo.com/abc",
"Suporte|call:+5511988888888"
]
}
Nota: Creamos otro endpoint para carrusel:
/send/carousel; funciona de la misma forma, pero con otro formato de payload. Elija el que le resulte más sencillo.
Términos de uso
Los recursos de botones interactivos y listas pueden ser descontinuados en cualquier momento sin previo aviso. No nos responsabilizamos por cualquier cambio o indisponibilidad de estos recursos.
Alternativas y compatibilidad
Considerando la naturaleza dinámica de estos recursos, nuestro endpoint fue diseñado para facilitar la migración entre diferentes tipos de mensajes (botones, listas y encuestas).
Recomendamos crear sus flujos de forma flexible, preparados para alternar entre los diferentes tipos.
En caso de descontinuación de algún recurso, podrá migrar fácilmente a otro tipo de mensaje solo cambiando el campo “type” en el payload, manteniendo la misma estructura de choices.
curl --request POST \
--url https://api.wppfy.com/send/menu \
--header 'Content-Type: application/json' \
--header 'token: <api-key>' \
--data '
{
"number": "5511999999999",
"type": "button",
"text": "Como podemos ajudar?",
"choices": [
"Suporte|suporte",
"Fazer pedido|pedido"
]
}
'{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"messageid": "<string>",
"chatid": "<string>",
"sender": "<string>",
"senderName": "<string>",
"isGroup": false,
"fromMe": false,
"messageType": "<string>",
"source": "<string>",
"messageTimestamp": 0,
"status": "<string>",
"text": "",
"quoted": "",
"edited": "",
"reaction": "",
"vote": "",
"convertOptions": "",
"buttonOrListid": "",
"owner": "",
"error": "",
"content": {},
"wasSentByApi": true,
"pinned": true,
"sendFunction": "<string>",
"sendPayload": {},
"fileURL": "<string>",
"callPeer": {
"jid": "<string>",
"name": "<string>",
"imagePreviewUrl": "<string>"
},
"send_folder_id": "<string>",
"track_source": "<string>",
"track_id": "<string>",
"ai_metadata": {
"agent_id": "<string>",
"turn": "<string>",
"flow_id": "<string>",
"request": {
"messages": "<array>",
"tools": "<array>",
"options": {
"model": "<string>",
"temperature": 123,
"maxTokens": 123,
"topP": 123,
"frequencyPenalty": 123,
"presencePenalty": 123
}
},
"response": {
"choices": "<array>",
"toolResults": "<array>",
"error": "<string>"
},
"outcome": {
"status": "sent",
"texts": 123,
"audio": true,
"menus": 123,
"files": 123,
"handoff": "<string>",
"lead": [
"<string>"
],
"detail": "<string>"
}
},
"sender_pn": "<string>",
"sender_lid": "<string>",
"sender_image_preview_url": "<string>",
"response": {
"status": "success",
"message": "Menú enviado correctamente"
}
}{
"error": "Faltan campos obligatorios o tipo de menú inválido"
}{
"error": "Token inválido"
}{
"error": "Límite de solicitudes excedido"
}{
"error": "Error al enviar el menú"
}Autorizaciones
Cuerpo
ID del chat al que se enviará el mensaje. Puede ser un número de teléfono en formato internacional, un ID de grupo (@g.us), un ID de usuario (con @s.whatsapp.net o @lid).
"5511999999999"
Tipo del menú. Use button para el formato actual y button_legacy solo para botones de respuesta en el formato anterior.
button, button_legacy, list, poll, carousel "list"
Texto principal (acepta placeholders)
"Elija una opción:"
Lista de opciones. Use [Título] para secciones en listas
[
"[Eletrônicos]",
"Smartphones|phones|Últimos lançamentos",
"Notebooks|notes|Modelos 2024",
"[Acessórios]",
"Fones|fones|Bluetooth e com fio",
"Capas|cases|Proteção para seu device"
]
Texto del pie de página (opcional)
"Menú de servicios"
Texto del botón principal
"Ver opciones"
Número máximo de opciones seleccionables (para encuestas)
1
Medio del encabezado (type: button): imagen, video o documento, por URL o base64, como en /send/media. El audio devuelve 400.
"https://exemplo.com/produto1.jpg"
Fuerza el tipo del file (opcional): image, video, document o el MIME type del archivo, como video/mp4. Sin él, el tipo se obtiene del archivo; cualquier otro valor responde 400.
"video/mp4"
Nombre del archivo cuando el file es un documento. Sin él, el nombre del archivo.
"Lista de precios.pdf"
ID del mensaje al que se responderá
"3EB0538DA65A59F6D8A251"
Números a mencionar (separados por coma)
"5511999999999,5511888888888"
Marca la conversación como leída después del envío
true
Marca los últimos mensajes recibidos como leídos
true
Retraso en milisegundos antes del envío; durante el retraso aparecerá 'Escribiendo...'
1000
Origen de rastreo del mensaje
"chatwoot"
ID para el seguimiento del mensaje (acepta valores duplicados)
"msg_123456789"
Si es true, envía el mensaje de forma asíncrona mediante la cola interna
false
Respuesta
Menú enviado correctamente
Representa un mensaje intercambiado en el sistema
ID único interno del mensaje (formato r + 7 caracteres hex aleatorios)
ID original del mensaje en el proveedor
ID de la conversación relacionada
ID del remitente del mensaje
Nombre visible del remitente
Indica si es un mensaje de grupo
Indica si el mensaje fue enviado por el usuario
Tipo de contenido del mensaje
Plataforma de origen del mensaje
Timestamp original del mensaje en milisegundos
Estado del ciclo de vida del mensaje.
Ejemplos comunes: Queued, Canceled, Failed, Sent, Delivered, Read.
En mensajes de grupo, sigue al participante más avanzado: Delivered cuando al menos uno lo recibió, Read cuando al menos uno lo leyó y Played cuando al menos uno lo escuchó.
Texto original del mensaje
ID del mensaje citado/respondido
Historial de ediciones del mensaje
ID del mensaje al que se reaccionó
Datos de votación de encuestas y listas
Conversión de opciones del mensaje, lista, encuesta y botones
ID del botón o elemento de lista seleccionado
Propietario del mensaje
Mensaje de error en caso de que el envío haya fallado
Contenido bruto del mensaje (JSON serializado o texto)
Indica si el mensaje fue enviado vía API
Mensaje fijado en la conversación (fijar y desfijar también llegan en messages_update, tipos Pinned y Unpinned)
Función usada para enviar el mensaje (cuando se envía vía API)
Payload utilizado en el envío cuando está disponible. Los datos de medios en base64 se omiten.
URL o referencia de archivo del mensaje
Contacto conocido asociado a una llamada, cuando está disponible en messageType: call.
Show child attributes
Show child attributes
Carpeta asociada al envío (cuando corresponda)
Origen de rastreo
ID de seguimiento (puede repetirse)
Registro de una ronda de la IA. El completo (solicitud al modelo, respuesta y outcome) queda una sola vez, en el último mensaje del contacto al que respondió la ronda, incluso cuando no salió nada (error, respuesta descartada). Cada mensaje enviado por la IA lleva solo agent_id y turn (el id de ese mensaje del contacto).
Show child attributes
Show child attributes
JID PN resuelto del remitente (cuando esté disponible)
LID original del remitente (cuando esté disponible)
URL temporal de vista previa del remitente, cuando se conoce. La hidratación de esta versión completa los mensajes recibidos en grupos; el campo puede omitirse. No provoca consulta de foto a WhatsApp en el listado.
Show child attributes
Show child attributes
