Skip to content

Admin API ​

Header: x-admin-key: <ADMIN_API_KEY>. The dashboard uses a session cookie instead. Leave ADMIN_API_KEY unset to disable header access.

Apps ​

MethodPathDescription
POST/api/appsCreate an app. Body { "name", "webhookUrl"? }. Returns the app plus apiKey and webhookSecret, shown once.
GET/api/appsList apps with live status. Keys are never returned.
GET/api/apps/:idApp detail and live status.
PATCH/api/apps/:idUpdate { "name", "webhookUrl", "rateLimitPerMin" }.
DELETE/api/apps/:idStop the client and delete the app, session, key and message log.
POST/api/apps/:id/restartRestart the WhatsApp client.
POST/api/apps/:id/unlinkLog out the number and show a fresh QR. Keeps the app and key.
GET / POST/api/apps/:id/api-keyView the app key / issue a new one (the old key stops working).
POST/api/apps/:id/webhook-secretRotate the webhook secret. Returned only here.

Create an app ​

bash
curl -X POST https://gateway.example.com/api/apps \
  -H "x-admin-key: $ADMIN_API_KEY" -H "Content-Type: application/json" \
  -d '{"name":"Support bot","webhookUrl":"https://example.com/hook"}'
json
{
  "id": "app_9f2c...",
  "name": "Support bot",
  "apiKey": "wa_...",
  "apiKeyHint": "wa_9f2...c41d",
  "webhookUrl": "https://example.com/hook",
  "createdAt": "2026-10-01T01:50:00.000Z"
}

Dashboard helpers ​

These act on an app without its key. Use the Tenant API from your own code.

MethodPath
GET/api/apps/:id/qr
POST / DELETE/api/apps/:id/pairing-code
POST / GET/api/apps/:id/messages

Webhook queue ​

MethodPathDescription
GET/api/apps/:id/webhooks?limit=50Recent events and delivery stats.
POST/api/apps/:id/webhooks/retryRequeue failed and skipped events. Returns { "requeued": n }.
POST/api/apps/:id/webhooks/testQueue a signed webhook.test. 409 NO_WEBHOOK if no URL is set.

Sessions ​

MethodPathDescription
GET/api/sessionsEvery stored session as Running, Idle, Inactive, Unreadable or Orphan.
POST/api/sessions/cleanupDelete inactive sessions. Body { "dryRun": true, "days": 30 } previews first.
DELETE/api/apps/:id/sessionDelete one app's stored session. Refused while it is running.

Provisioning keys ​

MethodPathDescription
POST/api/provisionersCreate a key. Body { "name", "maxApps"? }. The key is shown once.
GET/api/provisionersList keys.
PATCH/api/provisioners/:provisionerIdUpdate a key.
DELETE/api/provisioners/:provisionerIdRevoke. Its apps keep running.

The same can be done from a shell: node scripts/create-provisioner.js "Tally" 200.

Dashboard sign-in ​

GET /api/auth/config, POST /api/auth/request-code, POST /api/auth/verify, GET /api/auth/me and POST /api/auth/logout implement email and one-time-code sign-in. Codes last 5 minutes, work once and allow 5 attempts. Resends are limited to one a minute and five an hour per address. Sessions last 7 days in an HttpOnly cookie.

Released under the Apache-2.0 License.