Sessions
What a session is, its lifecycle, QR scan flow, persistence, reconnection behavior, and status codes.
Sessions
A session in WaSphere represents a single WhatsApp account (phone number) that is actively connected to your server. Each session runs as an isolated WebSocket connection managed by the WA Server. You can operate as many sessions simultaneously as your server's resources allow.
What Makes Up a Session
When you create a session, WaSphere stores:
- Credentials — the Noise protocol keys and registration data Baileys uses to authenticate with WhatsApp's servers. Stored in the
sessions/<session-id>/directory. - Session metadata — the human-readable name, status, anti-ban settings, and webhook associations. Stored in PostgreSQL.
- Message queue — outgoing messages waiting to be delivered. Managed by BullMQ in Redis.
Session Lifecycle
┌─────────────────────────────────────────────────────────────────┐
│ DISCONNECTED │
│ (initial state — no credentials exist yet) │
└────────────────────────┬────────────────────────────────────────┘
│ POST /api/sessions
▼
┌─────────────────────────────────────────────────────────────────┐
│ CONNECTING │
│ WA Server opens WebSocket to WhatsApp, generates QR code │
└────┬───────────────────────────────────────────────────────┬────┘
│ QR scanned by phone │ Timeout (60s) or
▼ │ WhatsApp rejects
┌───────────────────────┐ │
│ CONNECTED │ ▼
│ Session fully active │ ┌─────────────────────────┐
│ Messages can be sent │ │ DISCONNECTED │
└──────────┬────────────┘ │ (QR expired — rescan) │
│ Network drop / └─────────────────────────┘
│ phone logs out
▼
┌─────────────────────────────────────────────────────────────────┐
│ RECONNECTING │
│ Automatic reconnect with exponential backoff │
│ Up to 5 attempts before moving to DISCONNECTED │
└─────────────────────────────────────────────────────────────────┘
Status Values
| Status | Description |
|---|---|
disconnected | No active connection. Either never connected, or explicitly disconnected. Credentials may or may not exist. |
connecting | WA Server is establishing the WebSocket connection and waiting for QR scan. |
connected | Fully authenticated and active. Messages can be sent and received. |
reconnecting | A previously connected session lost its network connection. WA Server is attempting automatic reconnection. |
banned | WhatsApp has suspended the number. Manual intervention required — the number cannot be reconnected. |
Creating a Session via API
curl -X POST https://wa.yourdomain.com/api/sessions \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "support",
"description": "Customer support line"
}'const response = await fetch('https://wa.yourdomain.com/api/sessions', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'support',
description: 'Customer support line',
}),
});
const session = await response.json();
// { id: 'sess_abc123', name: 'support', status: 'connecting', qrCode: 'data:image/png;base64,...' }The response includes a qrCode field containing a base64-encoded PNG of the QR code. Display this image to the person scanning.
QR Code Scan Flow
- Your application calls
POST /api/sessions— WA Server opens a connection to WhatsApp and generates a QR code. - The QR code is valid for 60 seconds. If not scanned in time, the session moves to
disconnectedand you must callPOST /api/sessions/:id/qrto generate a fresh QR. - The user opens WhatsApp on their phone → Settings → Linked Devices → Link a Device → scans the QR.
- WhatsApp authenticates the new device and sends back session credentials.
- WA Server stores the credentials in
sessions/<id>/and updates the session status toconnected. - The dashboard emits a
session.connectedwebhook event to all registered endpoints.
Polling for Status
If you're building a custom integration (not using the dashboard UI), poll the session status while displaying the QR:
// Poll every 2 seconds until connected or timeout
async function waitForConnection(sessionId, apiKey, timeoutMs = 90_000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const res = await fetch(`https://wa.yourdomain.com/api/sessions/${sessionId}`, {
headers: { 'X-API-Key': apiKey },
});
const session = await res.json();
if (session.status === 'connected') return session;
if (session.status === 'banned') throw new Error('Phone number is banned');
await new Promise(r => setTimeout(r, 2000));
}
throw new Error('Connection timed out');
}
Getting a Fresh QR Code
If the original QR expired before scanning:
curl -X POST https://wa.yourdomain.com/api/sessions/SESSION_ID/qr \
-H "X-API-Key: YOUR_API_KEY"
Response includes a new qrCode and a expiresAt timestamp.
Session Persistence
Session credentials are stored on disk in the sessions/ directory (Docker volume wasphere_sessions). This means:
- Sessions survive WA Server restarts without needing to re-scan the QR.
- Upgrading WaSphere does not disconnect your sessions (as long as the volume is preserved).
- Moving to a new server requires copying the volume data — see Backup & Restore.
The sessions/ directory contains raw WhatsApp authentication keys. Anyone with access to this directory can impersonate your WhatsApp accounts. Restrict filesystem permissions and never include it in backups stored in untrusted locations without encryption.
Automatic Reconnection
When a connected session loses its network connection (server restart, transient network error, WhatsApp timeout), the WA Server automatically attempts to reconnect using the stored credentials. No QR re-scan is needed.
Reconnection uses exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | 5 seconds |
| 2 | 10 seconds |
| 3 | 20 seconds |
| 4 | 40 seconds |
| 5 | 80 seconds |
After 5 failed attempts, the session status changes to disconnected and a session.disconnected webhook is fired. You can then:
- Trigger a manual reconnect via the dashboard Reconnect button
- Call
POST /api/sessions/:id/reconnectfrom your application
Multi-Session Setup
Running multiple sessions is a first-class use case in WaSphere. There is no artificial session limit — the practical limit is determined by server RAM and the WhatsApp network's tolerance for concurrent connections from a single IP.
Best practices for multi-session deployments:
Use distinct phone numbers for different purposes — e.g. support, sales, notifications. This allows you to scope API keys to individual sessions so that a compromise of one key doesn't affect others.
# Create three sessions
curl -X POST .../api/sessions -d '{"name": "support"}'
curl -X POST .../api/sessions -d '{"name": "sales"}'
curl -X POST .../api/sessions -d '{"name": "notifications"}'
Each session gets its own UUID. When sending a message, always specify the sessionId in the request body to route through the correct account.
Anti-Ban Settings per Session
Each session has configurable anti-ban parameters accessible via the dashboard or API:
| Setting | Default | Description |
|---|---|---|
msgDelayMinMs | 1000 | Minimum delay between outgoing messages (milliseconds) |
msgDelayMaxMs | 3000 | Maximum delay (actual delay is random between min and max) |
typingSimulation | true | Send typing indicator before text messages |
rateLimitPerMin | 20 | Max messages per minute (excess is queued, not dropped) |
Update per-session settings:
curl -X PATCH https://wa.yourdomain.com/api/sessions/SESSION_ID \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"msgDelayMinMs": 2000,
"msgDelayMaxMs": 6000,
"typingSimulation": true,
"rateLimitPerMin": 10
}'
Higher delays and lower rate limits significantly reduce ban risk on bulk-messaging accounts. For notification-style accounts sending to opted-in users, default settings are typically sufficient.
Disconnecting a Session
To gracefully disconnect (preserving credentials for reconnection):
curl -X POST https://wa.yourdomain.com/api/sessions/SESSION_ID/disconnect \
-H "X-API-Key: YOUR_API_KEY"
To fully delete a session and remove credentials (the phone number will need to be re-linked):
curl -X DELETE https://wa.yourdomain.com/api/sessions/SESSION_ID \
-H "X-API-Key: YOUR_API_KEY"
DELETE /api/sessions/:id is irreversible. The stored credentials are deleted from disk and the phone number is removed from WhatsApp Linked Devices on the next sync. You will need to scan a new QR code to reconnect this number.
Listing Sessions
curl https://wa.yourdomain.com/api/sessions \
-H "X-API-Key: YOUR_API_KEY"
{
"sessions": [
{
"id": "sess_abc123",
"name": "support",
"status": "connected",
"phoneNumber": "+447700900123",
"connectedAt": "2026-05-25T08:00:00.000Z",
"lastSeenAt": "2026-05-25T10:30:00.000Z"
},
{
"id": "sess_def456",
"name": "notifications",
"status": "disconnected",
"phoneNumber": null,
"connectedAt": null,
"lastSeenAt": null
}
],
"total": 2
}