API de mensajería
API para enviar a varios números
Envía el mismo mensaje de WhatsApp a varios números de teléfono y grupos en una sola solicitud. Úsala para difusiones pequeñas, como boletines, ofertas y anuncios.
https://wbiztool.com/api/v1/send_msg/multi/Cuerpo: JSON o campos de formulario
Wbiztool crea un mensaje por destinatario y devuelve un msg_id para cada uno, así que puedes consultar su estado por separado.
Ejemplo rápido#
curl -X POST https://wbiztool.com/api/v1/send_msg/multi/ \
-H "Content-Type: application/json" \
-d '{
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 0,
"country_code": "91",
"phone": "9876543210,9812345670,Sales Team Mumbai",
"msg": "Our Diwali sale starts tomorrow. Get 20% off on all orders!"
}'import requests
response = requests.post(
"https://wbiztool.com/api/v1/send_msg/multi/",
json={
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 0,
"country_code": "91",
"phone": ",".join(["9876543210", "9812345670", "Sales Team Mumbai"]),
"msg": "Our Diwali sale starts tomorrow. Get 20% off on all orders!",
},
timeout=60,
)
result = response.json() # read the body even when the HTTP code is 400
if result.get("status") == 1:
for item in result["messages"]:
print(item["contact"], "->", item["msg_id"])
else:
print("Failed:", result.get("message", "no message in response"))// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const response = await fetch("https://wbiztool.com/api/v1/send_msg/multi/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: 12345,
api_key: "YOUR_API_KEY",
whatsapp_client: 678,
msg_type: 0,
country_code: "91",
phone: ["9876543210", "9812345670", "Sales Team Mumbai"].join(","),
msg: "Our Diwali sale starts tomorrow. Get 20% off on all orders!",
}),
});
const result = await response.json(); // read the body even when the HTTP code is 400
if (result.status === 1) {
for (const item of result.messages) {
console.log(item.contact, "->", item.msg_id);
}
} else {
console.error("Failed:", result.message ?? "no message in response");
}<?php
$payload = [
'client_id' => 12345,
'api_key' => 'YOUR_API_KEY',
'whatsapp_client' => 678,
'msg_type' => 0,
'country_code' => '91',
'phone' => implode(',', ['9876543210', '9812345670', 'Sales Team Mumbai']),
'msg' => 'Our Diwali sale starts tomorrow. Get 20% off on all orders!',
];
$ch = curl_init('https://wbiztool.com/api/v1/send_msg/multi/');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($result['status'] ?? 0) === 1) {
foreach ($result['messages'] as $item) {
echo $item['contact'] . ' -> ' . $item['msg_id'] . PHP_EOL;
}
} else {
echo 'Failed: ' . ($result['message'] ?? 'no message in response');
}Sustituye 12345, YOUR_API_KEY y 678 por tus propios valores. Consulta Autenticación para saber dónde encontrarlos.
Parámetros de la solicitud#
Autenticación
client_idintegerobligatorioTu ID de cliente de la API, de Configuración → Claves API.
api_keystringobligatorioTu clave API, de esa misma página.
whatsapp_clientintegerobligatorioID del número de WhatsApp desde el que se envía, de la configuración de WhatsApp. A diferencia de Enviar mensaje, este endpoint nunca elige un número por ti.
Destinatarios y mensaje
phonestringobligatorioNúmeros de teléfono y nombres de grupo en una sola cadena separada por comas, por ejemplo
9876543210,9812345670,Sales Team Mumbai. No envíes un array JSON. Consulta Cómo se leen los destinatarios.country_codestringopcionalCódigo telefónico del país sin
+, por ejemplo91. Se añade delante de cada número de teléfono, salvo que el número ya empiece por él. En JSON, envíalo como cadena ("91"), no como número. Si lo envías como número, cada número de teléfono de la lista se trata como nombre de grupo (is_group: true) y esos mensajes fallan.msg_typeintegeropcional0texto (predeterminado),1imagen,2archivo o documento.msgstringObligatorio cuando msg_type es 0Texto del mensaje. En imágenes y archivos es el pie de foto y puede estar vacío. El formato de WhatsApp funciona:
*bold*,_italic_,~strikethrough~. También se aceptamessagecomo alias.
Imágenes y archivos
img_urlstringObligatorio cuando msg_type es 1URL pública
httpohttpsde la imagen.file_urlstringObligatorio cuando msg_type es 2URL pública
httpohttpsdesde la que se puede descargar el archivo directamente.file_namestringopcionalNombre de archivo que ven los destinatarios, como
price-list.pdf. Se envía en minúsculas, los caracteres como& : ? * $ ;se reemplazan por_y se recorta a 150 caracteres. Si lo omites, el nombre se toma de la URL.
Opciones de entrega
webhookstringopcionalURL que recibe un
POSTpor cada mensaje cuando se envía o falla. El contenido es el mismo que en Enviar mensaje.
curl -X POST https://wbiztool.com/api/v1/send_msg/multi/ \
-H "Content-Type: application/json" \
-d '{
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 1,
"country_code": "91",
"phone": "9876543210,9812345670",
"img_url": "https://example.com/offers/diwali-sale.jpg",
"msg": "Our Diwali sale starts tomorrow."
}'Cómo se leen los destinatarios#
Wbiztool divide phone por las comas, quita los espacios alrededor de cada elemento y luego decide qué es cada elemento:
- Solo dígitos (se admiten un
+inicial o ceros iniciales): se trata como número de teléfono. Se añadecountry_code, salvo que el número ya empiece por él, y después el número debe tener entre 6 y 15 dígitos. - Cualquier otra cosa: se trata como nombre de un grupo de WhatsApp, que se busca igual que en Enviar a un grupo.
- Un grupo cuyo nombre solo tiene dígitos (por ejemplo
2024) se trata como número de teléfono, y los nombres de grupo que contienen comas no se pueden enviar desde este endpoint. Usa Enviar a un grupo para esos casos.
Otras cosas que debes saber:
- Los números demasiado cortos o demasiado largos tras añadir el código de país se omiten sin avisar. No aparecen en la respuesta y no reciben un
msg_id. - Los duplicados no se eliminan. Un número que aparece dos veces recibe dos mensajes.
- Si un número local empieza por los mismos dígitos que
country_code(por ejemplo9123456780concountry_code91), el código no se añade. Envía esos números con el código de país ya incluido (919123456780). - Las URL de imágenes y archivos no se comprueban cuando llamas a la API. Se descargan al enviar cada mensaje, así que un enlace roto hace que fallen los mensajes más tarde, no la solicitud. Se aplican las mismas reglas de envío que en Enviar mensaje: fallan las imágenes de más de 16 MB y los videos de más de 64 MB, el audio WAV y OGG no es compatible, y a los archivos (
msg_type2) sin una extensión admitida se les añade.pdf. Consulta Enviar imágenes y archivos.
Créditos#
Todo el lote se compara con tus créditos restantes antes de crear nada. Cuenta cada elemento no vacío de phone, incluidos los que después se omiten. Si el total supera tus créditos restantes, no se crea ningún mensaje y recibes:
{
"message": "Not enough credits: 120 messages requested, 85 credits remaining",
"status": 0
}
Los mensajes en cola que aún no se han enviado también cuentan contra tus créditos restantes. Divide las listas grandes en solicitudes más pequeñas o recarga tu plan. Para campañas grandes, sube en su lugar una hoja de cálculo desde la página de Campañas.
Respuesta#
Una solicitud correcta devuelve HTTP 200:
{
"msg_ids": [9817263, 9817264, 9817265],
"messages": [
{ "msg_id": 9817263, "contact": "919876543210", "is_group": false },
{ "msg_id": 9817264, "contact": "919812345670", "is_group": false },
{ "msg_id": 9817265, "contact": "Sales Team Mumbai", "is_group": true }
],
"message": "Successfully created 3 messages",
"status": 1
}
| Campo | Tipo | Descripción |
|---|---|---|
status | integer | 1 si se puso en cola al menos un mensaje, 0 en caso contrario. |
message | string | Successfully created N messages si todo va bien; en caso contrario, el error. |
msg_ids | array of integers | IDs de los mensajes en cola, en el orden de phone. Solo aparece si la solicitud es correcta. |
messages | array | Un objeto por cada mensaje en cola. Solo aparece si la solicitud es correcta. |
messages[].msg_id | integer | ID del mensaje. |
messages[].contact | string | El número de teléfono con el código de país aplicado, o el nombre del grupo. |
messages[].is_group | boolean | true si el elemento se trató como nombre de grupo. |
Compara messages con la lista que enviaste para detectar los números omitidos, y comprueba que is_group sea false en cada elemento que querías que fuera un número de teléfono.
Errores#
La mayoría de los errores devuelven HTTP 200 con status con valor 0, así que revisa siempre status en el cuerpo. Salvo en los errores HTTP 400 y 403, las respuestas (incluidas las correctas) son JSON enviado con Content-Type: text/html, así que procesa el cuerpo tú mismo en lugar de confiar en la detección automática de JSON (por ejemplo, en herramientas sin código):
{ "message": "Invalid whatsapp client", "status": 0 }
| Mensaje | Cómo solucionarlo |
|---|---|
Auth Error | Envía client_id y api_key. |
Invalid Client Id | Envía client_id como número. Se devuelve con HTTP 403. |
Auth Error: invalid api key | Comprueba que la clave existe, que no se ha eliminado y que pertenece a este client_id. Se devuelve con HTTP 400. |
Msg cant be null | Los mensajes de texto (msg_type 0) necesitan msg. |
Image Url Can't be null | Para msg_type 1, envía img_url. |
File Url Can't be null | Para msg_type 2, envía file_url. |
Not enough credits: … messages requested, … credits remaining | Envía menos destinatarios o añade créditos. Consulta Créditos. |
Invalid whatsapp client | Ese ID de whatsapp_client no está en tu espacio de trabajo. |
No valid contacts found | Todos los elementos de phone estaban vacíos o se omitieron. Comprueba que los números tengan entre 6 y 15 dígitos con el código de país. |
Demo Account can not access apis | Usa una cuenta normal. |
Invalid JSON format: … | El cuerpo JSON no es válido, o enviaste campos de formulario sin client_id. |
Consejos#
- Envía
phonecomo cadena: une tu lista con comas. Un array JSON devuelve{}. - Por ahora no uses
send_bulk_messagesdel cliente de Python: envía la lista comophones, que este endpoint ignora. Llama al endpoint directamente como en los ejemplos anteriores. - Haz seguimiento de cada mensaje: guarda cada
msg_iddemessages, o pasa unwebhookpara recibir un aviso cuando cada uno se envíe o falle. - Mantén tu número conectado: cada mensaje se envía desde tu número de WhatsApp, así que debe seguir conectado en la configuración de WhatsApp hasta que salga todo el lote.
- Texto distinto para cada persona: este endpoint envía el mismo
msga todos. Llama a Enviar mensaje una vez por destinatario para personalizar cada mensaje.
