La API de WhatsApp, documentada.
REST para enviar y leer, webhooks firmados para recibir y un servidor MCP listo para tu agente. Integra WhatsApp en tu producto con line_id y API keys.
De cero a tu primer mensaje en 3 pasos.
1. Conecta una linea
En la consola, escanea el QR con el WhatsApp del numero que quieras usar. Obtienes un line_id.
2. Crea una API key
En la consola, genera una API key. Empieza por wzb_live_ y se muestra una sola vez.
3. Llama a la API
Usa tu line_id y tu API key para enviar el primer mensaje (ejemplo abajo).
curl -X POST https://www.wazion.com/api/bridge/v1/messages/send \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{"line_id":"TU_LINE_ID","to":"+34600000000","message":"Hola desde WAzion Bridge"}'
La consola es donde gestionas lineas, API keys y webhooks. La documentacion describe la misma API que puedes probar alli.
Base de la API y autenticacion.
| Base REST | https://www.wazion.com/api/bridge/v1 |
|---|---|
| Servidor MCP | https://www.wazion.com/api/bridge/mcp |
| Cabecera | Authorization: Bearer wzb_live_... |
Toda peticion se autentica con una API key en la cabecera Authorization (tambien se acepta X-Bridge-Key). Las API keys se crean en la consola y empiezan por wzb_live_. Cada respuesta incluye una cabecera X-Request-Id util para soporte y depuracion. La API admite CORS (Access-Control-Allow-Origin: *).
Authorization: Bearer wzb_live_xxxxxxxxxxxxxxxxxxxxxxxx Content-Type: application/json
Como esta organizado Bridge.
line_id
Identifica una linea de WhatsApp conectada por QR. Toda peticion de envio o lectura usa un line_id.
API key
Credencial wzb_live_ que autentica a tu aplicacion. Puedes crear, rotar y revocar varias en la consola.
Webhook
Recibes eventos entrantes (mensajes, estados) firmados con HMAC en la URL que configures.
Trabajas siempre con line_id y API keys. Bridge oculta la sesion interna de WhatsApp: nunca expones ni usas la session_key.
Endpoints REST.
| Accion | Endpoint |
|---|---|
| Cuenta, plan y limites | GET /v1/me |
| Consumo del periodo | GET /v1/usage |
| Listar lineas | GET /v1/lines |
| Detalle de una linea | GET /v1/lines/{line_id} |
| Enviar texto | POST /v1/messages/send |
| Enviar media | POST /v1/messages/send-media |
| Responder citando | POST /v1/messages/reply |
| Reaccionar con emoji | POST /v1/messages/react |
| Marcar como leido | POST /v1/messages/read |
| Archivar chat | POST /v1/chats/archive |
| Listar chats | GET /v1/chats |
| Leer mensajes | GET /v1/messages |
| Listar / crear webhooks | GET /v1/webhooks · POST /v1/webhooks |
| Probar un webhook | POST /v1/webhooks/{id}/test |
POST /v1/messages/send
| Parametro | Tipo | Descripcion | |
|---|---|---|---|
line_id | string | obligatorio | Linea conectada desde la que se envia. |
to | string | obligatorio | Telefono destino en formato internacional, p. ej. +34600000000. |
message | string | obligatorio | Texto del mensaje. |
archive_policy | enum | opcional | never · always · preserve_if_previously_archived |
Los envios (send, send-media, reply) admiten la cabecera Idempotency-Key. Las lecturas GET /v1/chats y GET /v1/messages limitan el resultado a 500 y 200 respectivamente.
Enviar un mensaje en tu lenguaje.
curl -X POST https://www.wazion.com/api/bridge/v1/messages/send \
-H "Authorization: Bearer wzb_live_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1001" \
-d '{"line_id":"line_xxx","to":"+34600000000","message":"Pedido confirmado"}'
// Node 18+ (fetch nativo)
const res = await fetch("https://www.wazion.com/api/bridge/v1/messages/send", {
method: "POST",
headers: {
"Authorization": "Bearer wzb_live_xxx",
"Content-Type": "application/json",
"Idempotency-Key": "order-1001"
},
body: JSON.stringify({
line_id: "line_xxx",
to: "+34600000000",
message: "Pedido confirmado"
})
});
console.log(await res.json());
import requests
r = requests.post(
"https://www.wazion.com/api/bridge/v1/messages/send",
headers={
"Authorization": "Bearer wzb_live_xxx",
"Idempotency-Key": "order-1001",
},
json={
"line_id": "line_xxx",
"to": "+34600000000",
"message": "Pedido confirmado",
},
)
print(r.json())
<?php
$ch = curl_init("https://www.wazion.com/api/bridge/v1/messages/send");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer wzb_live_xxx",
"Content-Type: application/json",
"Idempotency-Key: order-1001",
],
CURLOPT_POSTFIELDS => json_encode([
"line_id" => "line_xxx",
"to" => "+34600000000",
"message" => "Pedido confirmado",
]),
]);
echo curl_exec($ch);
Enviar imagen, video, audio o documento.
Usa media_type con uno de estos valores: image, video, audio, document. El campo media_url debe ser una URL publica que el servidor pueda descargar.
| Parametro | Tipo | Descripcion | |
|---|---|---|---|
line_id | string | obligatorio | Linea de envio. |
to | string | obligatorio | Telefono destino. |
media_url | string (URL) | obligatorio | URL publica del archivo. |
media_type | enum | opcional | image · video · audio · document (por defecto image) |
caption | string | opcional | Texto adjunto al archivo. |
curl -X POST https://www.wazion.com/api/bridge/v1/messages/send-media \
-H "Authorization: Bearer wzb_live_xxx" \
-H "Content-Type: application/json" \
-d '{"line_id":"line_xxx","to":"+34600000000","media_url":"https://tu-cdn.com/foto.jpg","media_type":"image","caption":"Hola"}'
Idempotencia.
Para no enviar el mismo mensaje dos veces (reintentos de red, reinicios), envia la cabecera Idempotency-Key con un identificador unico de tu operacion. Si repites la misma clave con el mismo cuerpo, Bridge devuelve la respuesta guardada sin reenviar. La clave se recuerda 24 horas y aplica a send, send-media y reply.
-H "Idempotency-Key: pedido-1001"
Si reutilizas la misma clave con un cuerpo distinto, recibes 409 idempotency_conflict.
Recibir eventos firmados.
Crea un webhook con una URL HTTPS publica. Bridge enviara un POST a esa URL en cada evento. Cada webhook tiene su propio secreto (wzb_whsec_...) que se muestra una sola vez al crearlo.
Eventos que puedes suscribir (se entregan tal y como los produce el motor de WhatsApp): message.received, message.sent, message.status, line.status.
Cada entrega incluye estas cabeceras:
X-WAzion-Bridge-Event: message.received
X-WAzion-Bridge-Signature: sha256=<hmac>
Content-Type: application/json
{
"event": "message.received",
"line_id": "line_xxx",
"data": { ... }
}
Verificar la firma
La firma es un HMAC-SHA256 del cuerpo en crudo usando el secreto del webhook. Compara siempre antes de procesar:
// Node.js
import crypto from "node:crypto";
function verify(rawBody, signatureHeader, secret) {
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expected)
);
}
<?php
// PHP
$raw = file_get_contents("php://input");
$sig = $_SERVER["HTTP_X_WAZION_BRIDGE_SIGNATURE"] ?? "";
$expected = "sha256=" . hash_hmac("sha256", $raw, $secret);
if (!hash_equals($expected, $sig)) { http_response_code(401); exit; }
Puedes lanzar un evento de prueba a tu webhook desde la consola o con POST /v1/webhooks/{id}/test.
Manejo de errores.
Los errores de autenticacion, cuenta y servidor usan un sobre normalizado:
{
"ok": false,
"error": { "code": "unauthorized", "message": "...", "retryable": false }
}
Los errores de validacion y de negocio usan una forma plana con el codigo en error:
{ "error": "quota_exceeded", "message": "Monthly quota exceeded", "metric": "sent_messages", "used": 10000, "limit": 10000, "plan": "pro" }
| Codigo | HTTP | Significado |
|---|---|---|
unauthorized | 401 | API key ausente, invalida o revocada. |
subscription_required | 402 | La suscripcion Bridge no esta activa. |
validation_error | 400 | Faltan campos o son invalidos. |
line_not_found | 404 | El line_id no existe en tu cuenta. |
line_not_connected | 409 | La linea no esta conectada a WhatsApp. |
idempotency_conflict | 409 | Misma Idempotency-Key con cuerpo distinto. |
quota_exceeded | 429 | Superaste la cuota del periodo. |
line_limit_reached | 429 | Alcanzaste el maximo de lineas del plan. |
server_error | 500 | Error interno; puedes reintentar. |
Cuotas por plan.
- Las cuotas (mensajes enviados, eventos de webhook, numero de lineas) son por cuenta y se cuentan dentro de tu ciclo de facturacion.
- Al superar una cuota recibes 429 (quota_exceeded o line_limit_reached) con el detalle de used, limit y plan.
- GET /v1/chats devuelve como maximo 500 chats y GET /v1/messages como maximo 200 mensajes por peticion.
- Por estabilidad de WhatsApp, los envios de una misma linea se espacian unos segundos; reparte los envios masivos en el tiempo.
Consulta tu consumo en cualquier momento con GET /v1/usage. Los limites concretos de cada plan estan en la pagina de planes.
Servidor MCP para tu agente.
Bridge expone un servidor MCP (Model Context Protocol) para que tu agente envie y lea WhatsApp sin escribir codigo REST. Anadelo con:
claude mcp add --transport http wazion-bridge \ https://www.wazion.com/api/bridge/mcp \ --header "Authorization: Bearer wzb_live_xxx"
| Tool | Parametros |
|---|---|
bridge_list_lines | — |
bridge_send_message | line_id, to, message, archive_policy? |
bridge_send_media | line_id, to, media_url, media_type?, caption? |
bridge_reply_message | line_id, to, message, quoted_message_id |
bridge_react_message | line_id, jid, message_id, emoji |
bridge_get_chats | line_id, limit?, archived? |
bridge_get_messages | line_id, phone, limit? |
bridge_archive_chat | line_id, phone, archive? |
Listo para integrar.
Conecta una linea, crea tu API key y prueba cada endpoint desde la consola.