Build your next conversation.

The API reference and integration guide for your WhatsApp workspace.

DEVELOPER DOCUMENTATION

From zero to your first request.

Create an account, open API keys, and generate a sandbox key. Create a sandbox session and use its ID to send a test request. No phone connection or paid plan is required for sandbox tests.

Create a sandbox session
curl -X POST "http://localhost:3000/api/v1/sessions" \
  -H "Authorization: Bearer YOUR_SANDBOX_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Development","mode":"sandbox"}'
i Sandbox requests return simulated: true. They do not send messages to WhatsApp.

Authenticate with a secret API key.

Base URL: http://localhost:3000/api/v1. Send Authorization: Bearer YOUR_API_KEY on every request. Keys begin with wa_sandbox_ or wa_live_. A key can only access sessions in its own environment and account.

Keep keys in server environment variables. Never place them in HTML, client JavaScript, public repositories, or URLs. Revoke and replace a key from the dashboard if it is exposed.

Check your key and limits
curl "http://localhost:3000/api/v1/me" -H "Authorization: Bearer YOUR_API_KEY"

Manage sessions and QR connections.

For live mode, purchase a plan and create a live key and session. Call connect, then get the session until a QR image appears. Scan it in WhatsApp → Linked devices. Wait for connected before sending messages. QR images expire and refresh. After a server restart, use Connect to resume saved credentials.
Method Endpoint Behavior
GET /sessions List sessions matching your API key environment.
POST /sessions Create with {name, mode}.
GET /sessions/id Read status; qr.image is a data URL when available.
POST /sessions/id/connect Start a live QR connection or mark sandbox ready.
POST /sessions/id/disconnect Stop the connection while retaining credentials.
DELETE /sessions/id Log out and remove this session.

Send messages from your server.

Use an international phone number with 8–15 digits, country code first, and no + or spaces. A message body may contain up to 4,000 characters.

Nodejs 22+ · built-in fetch
const response = await fetch("http://localhost:3000/api/v1/messages", {
  method: "POST",
  headers: {
    "Authorization": "Bearer " + process.env.WA_API_KEY,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID()
  },
  body: JSON.stringify({
    session_id: "YOUR_SESSION_ID",
    to: "923001234567",
    body: "Hello from my application!"
  })
});
const data = await response.json();
if (!response.ok) throw new Error(data.error);
console.log(data);

Reuse the same Idempotency-Key when retrying an uncertain request. The same key and payload return the stored result; a different payload with that key returns 409. If a live send has status unknown, check WhatsApp before creating a new request.

Media payload · up to 5 MB decoded
{
  "session_id": "YOUR_SESSION_ID",
  "to": "923001234567",
  "body": "Your invoice is attached.",
  "media": {
    "mimetype": "application/pdf",
    "filename": "invoice.pdf",
    "data": "BASE64_ENCODED_FILE"
  }
}
Supported MIME types: image/jpeg, image/png, image/webp, application/pdf, audio/ogg, video/mp4. Attachments are forwarded to WhatsApp; the platform stores message metadata and caption, not attachment bytes.
GET /messages?page=1 returns 30 history records per page. History includes inbound messages from live sessions while the server is connected. A sent status means WhatsApp accepted the request, not a guarantee of delivery or reading.

Receive and verify events.

Save a public HTTPS endpoint in Webhooks. You receive a signing secret once. Events include message.sent, message.received, message.simulated, session.updated, and webhook.test.
Verify X-WA-Signature using HMAC-SHA256 over timestamp + ‘.’ + rawBody, where timestamp is X-WA-Timestamp. Reject timestamps more than 5 minutes old and deduplicate on event ID. The dashboard provides working verification code.
Return a 2xx response within 10 seconds. Other responses retry up to 5 total attempts with exponential delays. Only public HTTPS on port 443 is supported; redirects and private network destinations are blocked. Updating the endpoint rotates its secret and cancels previous pending deliveries.

Add WhatsApp to your website.

In Website widget, choose your business name, WhatsApp number, message, color, and position. Save and copy the generated code into your website before the closing body tag.

HTML · public ID, no secret API key
<script src="http://localhost:3000/embed.js" data-widget="YOUR_WIDGET_ID" defer></script>
The button opens a wa.me link so visitors can start a conversation in their own WhatsApp. It does not send messages automatically. The public embed requires an active paid plan and an enabled widget. Optionally restrict it to exact hostnames; add www and non-www separately. Allow the API host in your site’s script-src and connect-src content security policies and allow the widget’s inline styles if your policy restricts them.

Plans and NayaPay payments.

Select a monthly or lifetime plan. Create an order, transfer its exact PKR amount to the displayed NayaPay account, then submit your transaction reference. Access begins when an administrator verifies and approves the payment. The order records its price, payment details, and exchange rate so later changes do not alter it.
Monthly access lasts one calendar month from approval and is renewed manually. Lifetime access has no expiry. Message limits reset on the first day of each month at 00:00 UTC for both billing types. Multiple active purchases combine limits. Plans that include source access offer a ZIP download in billing.

Limits and errors.

Status Meaning
400 Invalid fields. Read the error property.
401 Missing, invalid, revoked key or expired sign-in.
402 A paid plan is required or access has expired.
403 Access denied, domain restriction, or session limit.
404 Resource not found in this account/environment.
409 Conflicting request, disconnected session, or duplicate reference.
429 Message quota or request rate limit reached.
502 Provider result uncertain. Check history before resending.
503 Required server integration is not configured.
Sandbox accounts allow 3 sessions and 100 simulated requests per UTC day. Live limits depend on active purchases. Revoked keys, suspended accounts, and expired plans lose API access immediately. Message history is retained for support and auditing.

Self-hosted setup.

Use Node.js 22.13 or newer on a persistent server. Install dependencies with npm install, copy .env.example to .env, and run npm start. The terminal prints a one-time link to create the first administrator. You can also open /setup and paste the code from data/setup-token.
In Platform settings, enter your NayaPay account title and ID or IBAN. Set a USD-to-PKR checkout rate, or edit all plans to use PKR pricing. Plan prices and the Enterprise monthly default must be reviewed before launch.
For live messaging, set WHATSAPP_ENABLED=true and point CHROME_PATH to a Chrome/Chromium executable. On Windows, installed Chrome or Edge can be detected automatically. Restart and scan the real WhatsApp QR code. Configure SMTP_HOST, SMTP_PORT, MAIL_FROM, and any mail credentials for email recovery.
For production, use HTTPS, set NODE_ENV=production, APP_URL to your public origin, and a random APP_SECRET of at least 32 characters. Run one application process against the SQLite database. Keep the entire data directory private and persistent, back it up, and exclude it from source control and public file hosting. See the included README for operational details.
This is an independent integration built on whatsapp-web.js. It is not the official WhatsApp Business Platform. Read the upstream project documentation before operating live accounts.