GhalaGhalaHelp Center
Back to ghala.ioghala.ioSign in
  • Getting Started
    • Ghala Documentation
    • Send Your First WhatsApp Message via API
    • Receiving Events with Webhooks
  • Commerce
    • Start Selling on WhatsApp
    • Set Up the AI Sales Agent
    • Get Paid with Snippe
  • Ai Automation
    • Configuring AI Auto-Reply for WhatsApp
    • Setting Up Human Handover Protocol
  • Campaigns Messaging
    • WhatsApp Message Templates: Complete Guide
    • Bulk WhatsApp Messaging: Complete Campaign Guide
  • Contacts Crm
    • WhatsApp Contact Management Guide
  • Best Practices
    • WhatsApp Customer Support Best Practices
    • Message Template Best Practices
  • Api Reference
    • Ghala Developer API Reference
    • Ghala API vs Meta Cloud API
    • Supported Capabilities
    • Multiple Numbers and Multi-Tenant Platforms
    • Errors and Retries
    • Limits and Quotas
    • Authentication and Access Tokens
    • Connecting and Onboarding a Number
    • Templates and Media
    • Send One-Time Codes
    • Developer Tooling
    • Versioning and Changelog

Products

  • Ghala
  • Sarufi
  • Snippe
  • Sema

Explore

  • Use Cases
  • Pricing
  • Ghala Academy
  • Blog

Developers

  • Docs
  • API Reference
  • API Quickstart
  • Webhooks Guide

Contact

  • SkyCity Mall, 9th Floor, Dar es Salaam, Tanzania
  • info@ghala.io
  • +255 699 920 009
© 2026 Neurotech Company LimitedTerms of ServicePrivacy PolicySitemap
  1. Help Center
  2. Api Reference
  3. Authentication and Access Tokens

Authentication and Access Tokens

v2

Where the token comes from, what it can reach, how it rotates, and what to do when one leaks.

What authenticates a request

One credential, one header:

Authorization: Bearer YOUR_ACCESS_TOKEN

That token is the connected number's WhatsApp access token. It is issued by Meta when the number is connected, and it is the same secret Ghala uses to send on your behalf. There is no separate, narrower API credential to mint for /api/v2.

Two consequences follow, and both matter:

  1. The token is as powerful as Ghala is on that number. Anyone holding it can message that number's customers. Treat it exactly as you would a production database password.
  2. Every request acts as exactly one number. Usually the token belongs to one number, and every /api/v2 endpoint is scoped to it. Two numbers connected from the same WhatsApp Business Account can share one token; then X-Phone-Number-Id names the number to act as. There is no way to reach a number that does not hold the token, list your numbers, or act at the account level.

Where to get it

Dashboard → Developer → Credentials. Each connected number has an entry, and each entry has an explicit reveal action.

Lists and detail views never carry the secret. They carry a masked preview — the first six and last four characters — so you can tell two tokens apart in the UI without either of them being readable over someone's shoulder. Revealing the full token is a deliberate, separate action.

Copy it into a secret manager or an environment variable. Never into code, a browser bundle, a mobile app, or git.

Token ownership and scope

Question Answer
Who issues it? Meta, when the number is connected through Embedded Signup
What does it authenticate? The connected numbers that hold it: usually one, but numbers connected from the same WhatsApp Business Account can share it
Can one token cover several numbers? Yes, when they share it. Then name one in X-Phone-Number-Id, or the request is 400 ambiguous_number
Who can read it? Members of the Ghala team that owns the number, through the explicit reveal action
Does it have scopes? No Ghala-side scopes. It grants everything /api/v2 can do for that number
Does it expire on a schedule? It is not published as having a fixed lifetime. Assume it lives until the number is reconnected or disconnected
Can I have several tokens per number? No. One number, one token
Is there a read-only variant? No

Because there are no scopes, the unit of least privilege is the token. If part of your system should only ever touch one number, give it only that number's token. A shared token reaches every number that holds it, and X-Phone-Number-Id does not limit that: it only picks which number a request acts as.

A token held by more than one number

When a token is shared, both endpoints need X-Phone-Number-Id, set to the WhatsApp phone number ID of the number to act as:

Authorization: Bearer YOUR_ACCESS_TOKEN
X-Phone-Number-Id: 106540352242922
  • Without it, the request is 400 ambiguous_number and nothing is sent. The body lists the IDs the token holds in phone_number_ids.
  • With an ID the token does not hold, the request is 403 number_not_for_token.
  • With a token held by one number, the header is optional, and that number's own ID is accepted.

No endpoint lists your numbers. Each number's Phone Number ID is on Developer → Credentials. Multiple Numbers and Multi-Tenant Platforms has the full table.

