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
    • 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. The token authenticates exactly one number. Every /api/v2 endpoint is scoped to it. There is no way to reach a second number, 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? Exactly one connected 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 number itself. If part of your system should only ever touch one number, give it only that number's token.

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 any other number.

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.

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
  • One token per number, mapped to your own tenant identifier
  • 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 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
  • Rotation
  • Revocation, loss, and compromise
  • When a working integration starts returning 401
  • Environment separation
  • Auditability
  • Checklist
  • What's next