# Authentication

> Bearer API keys, key rotation, platform (app) keys and the tenant header.

Canonical: https://docs.whabuzz.com/authentication/

Every `/v1` call carries an API key as a Bearer token:

```bash
curl https://api.whabuzz.com/v1/tenant -H "Authorization: Bearer wb_live_EXAMPLEKEY000000000000000000000000"
```

Only [`GET /v1/health`](https://docs.whabuzz.com/api/health.md#getHealth) is public.

## Keys {#keys}

- Format: `wb_live_` or `wb_test_` followed by 40 characters. The environment is a label that lets you keep staging credentials apart. Both hit the real WhatsApp Cloud API.
- The full key is returned once, when you create or rotate it. WhaBuzz stores only a hash and the first 12 characters (`prefix`) for display.
- Tenant owners and admins manage keys; agents cannot.

### Rotate {#rotate}

[`POST /v1/api-keys/{key_id}/rotate`](https://docs.whabuzz.com/api/api-keys.md#rotateApiKey) creates a new key with the same name and environment and lets the old one keep working for 24 hours, so you can deploy the new key without downtime.

### Revoke {#revoke}

[`DELETE /v1/api-keys/{key_id}`](https://docs.whabuzz.com/api/api-keys.md#revokeApiKey) revokes immediately. Keys are cached briefly for speed, so a revoked key usually stops working within 30 seconds, and in the worst case within about 90 seconds.

## Platform keys {#platform-keys}

If you run a platform that serves many businesses (an app in WhaBuzz terms), a WhaBuzz administrator issues you an **app key**. It is not tied to one business. On tenant routes, say which business you mean with a header:

```bash
curl https://api.whabuzz.com/v1/numbers \
  -H "Authorization: Bearer $WHABUZZ_APP_KEY" \
  -H "X-WhaBuzz-Tenant: a578246e-b97f-48e6-ae42-939ec3ccf917"
```

WhaBuzz checks that the tenant belongs to your app. Missing header on a tenant route is `400 invalid_request`. The `/v1/tenants` routes (create and list your businesses) need no header. See [Tenants](https://docs.whabuzz.com/guides/tenants.md).

## Account status gates {#status}

A key works only while its tenant allows it:

| Tenant status | `/v1` behaviour |
|---|---|
| `pending_approval`, `rejected` | `403 tenant_not_approved` on everything except `GET /v1/tenant` |
| `active` | allowed |
| `suspended` | `403 tenant_suspended` on everything except `GET /v1/tenant`, `GET /v1/billing*` and `GET /v1/events*`. Inbound messages are still forwarded to your endpoints. |

## Response headers {#headers}

Every response carries `X-WhaBuzz-Request-Id` (quote it to support), `X-WhaBuzz-Processing-Ms` and `Server-Timing: wb;dur=<our ms>, meta;dur=<Meta's ms>`. Send responses also carry `X-WhaBuzz-Event-Id`. See [Rate limits and pacing](https://docs.whabuzz.com/guides/rate-limits.md) for how to read the timing split.
