Authentication & channels

Every WhatsApp API call authenticates with a key and targets a channel (a connected WhatsApp number). There are two kinds of key:

  • Your org API key (vai_live_…) — for your own server sending from your own org. No app needed. See Use your org API key instead.
  • An app key (vai_app_…) — for an app that other orgs install. It carries only the scopes each org approved.

This page shows how to get each key, which scopes each call needs, and how to look up your channelId.


Use your org API key instead

If your server only sends and reads for your own org, use the org API key you create under Developers → API keys in the dashboard. Send it in the X-API-Key header to the org routes under /api/orgs/{orgId}:

# Your channels — read `id` from data.channels[]
curl https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/channels \
  -H "X-API-Key: vai_live_…"
# Send a text
curl -X POST https://api.telenow.ai/api/orgs/{orgId}/whatsapp-hub/channels/{channelId}/send \
  -H "X-API-Key: vai_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "to": "+919876543210", "body": "Hi Asha! Your order #1234 has shipped." }'
{ "success": true, "data": { "wamid": "wamid.HBgLMTQx…" } }
Routes under /api/orgs/{orgId}Org API key
/whatsapp-hub/* — channels, send, inbox, contacts, saved audiences, quick repliesYes
/whatsapp-campaigns/* — broadcasts, opt-outsYes
/whatsapp-cloud/channels/{channelId}/* — templates, account health, business profileYes
/whatsapp-cloud/* (everything else) — connecting a number, registrations, account and number lists, usageNo — dashboard login only, even the reads; connecting is a Meta login in a browser
/whatsapp/* — linking a WhatsApp Web number by QRNo — dashboard login only

Every org-key route is listed in the API reference. How the key is checked:

  • Its own org only. Another org's id in the path returns 403.
  • Its role. A viewer key can only read. Sending and any other change needs an owner, admin or developer key.
  • It acts as the person who created it. Owner/admin-only actions (such as adding or removing a channel) need that person to be an owner or admin, and messages sent with the key show them as the sender.
  • Reading can have side effects. GET …/threads/{threadId}/messages marks the conversation read for the key's creator and can send the customer blue ticks — see Reading conversations.

Limits

These apply to org-API-key calls. They differ from the app-key limits on Errors & limits.

LimitValue
Requests2,000 per 15 minutes per IP address. Every request from that address that isn't signed in to the dashboard counts — WhatsApp and any other API-key call. (Signed-in dashboard use has its own budget: 3,000 per 15 minutes per user.)
Request body2 MB on JSON routes — a 20,000-row recipient upload with variables may need splitting
Media upload — POST /whatsapp-hub/channels/{channelId}/mediaUp to 101 MB per request. Per file: image 5 MB, video 16 MB, audio 16 MB, sticker 500 KB, document 100 MB — see Media
Template header media — POST /whatsapp-cloud/channels/{channelId}/templates/media16 MB
Broadcast recipients — POST /whatsapp-campaigns/{id}/recipientsUp to 20,000 per upload
Broadcast from a saved audience — POST /whatsapp-campaigns/{id}/recipients-from-segmentTakes at most 5,000 matching contacts — the most recently updated ones. When more matched, the response says so: "capped": true (with "cap": 5000). For a larger audience, upload the list instead.

Over the request limit you get a 429. retryAfter (also sent as the Retry-After header) is the number of seconds until the 15-minute window resets:

{ "success": false, "error": "Too many requests, please try again later", "retryAfter": 412 }

Sending the same message to many people? Use a broadcast: one request carries the whole list, while one /send per person spends the request budget quickly. WhatsApp's own rules (the 24-hour window, per-recipient pacing) apply on top — see Errors & limits.

To receive incoming messages on your server, subscribe with the same key — see Webhooks & events.

Get an app key

In the dashboard, install or open your app and create a key (owner/admin only). The secret is shown once — it looks like vai_app_xxxxxxxxxxxxxxxx. Copy it and store it somewhere safe; you can't retrieve it again, only rotate it.

The key must hold the scope each call requires (see below). Scopes are declared in the app manifest and consented at install time.

Send the key

Put the key in the Authorization header as a bearer token on every request:

Authorization: Bearer vai_app_xxxxxxxxxxxxxxxx

The X-App-Key header is also accepted if you prefer:

X-App-Key: vai_app_xxxxxxxxxxxxxxxx

Call these endpoints from your server, never the browser — an app key is a full credential.

Scopes

Each WhatsApp route requires one of these scopes. A missing scope returns 403. See App scopes for the full model.

ScopeGrants
whatsappSend messages, read threads & message history, upload/download media, mark messages read, list templates
whatsapp:templatesCreate and edit templates, upload template header media
whatsapp:campaignCreate and control broadcasts
whatsapp:webAlso list and send plain text on WhatsApp Web numbers (linked by QR)

Which scope a given call needs is noted on each reference page — e.g. Send and Media need whatsapp; Manage templates needs whatsapp:templates; Broadcasts needs whatsapp:campaign.

Find your channelId

Every send targets a channel — one of your connected WhatsApp numbers. List them and read the id:

curl https://api.telenow.ai/api/app-whatsapp/channels \
  -H "Authorization: Bearer vai_app_…"
{
  "success": true,
  "data": {
    "channels": [
      { "id": "b1e2c3d4-…", "label": "Acme Support", "phone": "+14155550100", "kind": "cloud" }
    ]
  }
}

Use that id as the channelId in every send, and in the /channels/{id}/… path segments throughout these docs.

FieldMeaning
idThe channel id — pass as channelId (or in the path)
labelHuman-friendly name you set when connecting the number
phoneThe channel's WhatsApp number, in E.164
kindcloud — a Meta Cloud number (native or your own Meta app) — or web, a WhatsApp Web number

GET /channels requires the whatsapp scope. If it returns an empty list, connect a number first — see the WhatsApp guide. Meta Cloud numbers appear here, and WhatsApp Web numbers too when the key holds whatsapp:web. Partner numbers (GupShup, Plivo, AiSensy) don't — use your org API key for those.

Dashboard JWT alternative

The same operations are available under /api/orgs/{orgId} using a user JWT instead of an app key — useful when you're building your own dashboard UI rather than a standalone integration. (For a server, use your org API key on these routes instead.) Send Authorization: Bearer <jwt> plus X-Org-Id: {orgId}; routes live under /api/orgs/{orgId}/whatsapp-hub/* (send & inbox), /whatsapp-cloud/* (onboarding, templates, health) and /whatsapp-campaigns/* (broadcasts). See Authentication for how JWTs and org ids work — see Onboarding API for the connect/registration endpoints.