# Authentication

> Authenticate API requests with owf_ tokens, understand roles and limit a token to one zone, one client or cache purges.

Every request to the API carries an API token in the `Authorization` header. Tokens start with `owf_` and are shown only once, when they are created; OpenWAF stores only their SHA-256 hash.

```sh
curl https://dash.openwaf.dev/v1/orgs \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

A missing, invalid, expired or revoked token answers `401 unauthorized`.

## Create a token

**Dashboard**

Open **API tokens** in the organization menu, choose a name, a role, an optional zone or client and an expiry, and copy the secret: it is not shown again.

**API**

Call [Create token](https://developers.openwaf.dev/api/tokens/#create-token) with an existing token. The new token's role cannot be higher than the role of the caller.

```sh
curl -X POST "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/tokens" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"name": "ci-deploy", "role": "tech", "expires_in_days": 90}'
```


Tokens expire after `expires_in_days` (1-365, 90 by default). Revoke a token with [Revoke token](https://developers.openwaf.dev/api/tokens/#revoke-token); removing a member also invalidates all their tokens.

## Roles

Each member of an organization has a role, and each token has a role of its own. The effective role of a token is the lower of the two, so lowering a member's role also lowers their tokens.

| Role | Can |
|---|---|
| `owner` | Everything, including granting or removing the `owner` role. An organization always keeps at least one owner. |
| `admin` | Manage members, invitations, tokens, clients, white label and egress; read the audit log; everything `tech` can. |
| `tech` | Change zones: add and delete zones, records, edge settings, rules, cache purges, origin certificates. |
| `readonly` | Read everything the token can see. |

Each operation of this reference lists the minimum role it needs. **Organization-wide** means that the token (and its member) is not limited to one zone or one client.

## Limit a token

| Limit | Field | Effect |
|---|---|---|
| One zone | `zone_id` | The token only sees and changes that zone; [List zones](https://developers.openwaf.dev/api/zones/#list-zones) returns only it. |
| One client | `client_id` | The token only sees the zones of that [client](https://developers.openwaf.dev/api/clients/). Roles `tech` and `readonly` only. |
| Cache purge only | `purge_only` | The token can only purge its zone's cache ([Purge cache](https://developers.openwaf.dev/api/cache/#purge-cache) and [List purges](https://developers.openwaf.dev/api/cache/#list-cache-purges)); any other route answers `403 token_scope`. Needs `zone_id`, no client, role `tech`. |

A request on a zone or organization the token cannot see answers `404 not_found`, the same as a resource that does not exist.

## Store tokens safely

- Keep tokens in a secret manager or in environment variables (the SDKs and the CLI read `OPENWAF_TOKEN`), never in code.
- Give each integration its own token with the lowest role it needs and, when possible, limited to one zone.
- Revoke tokens you no longer use; `last_used_at` in [List tokens](https://developers.openwaf.dev/api/tokens/#list-tokens) shows when each one was last used.
