| POST | /start | Start or resume a session |
| GET | /qr | Get the pairing QR |
| POST | /pair-phone | Pair with a phone-number code |
| POST | /check-state | Check connection state |
| GET | /clients | List sessions |
| POST | /set-webhook | Set or clear the webhook |
| POST | /set-org-id | Enable hosted history (workspace id) |
| POST | /set-api-secret | Per-session API secret |
| POST | /set-enable-group-ai | Enable group messages |
| POST | /disconnect | Unlink and delete a session |
/startStart 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.
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string (query) | Letters and digits only — no symbols. Chosen once, stable forever. |
webhookUrl | string (body) | Absolute https URL that receives inbound events. Without one, inbound messages are dropped. |
webhookToken | string (body) | Sent back to you as Authorization: Bearer <token> on every webhook call. |
pollLookupUrl | string (body) | Optional endpoint we call to resolve poll votes to option names. |
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"
}'{
"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.
| Status | When |
|---|---|
400 | clientId missing, contains symbols, or a webhook URL is not absolute http(s). |
500 | Session started but the webhook could not be persisted — call /set-webhook. |
/qrGet 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.
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string (query) |
curl "https://api.meowsapp.com/qr?clientId=acmemain" -H "Authorization: Bearer $SN_TOKEN"{ "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.
| Status | When |
|---|---|
404 | Unknown clientId — call /start first. |
/pair-phonePair 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.
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string | Your account identifier (letters and digits only). |
phonerequired | string | The WhatsApp number being linked, digits with country code (60123456789). |
{ "clientId": "acmemain", "phone": "60123456789" }{ "clientId": "acmemain", "phone": "60123456789", "code": "ABCD-EFGH" }| Status | When |
|---|---|
404 | Unknown clientId — call /start first. |
409 | Already paired. |
502 | WhatsApp did not issue a code; retry. |
/check-stateCheck connection state
Cheap, always 200. Use it before sending in bulk or in a health dashboard.
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string | Your account identifier (letters and digits only). |
{ "clientId": "acmemain" }{ "status": true, "state": "60123456789:[email protected]" } // connected; state = own JID
{ "status": false, "state": "not connected" }
{ "status": false, "state": "unknown clientId" }/clientsList sessions
Every clientId your token can see, with its linked number and current pod.
No parameters
{ "clients": [ { "clientId": "acmemain", "jid": "60123456789:[email protected]", "podName": "node-0", "orgId": "acme", "webhookUrl": "https://example.com/whatsapp/incoming" } ] }/set-webhookSet or clear the webhook
Change where inbound events go without restarting the session. Persisted; survives reconnects and restarts. Empty webhookUrl disables delivery.
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string | Your account identifier (letters and digits only). |
webhookUrlrequired | string | Absolute https URL, or "" to stop delivery. |
webhookToken | string | Bearer token we send you. |
pollLookupUrl | string | Optional poll-option lookup endpoint. |
{ "clientId": "acmemain", "webhookUrl": "https://example.com/whatsapp/incoming", "webhookToken": "…" }{ "ok": true, "clientId": "acmemain", "webhookUrl": "https://example.com/whatsapp/incoming", "pollLookupUrl": "" }| Status | When |
|---|---|
400 | Missing clientId or invalid URL. |
/set-org-idEnable 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.
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string | Your account identifier (letters and digits only). |
orgIdrequired | string | Your workspace id. Empty clears it (history stops being stored). |
{ "clientId": "acmemain", "orgId": "acme" }{ "ok": true, "clientId": "acmemain", "orgId": "acme" }| Status | When |
|---|---|
404 | Session not active — call /start first. |
/set-api-secretPer-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.
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string | Your account identifier (letters and digits only). |
secretrequired | string | At least 16 characters. "" removes it. |
{ "clientId": "acmemain", "secret": "k9F2…(32 random chars)" }{ "clientId": "acmemain", "hasSecret": true }/set-enable-group-aiEnable group messages
Off by default: group traffic is noisy. Turn it on to receive group messages as webhook events (isGroup: true). Persisted per session.
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string | Your account identifier (letters and digits only). |
enabledrequired | boolean |
{ "clientId": "acmemain", "enabled": true }{ "ok": true, "clientId": "acmemain", "enabled": true }/disconnectUnlink 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.
| Parameter | Type | Description |
|---|---|---|
clientIdrequired | string | Your account identifier (letters and digits only). |
{ "clientId": "acmemain" }{ "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" }| Status | When |
|---|---|
404 | No active session for that clientId. |