Docs Bridge

The WhatsApp API, documented.

REST to send and read, signed webhooks to receive, and an MCP server ready for your agent. Integrate WhatsApp into your product with line_id and API keys.

First steps

From zero to your first message in 3 steps.

1. Connect a line

In the console, scan the QR code with the WhatsApp of the number you want to use. You get a line_id.

2. Create an API key

In the console, generate an API key. It starts with wzb_live_ and is shown only once.

3. Call the API

Use your line_id and your API key to send the first message (example below).

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":"Hello from WAzion Bridge"}'

The console is where you manage lines, API keys, and webhooks. The documentation describes the same API that you can test there.

Authentication

API base and authentication.

REST basehttps://www.wazion.com/api/bridge/v1
MCP serverhttps://www.wazion.com/api/bridge/mcp
HeaderAuthorization: Bearer wzb_live_...

All requests are authenticated with an API key in the Authorization header (it is also accepted X-Bridge-Key). API keys are created in the console and start with wzb_live_. Each response includes a header X-Request-Id tool for support and debugging. The API supports CORS (Access-Control-Allow-Origin: *).

Authorization: Bearer wzb_live_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
Concepts

How Bridge is organized.

line_id

Identify a WhatsApp line connected by QR. Every send or read request uses a line_id.

API key

Credential wzb_live_ that authenticates your application. You can create, rotate, and revoke several in the console.

Webhook

You receive incoming events (messages, states) signed with HMAC at the URL you configure.

You always work with line_id and API keys. Bridge hides the internal WhatsApp session: you never expose or use the session_key.

Reference

REST endpoints.

ActionEndpoint
Account, plan, and limitsGET /v1/me
Period consumptionGET /v1/usage
List linesGET /v1/lines
Detail of a lineGET /v1/lines/{line_id}
Send textPOST /v1/messages/send
Send mediaPOST /v1/messages/send-media
Respond by quotingPOST /v1/messages/reply
React with emojiPOST /v1/messages/react
Mark as readPOST /v1/messages/read
Archive chatPOST /v1/chats/archive
List chatsGET /v1/chats
Read messagesGET /v1/messages
List / create webhooksGET /v1/webhooks · POST /v1/webhooks
Test a webhookPOST /v1/webhooks/{id}/test

POST /v1/messages/send

ParameterTypeDescription
line_idstringmandatoryLine connected from which it is sent.
tostringmandatoryDestination phone in international format, e.g. +34600000000.
messagestringmandatoryMessage text.
archive_policyenumoptionalnever · always · preserve_if_previously_archived

The shipments (send, send-media, reply) accept the Idempotency-Key header. The GET /v1/chats and GET /v1/messages readings limit the result to 500 and 200 respectively.

Examples

Send a message in your language.

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);
Multimedia

Send image, video, audio, or document.

Use media_type with one of these values: image, video, audio, document. The media_url field must be a public URL that the server can download.

ParameterTypeDescription
line_idstringmandatoryShipping line.
tostringmandatoryDestination phone.
media_urlstring (URL)mandatoryPublic URL of the file.
media_typeenumoptionalimage · video · audio · document (by default image)
captionstringoptionalText attached to the file.
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":"Hello"}'
Reliability

Idempotence.

To avoid sending the same message twice (network retries, restarts), send the header. Idempotency-Key with a unique identifier for your operation. If you repeat the same key with the same body, Bridge returns the saved response without resending. The key is remembered for 24 hours and applies to send, send-media, and reply.

-H "Idempotency-Key: pedido-1001"

If you reuse the same key with a different body, you receive 409 idempotency_conflict.

Webhooks

Receive signed events.

Create a webhook with a public HTTPS URL. Bridge will send a POST to that URL on each event. Each webhook has its own secret. (wzb_whsec_...) that is shown only once when creating it.

Events you can subscribe to (they are delivered as produced by the WhatsApp engine): message.received, message.sent, message.status, line.status.

Each delivery includes these headers:

X-WAzion-Bridge-Event: message.received
X-WAzion-Bridge-Signature: sha256=<hmac>
Content-Type: application/json

{
  "event": "message.received",
  "line_id": "line_xxx",
  "data": { ... }
}

Verify the signature

The signature is an HMAC-SHA256 of the raw body using the webhook secret. Always compare before processing:

// 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; }

You can trigger a test event to your webhook from the console or with POST /v1/webhooks/{id}/test.

Errors

Error handling.

Authentication, account, and server errors use a standardized envelope:

{
  "ok": false,
  "error": { "code": "unauthorized", "message": "...", "retryable": false }
}

Validation and business errors use a flat form with the error code:

{ "error": "quota_exceeded", "message": "Monthly quota exceeded", "metric": "sent_messages", "used": 10000, "limit": 10000, "plan": "pro" }
CodeHTTPMeaning
unauthorized401Missing, invalid, or revoked API key.
subscription_required402The Bridge subscription is not active.
validation_error400Fields are missing or invalid.
line_not_found404The line_id does not exist in your account.
line_not_connected409The line is not connected to WhatsApp.
idempotency_conflict409Same Idempotency-Key with different body.
quota_exceeded429You exceeded the quota for the period.
line_limit_reached429You have reached the maximum number of lines in the plan.
server_error500Internal error; you can try again.
Limits and quotas

Plan fees.

  • The quotas (sent messages, webhook events, number of lines) are per account and are counted within your billing cycle.
  • Upon exceeding a quota, you receive 429 (quota_exceeded or line_limit_reached) with the details of used, limit, and plan.
  • GET /v1/chats returns a maximum of 500 chats and GET /v1/messages a maximum of 200 messages per request.
  • For the stability of WhatsApp, the deliveries of the same line are spaced a few seconds apart; it distributes mass deliveries over time.

Check your consumption at any time with GET /v1/usage. The specific limits of each plan are in the plans page.

MCP

MCP server for your agent.

Bridge exposes an MCP (Model Context Protocol) server so that your agent can send and read WhatsApp without writing REST code. Add it with:

claude mcp add --transport http wazion-bridge \
  https://www.wazion.com/api/bridge/mcp \
  --header "Authorization: Bearer wzb_live_xxx"
ToolParameters
bridge_list_lines
bridge_send_messageline_id, to, message, archive_policy?
bridge_send_medialine_id, to, media_url, media_type?, caption?
bridge_reply_messageline_id, to, message, quoted_message_id
bridge_react_messageline_id, jid, message_id, emoji
bridge_get_chatsline_id, limit?, archived?
bridge_get_messagesline_id, phone, limit?
bridge_archive_chatline_id, phone, archive?

Ready to integrate.

Connect a line, create your API key, and test each endpoint from the console.

WAzion Assistant

Commercial information and technical support

Hello! I am the WAzion assistant. I can help you with information about prices and plans, technical questions, configuration, or any questions about our product. How can I assist you?
Developed with WAzion AI