Getting started
Getting started with the OmniManager API
Authentication, the response envelope, permissions and rate limits shared by every /api/v1 route.
Getting started
The OmniManager public API (/api/v1/**) gives programmatic access to a tenant's account with a per-tenant API key: shops, WhatsApp connection and sending, statuses, groups, and consent management — with the platform's anti-ban policy enforced on your behalf on every send.
Base URL: https://<your-omnimanager-host>/api/v1
Authentication
Create a key in Settings → API (requires canEditSettings), or ask an OmniManager admin to mint one for your tenant. The raw key (omk_live_…) is shown once; only its SHA-256 hash is stored, so if you lose it you must rotate, not "recover" it.
Send it on every request:
Authorization: Bearer omk_live_YOUR_KEY
(x-api-key: omk_live_YOUR_KEY is accepted as an alias.)
A key can hold an expiry and an IP allowlist; revoking a key (from Settings or the admin) takes effect immediately — the next request with that key fails 401 API_KEY_REVOKED.
Permissions
Every route requires one permission from this list (src/libs/api-keys/permissions.ts); a key only has the ones it was granted:
| Permission | Grants |
|---|---|
shops.read | list/read shops |
shops.write | create shops |
whatsapp.read | read WhatsApp channel state |
whatsapp.connect | start/poll/stop the WhatsApp connection |
messages.send | send WhatsApp messages |
messages.read | read message/delivery state |
statuses.post | post a WhatsApp status |
contacts.read | list declared (consented) contacts |
contacts.write | declare / revoke consented contacts |
groups.read | list the shop's WhatsApp groups |
GET /me needs none of these — a key with a single permission can still verify itself.
Envelope
Every response is one of two shapes:
// success
{ "success": true, "data": { /* … */ } }
// error
{ "success": false, "error": { "code": "DAILY_CAP_REACHED", "message": "…", "retryAfter": 3600 } }
Every response carries X-Request-Id (echoed back if you send one) and, once authenticated, X-RateLimit-Limit / Remaining / Reset / Scope for the bucket that request just consumed.
Common error codes
| HTTP | code | meaning |
|---|---|---|
| 401 | API_KEY_MISSING / API_KEY_INVALID / API_KEY_REVOKED / API_KEY_EXPIRED | key problems |
| 402 / 429 | QUOTA_EXCEEDED | plan quota or capability spent |
| 403 | IP_NOT_ALLOWED / TENANT_INACTIVE / FORBIDDEN_PERMISSION | access denied |
| 404 | SHOP_NOT_FOUND / MESSAGE_NOT_FOUND / DOC_ARTICLE_NOT_FOUND | |
| 409 | AMBIGUOUS_SHOP | several shops share that name — pass the id instead |
| 409 | WHATSAPP_NOT_CONFIGURED | GET connect before any POST connect |
| 422 | VALIDATION_ERROR | body/query invalid (error.fields) |
| 429 | RATE_LIMITED | per-key minute/hour/day limit (Retry-After) |
| 429 | anti-ban policy codes | see Messaging & the anti-ban policy |
| 503 | BOT_SERVICE_UNREACHABLE / WHATSAPP_NOT_CONNECTED / WHATSAPP_SESSION_LOST | session / bot down |
Rate limits and metering
Per key, by default: 60/min, 1 000/h, 10 000/day (see X-RateLimit-* headers on every response; a breach returns 429 RATE_LIMITED with Retry-After). Every call counts toward the plan's api_calls allowance, visible in GET /me; every request is logged (route template, status, latency, IP — never the request body) and visible to OmniManager admins.
First call
curl -s -H "Authorization: Bearer omk_live_YOUR_KEY" https://app.omni-manager.com/api/v1/me
returns your key's permissions, rate limits and remaining api_calls quota.