An API key is a pair of strings — a client_id and a client_secret — that your code sends on every REST API request instead of logging in. Each key belongs to your organization, carries its own rate limit, and can be turned off the moment it leaks.
Generating a key #
-
Name it after the thing that will use it
One key per integration, not one shared key for everything. When you later need to disable something, the name is what tells you which key to kill. -
Choose the WhatsApp account
Bind the key to a specific number, or leave it on Any / default. -
Generate
Theclient_idandclient_secretappear in a highlighted panel above the form, with a copy button. -
Store the secret, then reload
Once you navigate away the panel is gone for good. The list keeps showing theclient_id, which is not secret.
How a request is authenticated #
Send both credentials as headers:
x-client-id: client_xxxxxxxxxxxxxxxxxxxxxxxx
x-client-secret: secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
A missing or wrong pair returns 401, and so does a key that has been disabled. If your organization has no active subscription the call returns 403 with the code subscription_required, and if the subscription is live but the plan does not include API access it returns 403 plan_upgrade_required — the API is gated on billing exactly like the app is, and those two need different answers: renew, versus change plan. Each successful authentication stamps the key's Last used time, which is the quickest way to spot a key nothing calls any more.
Scopes #
Every endpoint declares the scope it requires. A key that does not hold the scope is refused with 403 before the handler runs:
| Field | What it does |
|---|---|
| messages.send | Send a message or a template — POST /api/v1/messages and POST /api/v1/messages/template. |
| templates.read | List your templates and their approval status — GET /api/v1/templates. |
| templates.write | Create a template and submit it to Meta — POST /api/v1/templates. |
| conversations.read | Read message history for a phone number — GET or POST /api/v1/conversations/history. |
| media.write | Upload a file and get back a public URL — POST /api/v1/media. |
Binding a key to one number #
The WhatsApp Account choice decides which number the key sends from and which contacts it can see. Bound to one account, every send goes out from that number and history lookups are limited to its conversations. Left on Any / default, the key resolves to your organization's default account, falling back to the first one you connected.
Bind keys whenever you run more than one number. Contacts are partitioned per account, so an unbound key pointed at the wrong default will happily create a duplicate contact under the other number. Connected numbers and the default flag live in WhatsApp accounts.
Rate limits, disabling and deleting #
Each key carries its own limit in requests per minute — 100 by default — counted in a rolling 60-second window for that key alone. Exceeding it returns 429 with a Retry-After header telling you how many seconds to wait; a limit of 0 means no throttling. Because the window is per key, one runaway script cannot starve your other integrations.
| Field | What it does |
|---|---|
| Disable | Flips the key to inactive. Requests start failing straight away, and enabling it again restores the same credentials. This is the reversible option — use it first when you suspect a leak. |
| Delete | Removes the key permanently after a confirmation prompt. The credentials cannot be brought back, and anything still using them breaks at the next call. |
Any member of your workspace can create, disable and delete API keys.
Keys created by connecting an app #
Not every key on this screen was typed in by hand. When you connect an outside application — you click Connect in that product, land here, choose which WhatsApp number it may send from, and approve — the permission you grant is stored as a key on this screen, named after the application.
That means everything above applies to it. The key shows which number the app sends from and how many requests a minute it may make, and deleting it is how you disconnect the app. There is nothing else to undo and no setting to find in the other product; the next call it makes fails, and it should ask you to reconnect.
You never copy a secret when connecting this way — the application receives its own credentials directly, and they are never shown to you or retrievable afterwards. If an app needs reconnecting it gets a brand new key, so the old one is safe to delete once the new connection works.