Documentation menu

API reference

Sessions

A session is one WhatsApp number linked to the API under a `clientId` you choose. Pair it once by QR code or pairing code; from then on the platform keeps it connected, reconnects it after restarts, and routes every request for that `clientId` to the pod that holds the connection.

POST/startStart or resume a session
GET/qrGet the pairing QR
POST/pair-phonePair with a phone-number code
POST/check-stateCheck connection state
GET/clientsList sessions
POST/set-webhookSet or clear the webhook
POST/set-org-idEnable hosted history (workspace id)
POST/set-api-secretPer-session API secret
POST/set-enable-group-aiEnable group messages
POST/disconnectUnlink and delete a session
POST/start

Start or resume a session

Begin QR pairing for a new clientId, or reconnect an already-paired one. Idempotent, returns immediately. Pass your webhook in the body so the session never exists without one.

ParameterTypeDescription
clientIdrequiredstring (query)Letters and digits only — no symbols. Chosen once, stable forever.
webhookUrlstring (body)Absolute https URL that receives inbound events. Without one, inbound messages are dropped.
webhookTokenstring (body)Sent back to you as Authorization: Bearer <token> on every webhook call.
pollLookupUrlstring (body)Optional endpoint we call to resolve poll votes to option names.
Request
curl -X POST "https://api.meowsapp.com/start?clientId=acmemain" \
  -H "Authorization: Bearer $SN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "webhookUrl": "https://example.com/whatsapp/incoming",
    "webhookToken": "choose-a-long-random-secret"
  }'
Response · 200
{
  "clientId": "acmemain",
  "status": "initializing",
  "podName": "node-1",
  "webhookUrl": "https://example.com/whatsapp/incoming",
  "pollLookupUrl": ""
}

status moves to qr (scan needed) or straight to connected if the device is already paired. podName is informational — routing is automatic.

StatusWhen
400clientId missing, contains symbols, or a webhook URL is not absolute http(s).
500Session started but the webhook could not be persisted — call /set-webhook.
GET/qr

Get the pairing QR

Poll every ~2 s after /start until status is connected. While status is qr, render the data-URL PNG for the user to scan under WhatsApp → Linked devices.

ParameterTypeDescription
clientIdrequiredstring (query)
Request
curl "https://api.meowsapp.com/qr?clientId=acmemain" -H "Authorization: Bearer $SN_TOKEN"
Response · 200
{ "clientId": "acmemain", "status": "qr", "qr": "data:image/png;base64,iVBORw0…" }

qr is an empty string unless status is qr. The code rotates automatically; keep polling and re-render.

StatusWhen
404Unknown clientId — call /start first.
POST/pair-phone

Pair with a phone-number code

Alternative to the QR: returns an 8-character code the user types into WhatsApp → Linked devices → Link with phone number. Call /start first.

ParameterTypeDescription
clientIdrequiredstringYour account identifier (letters and digits only).
phonerequiredstringThe WhatsApp number being linked, digits with country code (60123456789).
Request · JSON body
{ "clientId": "acmemain", "phone": "60123456789" }
Response · 200
{ "clientId": "acmemain", "phone": "60123456789", "code": "ABCD-EFGH" }
StatusWhen
404Unknown clientId — call /start first.
409Already paired.
502WhatsApp did not issue a code; retry.
POST/check-state

Check connection state

Cheap, always 200. Use it before sending in bulk or in a health dashboard.

ParameterTypeDescription
clientIdrequiredstringYour account identifier (letters and digits only).
Request · JSON body
{ "clientId": "acmemain" }
Response · 200
{ "status": true,  "state": "60123456789:12@s.whatsapp.net" }   // connected; state = own JID
{ "status": false, "state": "not connected" }
{ "status": false, "state": "unknown clientId" }
GET/clients

List sessions

Every clientId your token can see, with its linked number and current pod.

No parameters

Response · 200
{ "clients": [ { "clientId": "acmemain", "jid": "60123456789:12@s.whatsapp.net", "podName": "node-0", "orgId": "acme", "webhookUrl": "https://example.com/whatsapp/incoming" } ] }
POST/set-webhook

Set or clear the webhook

Change where inbound events go without restarting the session. Persisted; survives reconnects and restarts. Empty webhookUrl disables delivery.

ParameterTypeDescription
clientIdrequiredstringYour account identifier (letters and digits only).
webhookUrlrequiredstringAbsolute https URL, or "" to stop delivery.
webhookTokenstringBearer token we send you.
pollLookupUrlstringOptional poll-option lookup endpoint.
Request · JSON body
{ "clientId": "acmemain", "webhookUrl": "https://example.com/whatsapp/incoming", "webhookToken": "…" }
Response · 200
{ "ok": true, "clientId": "acmemain", "webhookUrl": "https://example.com/whatsapp/incoming", "pollLookupUrl": "" }
StatusWhen
400Missing clientId or invalid URL.
POST/set-org-id

Enable hosted history (workspace id)

Attach a workspace/organisation id of your choosing. Required only if you use the hosted inbox: until it is set, no history is stored. Call once per clientId; it persists.

ParameterTypeDescription
clientIdrequiredstringYour account identifier (letters and digits only).
orgIdrequiredstringYour workspace id. Empty clears it (history stops being stored).
Request · JSON body
{ "clientId": "acmemain", "orgId": "acme" }
Response · 200
{ "ok": true, "clientId": "acmemain", "orgId": "acme" }
StatusWhen
404Session not active — call /start first.
POST/set-api-secret

Per-session API secret

Give a third party (a customer of yours, a contractor) access to one session only. Requests naming this clientId are then accepted with either your master token or this secret.

ParameterTypeDescription
clientIdrequiredstringYour account identifier (letters and digits only).
secretrequiredstringAt least 16 characters. "" removes it.
Request · JSON body
{ "clientId": "acmemain", "secret": "k9F2…(32 random chars)" }
Response · 200
{ "clientId": "acmemain", "hasSecret": true }
POST/set-enable-group-ai

Enable group messages

Off by default: group traffic is noisy. Turn it on to receive group messages as webhook events (isGroup: true). Persisted per session.

ParameterTypeDescription
clientIdrequiredstringYour account identifier (letters and digits only).
enabledrequiredboolean
Request · JSON body
{ "clientId": "acmemain", "enabled": true }
Response · 200
{ "ok": true, "clientId": "acmemain", "enabled": true }
POST/disconnect

Unlink and delete a session

Logs the device out of WhatsApp (removes it from Linked devices) and deletes the session. The next /start with the same clientId pairs fresh.

ParameterTypeDescription
clientIdrequiredstringYour account identifier (letters and digits only).
Request · JSON body
{ "clientId": "acmemain" }
Response · 200
{ "ok": true, "clientId": "acmemain" }
// partial: local session removed, but WhatsApp did not confirm the logout
{ "ok": true, "clientId": "acmemain", "warning": "WhatsApp-side logout failed (…) — remove the device under Linked devices" }
StatusWhen
404No active session for that clientId.