WaZappy
Developer API · REST & Webhooks

Build into your own product

A clean, well-documented REST API on the official WhatsApp Business Platform. Send messages and templates, manage contacts and receive real-time events — straight from your backend, with a single API key.

Bearer API keys Predictable JSON errors Rate-limited & idempotent

cURL
curl -X POST https://api.wazappy.com/api/v1/messages/send \
  -H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+919555592220",
    "type": "text",
    "message": "Hi Priya! Your order #1042 has shipped 🚚"
  }'

What you can build

One API for every WhatsApp workflow

The same engine that powers WaZappy flows and campaigns, exposed as a simple REST API for your own code.

Notify from your own app

Fire order confirmations, shipping updates, OTPs and reminders straight from your backend when events happen.

Wire WhatsApp into your stack

Trigger messages from your CRM, ERP, e-commerce or internal tools — no dashboard needed.

Send approved templates at scale

Deliver any approved template — with dynamic header, body variables, buttons, carousels and offers.

Keep contacts in sync

Upsert customers with tags, status and marketing opt-in as they sign up or transact in your system.

Build custom AI agents

Pair the API with your own logic (or the MCP server) to run bespoke WhatsApp assistants.

Log & reconcile

Every API send is recorded for reports, so programmatic traffic shows up alongside the rest.

Quickstart

Send your first message in 3 steps

  1. 1

    Get an API key

    On a plan that includes API access (Pro and above), open the dashboard → Developers / API Keys → Create key. You can scope a key to one WhatsApp number. The full key is shown once — copy it (you can also reveal it again later).

  2. 2

    Set your base URL & auth

    Point requests at https://api.wazappy.com/api/v1 and send your key as an Authorization: Bearer header (or x-api-key).

  3. 3

    Call /messages/send

    Post a JSON body with the recipient and message. You get back a messageId you can track in Message Reports.

Node.js
const res = await fetch("https://api.wazappy.com/api/v1/messages/send", {
  method: "POST",
  headers: {
    "Authorization": "Bearer wz_live_xxxxxxxxxxxxxxxx",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    to: "+919555592220",
    type: "text",
    message: "Hi Priya! Your order #1042 has shipped",
  }),
});

const data = await res.json();
// { success: true, messageId: "wamid.HBg...", to: "919555592220", type: "text" }
console.log(data);
Python
import requests

res = requests.post(
    "https://api.wazappy.com/api/v1/messages/send",
    headers={"Authorization": "Bearer wz_live_xxxxxxxxxxxxxxxx"},
    json={
        "to": "+919555592220",
        "type": "text",
        "message": "Hi Priya! Your order #1042 has shipped",
    },
)
print(res.json())

Authentication

API keys & base URL

Every request is authenticated with a secret API key that starts with wz_live_. Send it as a Bearer token, or as an x-api-key header.

  • Keys are tied to your account and (optionally) a specific WhatsApp number.
  • Treat keys like passwords — use them server-side only, never in a browser or mobile app.
  • Revoke or rotate a key anytime from the dashboard; requests with it stop immediately.

Base URL

https://api.wazappy.com/api/v1

HTTP headers
Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx
Content-Type: application/json

# or, equivalently:
x-api-key: wz_live_xxxxxxxxxxxxxxxx
cURL · GET /status
curl https://api.wazappy.com/api/v1/status \
  -H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx"

Reference

Endpoints

All paths are relative to https://api.wazappy.com/api/v1. All requests and responses are JSON.

POST/messages/send

Send a text, image, video, document or audio message to a number.

POST/messages/template

Send any approved template — dynamic header, body variables, buttons, carousel & limited-time offer.

POST/contacts

Create or update a contact (idempotent upsert) with name, email, tags, status and opt-in.

GET/templates

List your APPROVED templates, normalised into a render-ready spec so you know exactly which inputs to send.

GET/status

Health snapshot — plan, API access, connected number, quality rating and key usage.

POST /messages/send

Send a text or media message. Fields: to (required), type (text, image, video, document, audio), and either message (for text) or mediaUrl/mediaId with an optional caption.

cURL · text
curl -X POST https://api.wazappy.com/api/v1/messages/send \
  -H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+919555592220",
    "type": "text",
    "message": "Hi Priya! Your order #1042 has shipped 🚚"
  }'
cURL · media
curl -X POST https://api.wazappy.com/api/v1/messages/send \
  -H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+919555592220",
    "type": "image",
    "mediaUrl": "https://example.com/invoice-1042.jpg",
    "caption": "Your invoice for order #1042"
  }'

