Instances
An instance is one logical WhatsApp connection β one phone number, one paired session, one set of webhooks. Every message you send and every message you receive belongs to exactly one instance.
Lifecycle
Instances move through a finite state machine. The status field on the API mirrors the FSM 1:1:
ββββββββββββββββββββ
create β β pending β β instance row exists, no socket yet
ββββββββββ¬ββββββββββ
β start session
βΌ
ββββββββββββββββββββ
β qr_required β β Baileys produced a QR, waiting for scan
ββββββββββ¬ββββββββββ
scan β timeout / cancel
βΌ
ββββββββββββββββββββ
β connected β β session live; can send + receive
ββββββ¬ββββββ¬ββββββββ
network β β user logout / sessionInvalidated
blip β βΌ
ββββ΄ββββββββββββββββ
β reconnecting β
ββββββββββ¬ββββββββββ
β recovery fails
βΌ
ββββββββββββββββββββ
β disconnected β β needs human to re-pair
ββββββββββββββββββββ
Notable transitions:
pending β qr_requiredhappens lazily on the firstGET /v1/instances/:id/qrcall. We don't burn a Baileys socket until you ask.connected β reconnectingis automatic on transient socket errors. The manager backs off with jitter and tries to resume the session from the persisted auth-state.reconnecting β disconnectedhappens when WhatsApp explicitly invalidates the session (sessionInvalidated). This means the user logged out from another device, banned the number, or hit a Baileys protocol mismatch. The auth-state is wiped; you'll need a fresh QR scan to reconnect.
The event stream and the instance.connected / instance.disconnected webhooks emit on every transition.
Listing and creation
You can have multiple instances per customer β one per number you want to use. There's no hard cap in the schema, but each connected instance holds a WebSocket and ~20 MB of memory in the Node process, so a single backend can comfortably hold ~50 active sessions.
Create an instance
curl -sX POST "$WHATISUP_API/v1/instances" \
-H "Authorization: Bearer $WHATISUP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"support-line"}'List your instances
curl -s "$WHATISUP_API/v1/instances" \
-H "Authorization: Bearer $WHATISUP_API_KEY"Names are free-form; they're for humans, not routing.
Soft-delete
DELETE /v1/instances/:id doesn't drop the row β it stops the Baileys socket, wipes the on-disk auth-state, and sets deleted_at. Webhook deliveries and audit events that reference this instance stay queryable. If you re-create with the same name, you get a brand-new id.
Deleting an instance does not unlink the device on the WhatsApp side. The user remains paired until either the gateway emits a logout (which Baileys does automatically on auth-state wipe) or the user manually unlinks from the phone's Linked devices screen.
Heartbeat and reconciliation
The session manager runs a heartbeat tick (default 30s, configurable via HEARTBEAT_INTERVAL_MS) that:
- Bumps
last_seen_atfor every connected session β observability for soft-stuck sockets. - Reconciles each in-memory session against the DB row. If the row is gone (hard delete or out-of-band SQL), the stale socket is stopped.
This is invisible to your application; you'll just notice that orphan sessions don't pile up.