API de mensajería
API de envío de mensajes
Envía un texto, una imagen o un documento de WhatsApp a un número de teléfono desde tu número de WhatsApp conectado. Úsala para confirmaciones de pedidos, recordatorios de pago, alertas y respuestas de soporte.
https://wbiztool.com/api/v1/send_msg/Cuerpo: JSON, campos de formulario o multipart/form-data al subir un archivo
El mensaje se pone en cola y se envía desde tu número de WhatsApp en pocos instantes. La respuesta te da un msg_id que puedes usar para consultar su estado.
Ejemplo rápido#
curl -X POST https://wbiztool.com/api/v1/send_msg/ \
-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",
"msg": "Hi Aman, your order #4821 has shipped and will arrive on Thursday."
}'import requests
response = requests.post(
"https://wbiztool.com/api/v1/send_msg/",
json={
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 0,
"country_code": "91",
"phone": "9876543210",
"msg": "Hi Aman, your order #4821 has shipped and will arrive on Thursday.",
},
timeout=60,
)
result = response.json() # read the body even when the HTTP code is 400
if result.get("status") == 1:
print("Queued with msg_id", result["msg_id"])
else:
print("Failed:", result.get("message"))// 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/", {
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",
msg: "Hi Aman, your order #4821 has shipped and will arrive on Thursday.",
}),
});
const result = await response.json(); // read the body even when the HTTP code is 400
if (result.status === 1) {
console.log("Queued with msg_id", result.msg_id);
} else {
console.error("Failed:", result.message);
}<?php
$payload = [
'client_id' => 12345,
'api_key' => 'YOUR_API_KEY',
'whatsapp_client' => 678,
'msg_type' => 0,
'country_code' => '91',
'phone' => '9876543210',
'msg' => 'Hi Aman, your order #4821 has shipped and will arrive on Thursday.',
];
$ch = curl_init('https://wbiztool.com/api/v1/send_msg/');
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) {
echo 'Queued with msg_id ' . $result['msg_id'];
} else {
echo 'Failed: ' . ($result['message'] ?? 'no 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_clientintegerObligatorio si tienes más de un númeroID del número de WhatsApp desde el que se envía, de la configuración de WhatsApp. Si lo omites y tu espacio de trabajo tiene exactamente un número conectado, se usa ese número.
Destinatario y mensaje
phonestringobligatorioEl número de WhatsApp del destinatario, solo dígitos. Los espacios,
+,-,.y los paréntesis se eliminan automáticamente. Envía el número con su código de país (919876543210) o sin él (9876543210) junto concountry_code. Con campos de formulario, no incluyas un0inicial de prefijo nacional (09876543210): no se elimina antes de añadircountry_code, así que el mensaje llega al número equivocado. Las solicitudes JSON lo eliminan por ti.country_codestringopcionalCódigo telefónico del país sin
+, por ejemplo91para India o1para EE. UU. Se añade delante dephone, salvo que el número ya empiece por él. Excepción: con91, un número de 10 dígitos siempre recibe el prefijo. Con otros códigos, un número local que empiece por los mismos dígitos no recibe el prefijo, así que envíalo con el código de país incluido.msg_typeintegeropcional0texto (predeterminado),1imagen,2archivo o documento.msgstringObligatorio cuando msg_type es 0Texto del mensaje, hasta 3.000 caracteres. 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 1 y no se sube ningún archivoURL pública
httpohttpsde la imagen.file_urlstringObligatorio cuando msg_type es 2 y no se sube ningún archivoURL pública
httpohttpsdesde la que se puede descargar el archivo directamente.filefileopcionalSube la imagen o el archivo en lugar de indicar una URL. Envía la solicitud como
multipart/form-datacon el campo llamadofile.file_namestringopcionalNombre de archivo que ve el destinatario, como
invoice-4821.pdf. Su extensión determina cómo se envía el archivo, así que incluye una. 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 o del archivo subido.
Opciones de entrega
expire_after_secondsintegeropcionalMarca el mensaje como caducado (estado
4) si no se ha enviado en este número de segundos, por ejemplo3600para una hora. Útil para mensajes urgentes, como horas estimadas de entrega. Un proceso en segundo plano lo hace al menos 30 segundos después del plazo, así que no confíes en él para plazos de menos de un minuto.webhookstringopcionalURL que recibe un
POSTcuando el mensaje se envía o falla. Consulta Webhook.
Enviar imágenes y archivos#
Límites de descarga para img_url y file_url:
- La URL debe ser pública:
httpohttps, accesible desde internet. Se siguen hasta 5 redirecciones, y cada una también debe llevar a una dirección pública. - Los archivos enlazados pueden pesar hasta 100 MB. El servidor debe empezar a responder en 45 segundos y no quedarse parado durante más tiempo.
- El archivo se descarga cuando llamas a la API, así que un enlace roto falla de inmediato con
Invalid file url.
Extensiones admitidas: .pdf, .xlsx, .xls, .txt, .docx, .png, .jpg, .jpeg, .webp, .mp3, .mpga, .m4a, .mp4, .webm.
Estas comprobaciones se hacen al enviar el mensaje, no al llamar a la API, así que los fallos solo aparecen en Estado del mensaje y en el webhook:
| Problema | error en Estado del mensaje |
|---|---|
Una imagen (msg_type 1) de más de 16 MB | File exceeds WhatsApp size limit (16MB max) |
Un video (.mp4, .webm) de más de 64 MB, o un archivo vacío | File exceeds WhatsApp size limit (…) |
Un archivo .ogg, o un archivo .wav enviado como imagen (msg_type 1) | File type not supported |
El audio WAV y OGG no es compatible. Un archivo .wav enviado como archivo (msg_type 2) no se rechaza, pero llega como recording.wav.pdf. Convierte el audio a .mp3 o .m4a antes.
curl -X POST https://wbiztool.com/api/v1/send_msg/ \
-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",
"img_url": "https://example.com/offers/diwali-sale.jpg",
"msg": "Our Diwali sale starts today 🎉"
}'import requests
response = requests.post(
"https://wbiztool.com/api/v1/send_msg/",
json={
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 1,
"country_code": "91",
"phone": "9876543210",
"img_url": "https://example.com/offers/diwali-sale.jpg",
"msg": "Our Diwali sale starts today 🎉",
},
timeout=60,
)
print(response.json())// 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/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: 12345,
api_key: "YOUR_API_KEY",
whatsapp_client: 678,
msg_type: 1,
country_code: "91",
phone: "9876543210",
img_url: "https://example.com/offers/diwali-sale.jpg",
msg: "Our Diwali sale starts today 🎉",
}),
});
console.log(await response.json());<?php
$ch = curl_init('https://wbiztool.com/api/v1/send_msg/');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'client_id' => 12345,
'api_key' => 'YOUR_API_KEY',
'whatsapp_client' => 678,
'msg_type' => 1,
'country_code' => '91',
'phone' => '9876543210',
'img_url' => 'https://example.com/offers/diwali-sale.jpg',
'msg' => 'Our Diwali sale starts today 🎉',
]),
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);
curl_close($ch);curl -X POST https://wbiztool.com/api/v1/send_msg/ \
-F client_id=12345 \
-F api_key=YOUR_API_KEY \
-F whatsapp_client=678 \
-F msg_type=2 \
-F country_code=91 \
-F phone=9876543210 \
-F "msg=Your invoice for order #4821 is attached." \
-F file_name=invoice-4821.pdf \
-F file=@./invoice-4821.pdfimport requests
with open("invoice-4821.pdf", "rb") as f:
response = requests.post(
"https://wbiztool.com/api/v1/send_msg/",
data={
"client_id": 12345,
"api_key": "YOUR_API_KEY",
"whatsapp_client": 678,
"msg_type": 2,
"country_code": "91",
"phone": "9876543210",
"msg": "Your invoice for order #4821 is attached.",
"file_name": "invoice-4821.pdf",
},
files={"file": f},
timeout=120,
)
print(response.json())// Node.js 20+ (built-in fetch, FormData and fs.openAsBlob). Save as .mjs to use top-level await.
import { openAsBlob } from "node:fs";
const form = new FormData();
form.append("client_id", "12345");
form.append("api_key", "YOUR_API_KEY");
form.append("whatsapp_client", "678");
form.append("msg_type", "2");
form.append("country_code", "91");
form.append("phone", "9876543210");
form.append("msg", "Your invoice for order #4821 is attached.");
form.append("file_name", "invoice-4821.pdf");
form.append("file", await openAsBlob("./invoice-4821.pdf"), "invoice-4821.pdf");
// Don't set Content-Type yourself; fetch adds the multipart boundary.
const response = await fetch("https://wbiztool.com/api/v1/send_msg/", { method: "POST", body: form });
console.log(await response.json());<?php
$ch = curl_init('https://wbiztool.com/api/v1/send_msg/');
curl_setopt_array($ch, [
CURLOPT_POST => true,
// An array body (not json_encode) makes cURL send multipart/form-data.
CURLOPT_POSTFIELDS => [
'client_id' => 12345,
'api_key' => 'YOUR_API_KEY',
'whatsapp_client' => 678,
'msg_type' => 2,
'country_code' => '91',
'phone' => '9876543210',
'msg' => 'Your invoice for order #4821 is attached.',
'file_name' => 'invoice-4821.pdf',
'file' => new CURLFile('/path/to/invoice-4821.pdf', 'application/pdf', 'invoice-4821.pdf'),
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
]);
echo curl_exec($ch);
curl_close($ch);Usar los clientes oficiales#
Los clientes de Python y Node.js llaman a este endpoint por ti.
from wbiztool_client import WbizToolClient
client = WbizToolClient(api_key="YOUR_API_KEY", client_id="12345")
result = client.send_message(
phone="9876543210",
country_code="91",
msg="Hi Aman, your order #4821 has shipped.",
whatsapp_client=678,
)
print(result)Los errores lanzan requests.HTTPError. Lee el motivo con e.response.json()["message"].
const { WbizToolClient } = require("wbiztool-client");
const client = new WbizToolClient({
clientId: 12345,
apiKey: "YOUR_API_KEY",
whatsappClient: 678,
});
(async () => {
// Errors throw, with the API's response in the error message.
const result = await client.sendMessage({
phone: "9876543210",
countryCode: "91",
message: "Hi Aman, your order #4821 has shipped.",
});
console.log(result);
})().catch(console.error);Respuesta#
Una solicitud correcta devuelve HTTP 200:
{
"status": 1,
"message": "Created",
"msg_id": 9817263
}
| Campo | Tipo | Descripción |
|---|---|---|
status | integer | 1 si el mensaje se puso en cola, 0 si la solicitud falló. |
message | string | Created si todo va bien; en caso contrario, el error. |
msg_id | integer | ID del mensaje en cola. Guárdalo para consultar el estado más adelante. Solo aparece si la solicitud es correcta. |
"status": 1 significa que el mensaje se puso en cola, no que ya haya llegado al destinatario. Usa un webhook o Estado del mensaje para confirmar que se envió.
Errores#
Los errores devuelven HTTP 400 con status con valor 0 (Account Disabled no tiene campo status):
{ "status": 0, "message": "Msg cant be null" }
| Mensaje | Cómo solucionarlo |
|---|---|
Auth Error - Please send correct API key and Client id | Envía un api_key que no esté vacío. |
Invalid client id. | Envía client_id como número. |
Auth Error: invalid api key | Comprueba que la clave existe, que no se ha eliminado y que pertenece a este client_id. |
Either phone or group_name parameter is required | Añade phone. |
Please provide either phone OR group_name, not both | Elimina uno de los dos. |
Invalid phone number | phone solo debe contener dígitos (entre 6 y 17), opcionalmente precedidos de +. |
Invalid Contact Number "…" | Con el código de país añadido, el número debe tener entre 6 y 15 dígitos. |
Msg cant be null | Los mensajes de texto (msg_type 0) necesitan msg. |
Message length is too long | Limita msg a 3.000 caracteres o menos. |
Image Url Can't be null | Para msg_type 1, envía img_url o sube un file. |
File Url Can't be null | Para msg_type 2, envía file_url o sube un file. |
Invalid file url, Can't download / Invalid file url | La URL no es pública, se agotó el tiempo de espera o el archivo supera los 100 MB. |
Invalid whatsapp client | Ese ID de whatsapp_client no está en tu espacio de trabajo. |
Invalid whatsapp client id. | Envía whatsapp_client. Es obligatorio cuando tu espacio de trabajo tiene más de un número conectado. |
Not enough credits | Tu plan no tiene mensajes disponibles. |
Demo Account can not access apis | Usa una cuenta normal. |
Account Disabled | Tu cuenta está desactivada. Contacta con soporte. |
Invalid JSON format: … | El cuerpo JSON no es válido, a menudo por una coma final o un salto de línea sin escapar en msg. Usa \n para los saltos de línea. |
Un mensaje en cola todavía puede fallar al enviarse, por ejemplo con File exceeds WhatsApp size limit (…). Esos errores nunca aparecen en esta respuesta. Consulta Enviar imágenes y archivos y revisa Estado del mensaje.
Webhook#
Si pasas webhook, Wbiztool envía un POST a esa URL cuando el mensaje se envía o falla. El cuerpo va codificado como formulario (application/x-www-form-urlencoded), no como JSON:
msg_id=9817263&status=SENT
| Campo | Valores |
|---|---|
msg_id | El msg_id que se devolvió al enviar el mensaje. |
status | SENT o FAILED |
Responde con cualquier código 2xx. Si tu endpoint agota el tiempo de espera (a los 3 segundos) o devuelve 5xx, la llamada se reintenta hasta 3 veces en total. Una respuesta 4xx no se reintenta. No se envía ningún webhook cuando un mensaje se cancela o caduca; para esos casos usa Estado del mensaje.
Consejos#
- Números de teléfono: guarda los números en formato internacional y envíalos con
country_codepara evitar ambigüedades. - Saltos de línea en JSON: escríbelos como
\ndentro demsg. Un salto de línea literal hace que el JSON no sea válido. - Mantén tu número conectado: los mensajes se envían desde tu número de WhatsApp, así que debe seguir conectado en la configuración de WhatsApp.
- Muchos destinatarios: para enviar el mismo mensaje a varios números en una sola solicitud, usa Enviar a varios números. Para campañas grandes, sube una hoja de cálculo desde la página de Campañas.
