curl --request POST \
--url https://api.wppfy.com/send/carousel \
--header 'Content-Type: application/json' \
--header 'token: <api-key>' \
--data '
{
"number": "5511999999999",
"text": "Nossos produtos",
"carousel": [
{
"text": "Smartphone XYZ",
"image": "https://exemplo.com/produto.jpg",
"buttons": [
{
"id": "comprar_xyz",
"text": "Comprar agora",
"type": "REPLY"
}
]
}
]
}
'import requests
url = "https://api.wppfy.com/send/carousel"
payload = {
"number": "5511999999999",
"text": "Nossos produtos",
"carousel": [
{
"text": "Smartphone XYZ",
"image": "https://exemplo.com/produto.jpg",
"buttons": [
{
"id": "comprar_xyz",
"text": "Comprar agora",
"type": "REPLY"
}
]
}
]
}
headers = {
"token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {token: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
number: '5511999999999',
text: 'Nossos produtos',
carousel: [
{
text: 'Smartphone XYZ',
image: 'https://exemplo.com/produto.jpg',
buttons: [{id: 'comprar_xyz', text: 'Comprar agora', type: 'REPLY'}]
}
]
})
};
fetch('https://api.wppfy.com/send/carousel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.wppfy.com/send/carousel",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'number' => '5511999999999',
'text' => 'Nossos produtos',
'carousel' => [
[
'text' => 'Smartphone XYZ',
'image' => 'https://exemplo.com/produto.jpg',
'buttons' => [
[
'id' => 'comprar_xyz',
'text' => 'Comprar agora',
'type' => 'REPLY'
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.wppfy.com/send/carousel"
payload := strings.NewReader("{\n \"number\": \"5511999999999\",\n \"text\": \"Nossos produtos\",\n \"carousel\": [\n {\n \"text\": \"Smartphone XYZ\",\n \"image\": \"https://exemplo.com/produto.jpg\",\n \"buttons\": [\n {\n \"id\": \"comprar_xyz\",\n \"text\": \"Comprar agora\",\n \"type\": \"REPLY\"\n }\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.wppfy.com/send/carousel")
.header("token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"number\": \"5511999999999\",\n \"text\": \"Nossos produtos\",\n \"carousel\": [\n {\n \"text\": \"Smartphone XYZ\",\n \"image\": \"https://exemplo.com/produto.jpg\",\n \"buttons\": [\n {\n \"id\": \"comprar_xyz\",\n \"text\": \"Comprar agora\",\n \"type\": \"REPLY\"\n }\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.wppfy.com/send/carousel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"number\": \"5511999999999\",\n \"text\": \"Nossos produtos\",\n \"carousel\": [\n {\n \"text\": \"Smartphone XYZ\",\n \"image\": \"https://exemplo.com/produto.jpg\",\n \"buttons\": [\n {\n \"id\": \"comprar_xyz\",\n \"text\": \"Comprar agora\",\n \"type\": \"REPLY\"\n }\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"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": "Carrusel enviado correctamente"
}
}{
"error": "Faltan campos obligatorios o formato de tarjeta inválido"
}{
"error": "Token inválido"
}{
"error": "Error al enviar el carrusel"
}Enviar carrusel de medios con botones
Este endpoint permite enviar un carrusel con imágenes y botones interactivos.
Funciona de la misma manera que el endpoint /send/menu con type: carousel, pero usando otro formato de payload.
Campos Comunes
Este endpoint admite todos los campos opcionales comunes documentados en la tag “Enviar Mensaje”, incluyendo:
delay, readchat, readmessages, replyid, mentions, forward, track_source, track_id, placeholders y envío a grupos.
Estructura del Payload
{
"number": "5511999999999",
"text": "Texto principal",
"carousel": [
{
"text": "Texto do cartão",
"image": "URL da imagem",
"buttons": [
{
"id": "resposta1",
"text": "Texto do botão",
"type": "REPLY"
}
]
}
]
}
Tipos de Botones
-
REPLY: Botón de respuesta rápida- Al hacer clic, envía el valor del id como respuesta al chat
- El id será el texto enviado como respuesta
-
URL: Botón con enlace- Al hacer clic, abre la URL especificada
- El id debe contener la URL completa (ej.: https://exemplo.com)
-
COPY: Botón para copiar texto- Al hacer clic, copia el texto al portapapeles
- El id será el texto que se copiará
-
CALL: Botón para realizar una llamada- Al hacer clic, inicia una llamada telefónica
- El id debe contener el número de teléfono
Ejemplo de Botones
{
"buttons": [
{
"id": "Sim, quero comprar!",
"text": "Confirmar Compra",
"type": "REPLY"
},
{
"id": "https://exemplo.com/produto",
"text": "Ver Produto",
"type": "URL"
},
{
"id": "CUPOM20",
"text": "Copiar Cupom",
"type": "COPY"
},
{
"id": "5511999999999",
"text": "Falar com Vendedor",
"type": "CALL"
}
]
}
Ejemplo Completo de Carrusel
{
"number": "5511999999999",
"text": "Nossos Produtos em Destaque",
"carousel": [
{
"text": "Smartphone XYZ\nO mais avançado smartphone da linha",
"image": "https://exemplo.com/produto1.jpg",
"buttons": [
{
"id": "SIM_COMPRAR_XYZ",
"text": "Comprar Agora",
"type": "REPLY"
},
{
"id": "https://exemplo.com/xyz",
"text": "Ver Detalhes",
"type": "URL"
}
]
},
{
"text": "Cupom de Desconto\nGanhe 20% OFF em qualquer produto",
"image": "https://exemplo.com/cupom.jpg",
"buttons": [
{
"id": "DESCONTO20",
"text": "Copiar Cupom",
"type": "COPY"
},
{
"id": "5511999999999",
"text": "Falar com Vendedor",
"type": "CALL"
}
]
}
]
}
curl --request POST \
--url https://api.wppfy.com/send/carousel \
--header 'Content-Type: application/json' \
--header 'token: <api-key>' \
--data '
{
"number": "5511999999999",
"text": "Nossos produtos",
"carousel": [
{
"text": "Smartphone XYZ",
"image": "https://exemplo.com/produto.jpg",
"buttons": [
{
"id": "comprar_xyz",
"text": "Comprar agora",
"type": "REPLY"
}
]
}
]
}
'import requests
url = "https://api.wppfy.com/send/carousel"
payload = {
"number": "5511999999999",
"text": "Nossos produtos",
"carousel": [
{
"text": "Smartphone XYZ",
"image": "https://exemplo.com/produto.jpg",
"buttons": [
{
"id": "comprar_xyz",
"text": "Comprar agora",
"type": "REPLY"
}
]
}
]
}
headers = {
"token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {token: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
number: '5511999999999',
text: 'Nossos produtos',
carousel: [
{
text: 'Smartphone XYZ',
image: 'https://exemplo.com/produto.jpg',
buttons: [{id: 'comprar_xyz', text: 'Comprar agora', type: 'REPLY'}]
}
]
})
};
fetch('https://api.wppfy.com/send/carousel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.wppfy.com/send/carousel",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'number' => '5511999999999',
'text' => 'Nossos produtos',
'carousel' => [
[
'text' => 'Smartphone XYZ',
'image' => 'https://exemplo.com/produto.jpg',
'buttons' => [
[
'id' => 'comprar_xyz',
'text' => 'Comprar agora',
'type' => 'REPLY'
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"token: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.wppfy.com/send/carousel"
payload := strings.NewReader("{\n \"number\": \"5511999999999\",\n \"text\": \"Nossos produtos\",\n \"carousel\": [\n {\n \"text\": \"Smartphone XYZ\",\n \"image\": \"https://exemplo.com/produto.jpg\",\n \"buttons\": [\n {\n \"id\": \"comprar_xyz\",\n \"text\": \"Comprar agora\",\n \"type\": \"REPLY\"\n }\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.wppfy.com/send/carousel")
.header("token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"number\": \"5511999999999\",\n \"text\": \"Nossos produtos\",\n \"carousel\": [\n {\n \"text\": \"Smartphone XYZ\",\n \"image\": \"https://exemplo.com/produto.jpg\",\n \"buttons\": [\n {\n \"id\": \"comprar_xyz\",\n \"text\": \"Comprar agora\",\n \"type\": \"REPLY\"\n }\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.wppfy.com/send/carousel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"number\": \"5511999999999\",\n \"text\": \"Nossos produtos\",\n \"carousel\": [\n {\n \"text\": \"Smartphone XYZ\",\n \"image\": \"https://exemplo.com/produto.jpg\",\n \"buttons\": [\n {\n \"id\": \"comprar_xyz\",\n \"text\": \"Comprar agora\",\n \"type\": \"REPLY\"\n }\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"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": "Carrusel enviado correctamente"
}
}{
"error": "Faltan campos obligatorios o formato de tarjeta inválido"
}{
"error": "Token inválido"
}{
"error": "Error al enviar el carrusel"
}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"
Array de tarjetas del carrusel
Show child attributes
Show child attributes
Texto principal del mensaje
"Nuestros Productos Destacados"
Retraso en milisegundos antes del envío
1000
Marca la conversación como leída después del envío
true
Marca los últimos mensajes recibidos como leídos
true
ID del mensaje al que se responderá
"3EB0538DA65A59F6D8A251"
Números a mencionar (separados por coma)
"5511999999999,5511888888888"
Marca el mensaje como reenviado en WhatsApp
false
Si es true, envía el mensaje de forma asíncrona mediante la cola interna
false
Origen de rastreo del mensaje
"chatwoot"
ID para el seguimiento del mensaje (acepta valores duplicados)
"msg_123456789"
Respuesta
Carrusel 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
