WhatsApp: enviar mensajes por la API
Envía texto, imagen, video, audio, documento, sticker, ubicación, botones y lista en WhatsApp por la API de XBASE, en la ventana de 24 horas.
Actualizado el
POST /whatsapp/messages envía un mensaje libre a un contacto, dentro de la ventana de 24 horas. Fuera de ella, envía una plantilla.
Enviar un mensaje
POST https://api.xbase.app/api/external/v1/whatsapp/messages| Campo | Tipo | Obligatorio | Regla |
|---|---|---|---|
numberId | texto | sí | Número que envía (listar los números) |
to | texto | sí | Teléfono del contacto con el código de país, de 8 a 15 dígitos. Se quitan +, espacios, guiones y paréntesis |
type | texto | sí | text, image, video, audio, document, sticker, location, buttons, list o flow |
| objeto del tipo | objeto | sí | Un campo con el mismo nombre del type, como "text": { "body": "…" }. Mira cada tipo abajo |
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": "5491155550100",
"type": "text",
"text": { "body": "Tu pedido salió para entrega y llega hoy antes de las 18 h." }
}'La respuesta está en Respuesta. Un campo de más en el cuerpo se rechaza con 400.
Texto
{
"numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
"to": "5491155550100",
"type": "text",
"text": { "body": "¡Hola, María! ¿En qué te puedo ayudar?" }
}text.body tiene de 1 a 4096 caracteres. Los enlaces del texto aparecen clicables en WhatsApp.
Multimedia
Imagen, video, audio, documento y sticker van por URL https pública: Meta descarga el archivo de ella. Una URL http, con usuario y contraseña, o de una dirección interna o de red privada responde 400.
{
"numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
"to": "5491155550100",
"type": "image",
"image": {
"link": "https://cdn.miempresa.com/catalogo/zapatillas-azules.jpg",
"caption": "Zapatillas azules, talles 38 a 44"
}
}type | Objeto | Reglas de Meta |
|---|---|---|
image | link, caption | JPEG o PNG, hasta 5 MB |
video | link, caption | MP4 o 3GP, hasta 16 MB |
audio | link, voice | AAC, MP3, MP4 u OGG, hasta 16 MB. "voice": true lo muestra como nota de voz, y el archivo tiene que ser OGG con el códec Opus |
document | link, filename, caption | Cualquier archivo, hasta 100 MB. filename (hasta 240 caracteres) es el nombre que ve el contacto |
sticker | link | WebP de 512 × 512 píxeles |
caption es opcional, con hasta 1024 caracteres.
Ubicación
{
"numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
"to": "5491155550100",
"type": "location",
"location": {
"latitude": -34.6037,
"longitude": -58.3816,
"name": "Tienda Centro",
"address": "Av. Corrientes 1000, Buenos Aires"
}
}| Campo | Regla |
|---|---|
location.latitude | De −90 a 90 |
location.longitude | De −180 a 180 |
location.name · location.address | Opcionales, hasta 1000 caracteres |
Botones
{
"numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
"to": "5491155550100",
"type": "buttons",
"buttons": {
"header": "Pedido 12345",
"body": "¿Confirmamos la entrega para mañana?",
"footer": "Toca una opción",
"buttons": [
{ "id": "confirmar", "title": "Confirmar" },
{ "id": "reprogramar", "title": "Reprogramar" }
]
}
}| Campo | Regla |
|---|---|
buttons.body | Texto del mensaje, hasta 1024 caracteres |
buttons.header · buttons.footer | Opcionales, hasta 60 caracteres |
buttons.buttons | De 1 a 3 botones. id (hasta 256 caracteres, sin repetir) vuelve cuando el contacto toca; title tiene hasta 20 caracteres |
Lista
{
"numberId": "6d1f3c2a-4b5e-4f60-9a7b-8c9d0e1f2a3b",
"to": "5491155550100",
"type": "list",
"list": {
"body": "Elige el horario de entrega.",
"button": "Ver horarios",
"rows": [
{ "id": "manana", "title": "Mañana", "description": "De 8 a 12 h" },
{ "id": "tarde", "title": "Tarde", "description": "De 13 a 18 h" }
]
}
}| Campo | Regla |
|---|---|
list.body | Texto del mensaje, hasta 1024 caracteres |
list.button | Texto del botón que abre la lista, hasta 20 caracteres |
list.rows | De 1 a 10 filas. id (hasta 200 caracteres, sin repetir) vuelve cuando el contacto elige; title hasta 24 caracteres; description opcional, hasta 72 |
list.header · list.footer | Opcionales, hasta 60 caracteres |
El botón tocado o la fila elegida llega como whatsapp.message.received en los webhooks del workspace, con el id que enviaste.
Flow
Para abrir un WhatsApp Flow (un formulario dentro de WhatsApp), usa "type": "flow". Los campos y un ejemplo están en Flows.
Respuesta
Respuesta 200:
{
"status": "accepted",
"messageId": "wamid.HBgNNTUyMTk5OTk5MDAwMBUCABEYEjQ1QzM1RkQ2RDhGNjZBMDQ3MwA=",
"threadId": "c1d7f0b2-5a4e-4f3d-9c2b-1a0e9d8c7b6a",
"dialogId": "5a0e4c31-7b2d-4e8f-a1c3-9d6b5e4f3a21"
}| Campo | Descripción |
|---|---|
status | accepted: Meta aceptó el envío. La entrega y la lectura llegan después, en los eventos de webhook |
messageId | Id del mensaje en Meta (wamid.…). Va en la reacción y aparece en los eventos |
threadId | Conversación del contacto en XBASE |
dialogId | Mensaje en la conversación |
Errores
| Estado | code | Cuándo |
|---|---|---|
| 400 | (sin code) | Campo inválido: teléfono, type desconocido, texto vacío o demasiado largo, URL http o interna, campo de más. El message dice cuál |
| 404 | NUMBER_NOT_FOUND | El número no existe en este workspace |
| 422 | NUMBER_DISCONNECTED | El número está desconectado |
| 422 | WINDOW_CLOSED | Fuera de la ventana de 24 horas. Envía una plantilla |
| 422 | SEND_REJECTED | XBASE rechazó antes de enviar. El message dice el motivo |
| 422 | META_ERROR | Meta rechazó, por ejemplo, un archivo que no pudo descargar. details.metaCode trae el código de Meta |
En WINDOW_CLOSED, details.reason dice por qué la ventana está cerrada: no_contact_message (el contacto nunca escribió a este número), window_expired (su último mensaje tiene más de 24 horas) o awaiting_template_reply (el último envío fue una plantilla y el contacto todavía no respondió). details.lastContactMessageAt trae la fecha del último mensaje del contacto.
{
"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" }
}Preguntas frecuentes
Ver también
Plantillas
Lista las plantillas aprobadas de cada número y envía una plantilla de WhatsApp por la API de XBASE, a cualquier hora, con ejemplos y errores.
Reacciones
Reacciona con un emoji a un mensaje de una conversación de WhatsApp, o quita la reacción, por la API de XBASE con el id del mensaje en Meta.