Nex Messages Hub Developer API
Welcome to the Nex Messages Hub API documentation. Developers can use these HTTP endpoints to query active sessions, inspect delivery statistics, and dispatch automated messages concurrently across isolated virtual sessions.
x-api-key: YOUR_KEY, as a Bearer Token (Authorization: Bearer YOUR_KEY), or as a query parameter (?apiKey=YOUR_KEY). You can generate or refresh your key directly in the sidebar of the main dashboard.
Create an account, log in to receive your Developer API Key, and regenerate the key whenever needed. Every API request is authenticated using one of the following methods:
Authentication Methods
| Method | Example | Description |
|---|---|---|
| x-api-key header | x-api-key: whub_... | Preferred for server-to-server API integrations |
| Bearer token | Authorization: Bearer whub_... | Alternative header-based authentication |
| Query parameter | ?apiKey=whub_... | Useful for simple GET requests |
| UI user session | x-user-id: username | Used internally by the dashboard after login |
/api/admin/* additionally require an account with the isAdmin flag set. Non-admin accounts receive 403 Access denied.
Authenticate with your username and password. On success you receive your user profile including the Developer API Key used to authorize all subsequent API calls.
Request Body (JSON)
| Field | Type | Requirement | Description |
|---|---|---|---|
| username | string | Required | Your account username |
| password | string | Required | Your account password |
Response Example (200 OK)
{
"success": true,
"user": {
"username": "client1",
"name": "Alice Corp",
"apiKey": "whub_8a0b48dd...",
"isAdmin": false
}
}
Create a new self-service account. A Developer API Key is generated automatically for the new account.
Request Body (JSON)
| Field | Type | Requirement | Description |
|---|---|---|---|
| username | string | Required | Desired username (must be unique) |
| password | string | Required | Desired password |
| name | string | Required | Display name (e.g. Alice Corp) |
Response Example (200 OK)
{
"success": true,
"message": "Account registered successfully!"
}
Error Responses
// 400 - Username already taken
{
"success": false,
"error": "Username is already taken."
}
Generate (or regenerate) a fresh Developer API Key for your own account. The previous key is invalidated immediately.
Headers
| Header | Type | Requirement | Description |
|---|---|---|---|
| x-api-key | string | Required | Your current developer API key (any valid auth method also works) |
Response Example (200 OK)
{
"success": true,
"apiKey": "whub_1f2e3d4c5b6a..."
}
Retrieve user-level statistics (total sessions, connected sessions, total API messages sent, and total incoming messages received) along with an array of available (connected) sessions ready to dispatch messages.
Headers
| Header | Type | Requirement | Description |
|---|---|---|---|
| x-api-key | string | Required | Your developer API key (e.g. whub_8a0b48...) |
Response Example (200 OK)
{
"success": true,
"stats": {
"totalSessionsCount": 1,
"connectedSessionsCount": 1,
"totalMessagesSent": 25,
"totalMessagesReceived": 105
},
"availableSessions": [
{
"id": "client1_sales",
"label": "sales",
"phoneNumber": "201030101482",
"messagesSent": 25,
"messagesReceived": 105
}
],
"allSessions": [
{
"id": "client1_sales",
"label": "sales",
"state": "CONNECTED",
"phoneNumber": "201030101482",
"messagesSent": 25,
"messagesReceived": 105,
"isAvailable": true
}
]
}
Simpler global message sending API. Supports flexible account resolution (by Session ID, Custom Name Label, or Phone Number) and dispatches a text message. Stats are only incremented if sent successfully through this API.
Request Body (JSON)
| Field | Type | Requirement | Description |
|---|---|---|---|
| to | string | Required | Recipient phone number with country code (e.g. 15550199). Also accepts number or phoneNumber. |
| message | string | Required | Message body content. Also accepts text. |
| instanceName | string | Optional | Nickname label of the sender session (e.g. sales or support). Also accepts instanceLabel. |
| senderPhone | string | Optional | Phone number of the sender instance (e.g. 201030101482). Matches numeric digits. |
| sessionId | string | Optional | Direct session identifier (e.g. client1_sales or just sales). Also accepts from. |
Curl Example
curl -X POST http://localhost:3000/api/send \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY_HERE" \
-d '{
"instanceName": "sales",
"to": "15551234567",
"message": "Hello from the developer API!"
}'
Response Example (200 OK)
{
"success": true,
"message": "Message sent successfully!",
"sessionId": "client1_sales",
"messageId": "3EB0C61BA6553000AD279A"
}
List all instance sessions associated with your user account, detailing connection states, pairing status, and message metrics.
Response Example (200 OK)
{
"success": true,
"sessions": [
{
"id": "client1_sales",
"state": "CONNECTED",
"phoneNumber": "201030101482",
"pairingCode": null,
"qr": null,
"qrImageUrl": null,
"error": null,
"owner": "client1",
"receiveFromIndividuals": true,
"receiveFromGroups": false,
"messagesSent": 25,
"messagesReceived": 105
}
]
}
Initialize a new isolated session. If phoneNumber is supplied, it requests a pairing code instead of a QR code.
Request Body (JSON)
| Field | Type | Requirement | Description |
|---|---|---|---|
| instanceName | string | Optional | Unique label suffix for this session (e.g. sales) |
| phoneNumber | string | Optional | Phone number with country code if requesting a Pairing Code link method (e.g. 15551234567) |
Response Example (200 OK)
{
"success": true,
"session": {
"id": "client1_sales",
"state": "PAIRING_CODE",
"phoneNumber": "15551234567",
"pairingCode": "ABCD1234",
"error": null,
"owner": "client1"
}
}
Retrieve connection parameters, error alerts, QR code representations, pairing codes, and message metrics for a single specific session.
Response Example (200 OK)
{
"success": true,
"session": {
"id": "client1_sales",
"state": "CONNECTED",
"phoneNumber": "201030101482",
"pairingCode": null,
"qr": null,
"qrImageUrl": null,
"error": null,
"owner": "client1",
"receiveFromIndividuals": true,
"receiveFromGroups": false,
"messagesSent": 25,
"messagesReceived": 105
}
}
Returns the current WhatsApp QR code for the session as a self-contained base64-encoded PNG image. Use this endpoint to embed the QR code directly in a client website without external dependencies. The QR code rotates automatically; poll this endpoint every few seconds to get fresh codes.
How to display the QR on your website
The qrDataUrl field is a ready-to-use base64 data URL. Simply set it as the src of an tag:
Response Example (200 OK)
{
"success": true,
"sessionId": "client1_sales",
"qr": "raw-qr-string-from-whatsapp",
"qrDataUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5...",
"state": "QR_CODE",
"pairingCode": null,
"error": null
}
Response Fields
| Field | Type | Description | ||
|---|---|---|---|---|
| qr | string | Raw QR code data string from WhatsApp (null if no QR pending) | ||
| qrDataUrl | string | Base64-encoded PNG data URL — use directly as |
string | Current session state (QR_CODE, PAIRING_CODE, CONNECTING, etc.) |
| pairingCode | string | Current pairing code if available, else null | ||
| error | string | Error message if any |
Generate or regenerate a link-device pairing code for an existing session. Use this when you want to link a device via phone number instead of QR code. The session must not already be connected/registered.
Request Body (JSON)
| Field | Type | Requirement | Description |
|---|---|---|---|
| phoneNumber | string | Required | Phone number with country code (e.g. 15551234567) |
Response Example (200 OK)
{
"success": true,
"sessionId": "client1_sales",
"pairingCode": "ABCD-1234"
}
Error Responses
// 500 - Session already connected
{
"success": false,
"error": "Session 'client1_sales' is already connected. No pairing code is needed."
}
// 400 - Missing phone number
{
"success": false,
"error": "A phone number is required to generate a pairing code."
}
Dynamically alter routing properties. Choose whether this instance processes single direct chats, group chats, or both.
Request Body (JSON)
| Field | Type | Requirement | Description |
|---|---|---|---|
| receiveFromIndividuals | boolean | Optional | Toggle listening to single direct contacts (default: true) |
| receiveFromGroups | boolean | Optional | Toggle listening inside group chats (default: true) |
Response Example (200 OK)
{
"success": true,
"message": "Settings updated successfully.",
"config": {
"sessionId": "client1_sales",
"owner": "client1",
"receiveFromIndividuals": true,
"receiveFromGroups": false,
"messagesSent": 25,
"messagesReceived": 105
}
}
Direct endpoint to send a message via a specific targeted session. Updates stats for that session only.
Request Body (JSON)
| Field | Type | Requirement | Description |
|---|---|---|---|
| to | string | Required | Recipient phone number with country code (e.g. 15551234567) or full JID |
| message | string | Required | Message body content |
Response Example (200 OK)
{
"success": true,
"message": "Message sent successfully!",
"messageId": "3EB0C61BA6553000AD279A"
}
Trigger a reconnection attempt for an existing session (e.g. after it drops offline). Re-initializes the socket using the stored credentials.
Response Example (200 OK)
{
"success": true,
"message": "Reconnection triggered.",
"state": "CONNECTING"
}
Disconnect a session, unlink the WhatsApp device, and permanently delete its stored credentials and configuration. This action cannot be undone — the device must be re-linked afterwards.
Response Example (200 OK)
{
"success": true,
"message": "Session 'client1_sales' logged out and deleted successfully."
}
List every user account with consolidated statistics and all sessions owned by each user. Administrator access required.
Headers
| Header | Type | Requirement | Description |
|---|---|---|---|
| x-api-key | string | Required | API key of an account with isAdmin: true |
Response Example (200 OK)
{
"success": true,
"users": [
{
"username": "client1",
"name": "Alice Corp",
"password": "password123",
"apiKey": "whub_8a0b48dd...",
"isAdmin": false,
"stats": {
"totalSessionsCount": 1,
"connectedSessionsCount": 1,
"totalMessagesSent": 25,
"totalMessagesReceived": 105
},
"sessions": [
{
"id": "client1_sales",
"label": "sales",
"state": "CONNECTED",
"phoneNumber": "201030101482",
"messagesSent": 25,
"messagesReceived": 105
}
]
}
]
}
Create a new user account on behalf of a client. Administrator access required.
Request Body (JSON)
| Field | Type | Requirement | Description |
|---|---|---|---|
| username | string | Required | Unique username (lowercased automatically) |
| password | string | Required | Account password |
| name | string | Required | Display name |
| isAdmin | boolean | Optional | Grant administrator privileges (default: false) |
Response Example (200 OK)
{
"success": true,
"message": "Account for 'client3' registered successfully!"
}
Update the password for a specific user account. Administrator access required.
Path Parameter
| Parameter | Type | Requirement | Description |
|---|---|---|---|
| username | string | Required | Username of the target account |
Request Body (JSON)
| Field | Type | Requirement | Description |
|---|---|---|---|
| password | string | Required | New password for the account |
Response Example (200 OK)
{
"success": true,
"message": "Password for user 'client1' updated successfully."
}
Regenerate the API key for a specific user account. The previous key is invalidated immediately. Administrator access required.
Path Parameter
| Parameter | Type | Requirement | Description |
|---|---|---|---|
| username | string | Required | Username of the target account |
Response Example (200 OK)
{
"success": true,
"apiKey": "whub_9f8e7d6c5b4a..."
}
Permanently delete a user account along with all of its WhatsApp sessions and stored credentials. Administrator access required. You cannot delete your own logged-in admin account.
Path Parameter
| Parameter | Type | Requirement | Description |
|---|---|---|---|
| username | string | Required | Username of the account to delete |
Response Example (200 OK)
{
"success": true,
"message": "User 'client3' and all associated sessions deleted successfully."
}
Inspect the message dispatch queue, the active rate-limit/circuit-breaker configuration, and the number of messages currently pending per session. Administrator access required.
Response Example (200 OK)
{
"success": true,
"queue": {
"disabled": false,
"delayMin": 2000,
"delayMax": 6000,
"dailyLimit": 200,
"maxRetries": 2,
"pendingBySession": {
"client1_sales": 3
}
}
}
To protect your numbers from WhatsApp policy blocks when sending messages at scale, every message dispatched through POST /api/send and POST /api/sessions/:id/send is routed through a human-paced dispatch queue.
How it works
- Paced delivery: messages for a given session are sent one at a time with a randomized delay between them (mimics human typing/reading) so sends never look robotic.
- Daily send cap: each session has a daily limit (default
200messages/day, persisted per session). Once reached, further sends are rejected withDaily send limit reached for session …until the next calendar day. - Circuit breaker: if a session returns repeated send failures, the queue pauses that session for a cooldown window instead of hammering WhatsApp.
- Terminal disconnect protection: sessions WhatsApp blocks (e.g. status
405) are parked asDISCONNECTEDand are not auto-reconnected, preventing infinite reconnect loops.
Configuration (environment variables)
| Variable | Type | Default | Description |
|---|---|---|---|
| SEND_QUEUE_DISABLED | boolean | false |
Set true to bypass the queue and send instantly (not recommended for bulk sends). |
| SEND_DELAY_MIN_MS | number | 2000 |
Minimum delay between messages on a session. |
| SEND_DELAY_MAX_MS | number | 6000 |
Maximum delay between messages on a session. |
| SEND_DAILY_LIMIT | number | 200 |
Maximum messages sent per session per day. |
| SEND_CIRCUIT_FAILURES | number | 5 |
Consecutive failures before the circuit opens. |
| SEND_CIRCUIT_COOLDOWN_MS | number | 600000 |
Cooldown (ms) while the circuit is open. |
| MAX_RECONNECT_ATTEMPTS | number | 5 |
Max automatic reconnect attempts before a session is parked as DISCONNECTED. |