Goals
- Create and manage device sessions without manual intervention.
- Regenerate QR codes only when needed (blocked if session is still active).
- Disconnect sessions safely without destroying stored state.
- Allow a clean destroy when a device must be removed entirely.
Lifecycle Flow
Core lifecycle sequence so the implementation order is clear.
- Create:
POST /devices(or/devices/deploy) creates the device + initial QR → statusqr_generatedandqr_expires_atset. - Scan QR: scan before expiry → status
connected,linked_atpopulated. - Operate: use the device (messages, presence, profile) while
connected. - QR expired: if the QR is not scanned → status
expired; callPOST /devices/{device_id}/qrfor a new QR (only when no active session exists). - Relink: to temporarily break the session →
POST /devices/{device_id}/disconnect→ statusdisconnected→POST /devices/{device_id}/qr→ scan →connected. - Destroy:
DELETE /devices/{device_id}→ statusdestroyed(terminal); the device_id cannot be reused, but the device name can be reused.
QR blocking rule: /qr is rejected if the current QR is still valid or a session
is active. Disconnect first or wait for expiry.
create -> qr_generated -> (scan) -> connected
\-> (expires) -> expired -> /qr -> qr_generated
connected -> /disconnect -> disconnected -> /qr -> qr_generated
connected|disconnected -> /destroy -> destroyed (terminal)
Endpoint Summary
| Method | Path | Description |
|---|---|---|
POST |
/devices |
Create a device and return an initial QR + expiry. |
GET |
/devices |
List devices for the App (derived from Bearer token). |
POST |
/devices/deploy |
Legacy create + initial QR in one call (same behavior as /devices). |
POST |
/devices/{device_id}/qr |
Generate or regenerate QR (blocked if still active/valid). |
POST |
/devices/{device_id}/disconnect |
Disconnect session without destroying the device. |
GET |
/devices/{device_id}/presence?jid=... |
Get last-known online/offline for a peer JID (cache, may be stale). |
DELETE |
/devices/{device_id} |
Destroy device (session removed). |
Headers (all): Authorization: Bearer <token>,
Content-Type: application/json.
Get Presence (last-known)
When: You want a best-effort online/offline signal for a specific peer. This returns the last cached snapshot from WhatsApp presence events; it is not a real-time poll and may be unavailable due to privacy or missing events.
GET /devices/{device_id}/presence?jid=6281234567890@s.whatsapp.net
Authorization: Bearer <token>
Notes: Use a full JID (@s.whatsapp.net / @lid) or a raw phone
number. If no snapshot exists, status is unknown.
Create Device
When: Prepare a new device slot before linking.
POST /devices
Authorization: Bearer <token>
Content-Type: application/json
{
"device_name": "Testing Device",
"wa_number": "6281234567890"
}
Response (sample):
{
"data": {
"id": "7132724b-57cc-4c5a-979c-05e7af2521d6",
"app_id": "9bd6...",
"wa_number": "6281234567890",
"device_name": "Testing Device",
"status": "connected",
"linked_at": "2026-01-10T02:10:52Z",
"wa_device_jid": "6281234567890:1@s.whatsapp.net",
"wa_lid": "1234567890987654321@lid",
"created_at": "2026-01-10T02:00:00Z",
"updated_at": "2026-01-10T02:10:52Z"
},
"request_id": "..."
}
- Name uniqueness: unique per App for active devices; once destroyed, the name can be reused.
- Status:
qr_generatedon creation because the initial QR is issued immediately. - QR reissue: you cannot regenerate while the returned QR is still valid; disconnect or wait for expiry first.
- WA number: optional at create; if omitted it stays null until the device connects, then wa-server fills it from WhatsApp. If you already know the number, include it in the payload.
List Devices
When: Inventory check, show statuses, pick a device to regenerate QR.
GET /devices
Authorization: Bearer <token>
Deploy (create + QR)
When: Legacy one-step flow (create device and immediately return an initial QR). Behavior
matches POST /devices.
POST /devices/deploy
Authorization: Bearer <token>
Content-Type: application/json
{
"device_name": "New Device",
"wa_number": "15551234567"
}
Returns the device payload plus initial qr_code and qr_expires_at.
Generate / Regenerate QR
When: Start a new link or relink a disconnected session after the auto-issued QR expires or
the session is disconnected. Blocked if the current QR/session is still active (including the one returned
from /devices).
POST /devices/{device_id}/qr
Authorization: Bearer <token>
Response (sample):
{
"data": {
"id": "7132...",
"qr_code": "2@....",
"qr_expires_at": "2026-01-03T12:36:06Z",
"status": "qr_generated"
},
"request_id": "..."
}
- If a QR is still valid/active, the call is rejected; disconnect first if needed.
- Scan the returned QR code with the target WhatsApp device.
Disconnect (keep device)
When: Terminate the active session but keep the device record so it can be relinked later with a new QR.
POST /devices/{device_id}/disconnect
Authorization: Bearer <token>
- Keeps stored keys/state for reconnect (no data loss).
- Status becomes
disconnected; regenerate QR after this or after expiry. - Use this when you only want to break the session and later regenerate a QR.
- Prefer disconnect over destroy if you intend to reuse the same device entry.
Destroy Device
When: Permanently remove a device and its session. Use with care; relinking will require a fresh create + QR.
DELETE /devices/{device_id}
Authorization: Bearer <token>
- Destroys remote session, local store, and cached media for the device.
- Use only when the device should no longer exist; reconnect requires create + new QR.
- After destroy, the device name becomes available again for reuse.
Response Fields (common)
id,app_id,tenant_iddevice_name,wa_numberstatus:created|qr_generated|connected|disconnected|expired|destroyedlinked_at,qr_expires_at, timestampsrequest_idin the envelope for tracing- WA number population: may be null until connected; once connected, wa-server updates it from the paired account.
Integration Notes
- API key only; no JWT needed for devices/actions.
- Typical automation: create (QR returned) → scan → send messages; use disconnect (not destroy) when reusing the same device record, then regenerate QR after disconnect/expiry.
- Webhooks: subscribe to presence for typing indicators, warning/logout for reconnect triggers.
- Tooling/MCP: flat paths (
/devices) simplify scripting/CLI integrations.