Media accepts either a public mediaUrl or a Meta media mediaId from your gallery. Documents may include a filename.

POST /messages/template

Send any approved template. Supports positional bodyVariables or named bodyParams, a dynamic header (text / image / video / document / location), buttons (url, copy_code, quick_reply, flow), a limited-time offer and multi-card carousels.

cURL · template
curl -X POST https://api.wazappy.com/api/v1/messages/template \
  -H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+919555592220",
    "templateName": "order_update",
    "languageCode": "en",
    "bodyVariables": ["#1042", "shipped"],
    "buttons": [
      { "index": 0, "subType": "url", "value": "1042" }
    ]
  }'

POST /contacts

Idempotent upsert keyed on the phone number. Set name, email, tags, status, source and marketing optin.

cURL · contacts
curl -X POST https://api.wazappy.com/api/v1/contacts \
  -H "Authorization: Bearer wz_live_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "+919555592220",
    "name": "Priya Nair",
    "email": "priya@example.com",
    "tags": ["vip", "d2c"],
    "optin": true
  }'

Templates

GET /templates

Returns your APPROVED templates normalised into a render-ready spec — header type, body placeholders (positional or named), footer, buttons and carousel cards — so your client knows exactly which inputs to collect without hardcoding a single template. Results are cached for ~10 minutes.

  • Discover placeholders before you send
  • Build dynamic forms from the spec
  • Reuse the same code for every template

Status

GET /status

A quick health snapshot for your integration — plan, API access, the connected number and its quality rating, and this key’s usage.

200 OK
{
  "success": true,
  "account": { "plan": "pro", "apiAccess": true },
  "number": {
    "phoneId": "1029384756",
    "phoneNumber": "+91 95555 92220",
    "status": "active",
    "qualityRating": "GREEN"
  },
  "key": {
    "name": "Production key",
    "prefix": "wz_live_ab12cd",
    "lastUsedAt": "2026-08-05T09:12:44.000Z",
    "requestCount": 18422
  }
}

Webhooks

Get events in real time

Register a webhook URL in your dashboard to receive delivery status updates (sent → delivered → read → failed) and inbound customer messages as they happen. You can also POST to any endpoint mid-flow with the HTTP request node, so your systems stay in sync without polling.

  • Delivery & read receipts for every send
  • Inbound message events
  • Flow-triggered callbacks to any URL
POST → your webhook URL
{
  "event": "message.status",
  "messageId": "wamid.HBg...",
  "to": "919555592220",
  "status": "delivered",
  "timestamp": "2026-08-05T09:13:02.000Z"
}

Fair use

Rate limits & idempotency

60

requests / minute

Per API key. A 429 with RATE_LIMITED is returned when you exceed it.

5,000

requests / day

Per API key. Need more? Talk to us about higher limits.

30s

duplicate guard

Identical content to the same number inside the window returns 409 DUPLICATE_MESSAGE — safe retries, no double-sends.

Note: WhatsApp’s own per-number throughput and quality tier apply on top of these limits. Message usage is billed by Meta directly.

Errors

Predictable error codes

Failures return the right HTTP status and a stable JSON body: { success: false, code, message }. Branch on code, not the message text.

HTTPCodeWhen it happens
401NO_API_KEYNo key supplied in the Authorization / x-api-key header.
401INVALID_API_KEYKey is unknown or has been revoked.
401API_KEY_INACTIVEThe key was disabled from the dashboard.
402PLAN_INACTIVESubscription expired — renew to continue.
403API_NOT_IN_PLANYour plan does not include API access — upgrade to Pro or higher.
400NO_WHATSAPP_NUMBERNo WhatsApp number is connected to the account.
400NUMBER_NOT_ACTIVEThe connected number is not activated or is disabled.
403META_ACCOUNT_RESTRICTEDMeta has restricted the WhatsApp Business account (check Account Quality).
402META_BILLING_ISSUEA billing issue exists on your Meta WhatsApp account.
429RATE_LIMITEDToo many requests — see the rate limits below.
409DUPLICATE_MESSAGEIdentical content sent to the same number within the dedupe window.
400BAD_REQUESTMissing required fields or invalid values.
502SEND_FAILEDWhatsApp rejected the message — details are included in the response.
500SERVER_ERRORSomething went wrong on our side — retry shortly.

Ready to build?

Create an account, generate an API key, and send your first message in minutes. Questions? Our team is a message away.

Ready to put WhatsApp to work?

Start on the free plan, connect your number, and send your first automated reply today. No setup fee, no card.

Free plan · No setup fee · Messages billed by Meta at cost