Rotation

Reconnecting a number rotates its token. That is the mechanism, and it is the only one.

  • Reconnecting issues a new token and invalidates the old one immediately. There is no overlap window and no grace period.
  • Any integration still holding the old token starts returning 401 not_authenticated on the very next call.
  • Rotating one number's token has no effect on numbers that hold a different token.

The safe sequence:

  1. Reconnect the number in the dashboard.
  2. Reveal and copy the new token.
  3. Write it to the same secret reference your code reads from.
  4. Confirm with a low-stakes call — GET /api/v2/templates?limit=1 is ideal, because it proves authentication without messaging anybody. Send X-Phone-Number-Id with it if the token covers more than one number.

If your code caches the token at boot, invalidate that cache on write, or resolve the token per request. The multi-tenant guide shows a per-request resolver.

Revocation, loss, and compromise

There is no revoke button for an access token. Reconnecting the number is revocation, because it invalidates the previous token.

If a token leaks:

  1. Reconnect the number immediately. The exposed token stops working the moment the new one is issued.
  2. Update every integration holding the old value.
  3. Audit what happened while it was exposed. The number's event log under Developer → Events holds 30 days of activity, and the dashboard audit log records consequential account actions.
  4. Find how it leaked. A token in a browser bundle, a mobile app, a log line, or a git history will leak again the same way.

Disconnecting the number is the stronger option if you need it to stop sending entirely. Note that disconnecting also frees the number to be claimed by another team, so it is not a quiet operation.

When a working integration starts returning 401

In practice this has one overwhelmingly common cause: somebody reconnected the number. Reconnection is a routine fix for other problems, so it often happens without the person doing it realising an integration depends on the old token.

Check, in order:

  1. Was the number reconnected? Compare the stored token against the masked preview in Developer → Credentials — the first six characters are enough to tell.
  2. Is the Authorization header actually being sent? A missing header and an unknown token return the same 401.
  3. Is the number still connected at all? A disconnected number has no valid token.

A missing token and an invalid token are deliberately indistinguishable, so the API cannot be used to probe which tokens exist. That means the response will not tell you which of these it is; the dashboard will.

Environment separation

Ghala has no sandbox and no test-mode credential. A token sends real messages to real handsets, and there is no dry-run flag.

So separation is a matter of using different numbers, not different keys:

  • Connect a separate number for development or staging, in its own team, and give non-production environments only that number's token.
  • If a separate number is not practical, restrict development sends to phone numbers you control, and enforce that allowlist in your own code — nothing in the API will do it for you.
  • Keep production tokens out of .env files that developers have on laptops. Non-production and production should not read from the same secret store path.

Because there is no test mode, send your first message to your own handset. It is the cheapest way to discover a mistake.

Auditability

What is available today:

  • Masked previews in the credentials list, so you can identify which token an integration holds without revealing it.
  • The event log under Developer → Events, 30 days, showing what the number actually sent and received, including the exact payloads delivered to subscribers.
  • The dashboard audit log, which records consequential actions on the account: disconnecting a number, changing the webhook override, turning the AI agent off, disconnecting a payment account.

What is not available: there is no last-used timestamp on a number's access token, and no per-request correlation id in API responses. If you need to attribute a send to a caller, log your own Idempotency-Key — it is meaningful on both sides of the call and is the closest thing to a correlation id the API offers.

A note on dashboard API keys. The dashboard can also mint team-level API keys with a label and a last-used timestamp. Those authenticate Ghala's internal dashboard API, not /api/v2. The Developer API accepts the number's WhatsApp access token and nothing else; sending an API key instead returns 401 not_authenticated.

Checklist

  • Token stored in a secret manager, not in code or git
  • Resolved per request, or cache invalidated on rotation
  • Never sent to a browser, mobile app, or end user
  • Each number's token and phone number ID, mapped to your own tenant identifier
  • X-Phone-Number-Id sent on every request, so a shared token acts as the right number
  • Non-production uses a different number, not the same token
  • A 401 triggers an alert, not a silent retry loop
  • A documented runbook for "reconnect the number, update the secret"

What's next

  • Connecting and Onboarding a Number — where the token comes from in the first place
  • Multiple Numbers and Multi-Tenant Platforms — resolving the right token and number per tenant
  • Errors and Retries — handling 401 and everything else
PreviousLimits and QuotasNextConnecting and Onboarding a Number

On this page

  • What authenticates a request
  • Where to get it
  • Token ownership and scope
  • A token held by more than one number
  • Rotation
  • Revocation, loss, and compromise
  • When a working integration starts returning 401
  • Environment separation
  • Auditability
  • Checklist
  • What's next