Device Management

Manage WhatsApp device sessions per App: create, list, QR, disconnect, destroy. Device names must be unique per App; a destroyed name can be reused.

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.

  1. Create: POST /devices (or /devices/deploy) creates the device + initial QR → status qr_generated and qr_expires_at set.
  2. Scan QR: scan before expiry → status connected, linked_at populated.
  3. Operate: use the device (messages, presence, profile) while connected.
  4. QR expired: if the QR is not scanned → status expired; call POST /devices/{device_id}/qr for a new QR (only when no active session exists).
  5. Relink: to temporarily break the session → POST /devices/{device_id}/disconnect → status disconnectedPOST /devices/{device_id}/qr → scan → connected.
  6. Destroy: DELETE /devices/{device_id} → status destroyed (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_generated on 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_id
  • device_name, wa_number
  • status: created | qr_generated | connected | disconnected | expired | destroyed
  • linked_at, qr_expires_at, timestamps
  • request_id in 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.