# Tokens de API

> Crea, lista y revoca los tokens owf_ que autentican las peticiones a la API, la CLI y el servidor MCP.

Los tokens de API (`owf_…`) autentican la API, los SDK, la CLI y el servidor MCP. Un token actúa con el rol de su miembro, limitado al rol del propio token y, si se quiere, a una zona o a un cliente. Consulta [Autenticación](https://developers.openwaf.dev/es/api/authentication/).

| Operación | Ruta |
|---|---|
| [Listar tokens](https://developers.openwaf.dev/es/api/tokens/#list-tokens) | `GET /v1/orgs/{org}/tokens` |
| [Crear un token](https://developers.openwaf.dev/es/api/tokens/#create-token) | `POST /v1/orgs/{org}/tokens` |
| [Revocar un token](https://developers.openwaf.dev/es/api/tokens/#revoke-token) | `DELETE /v1/orgs/{org}/tokens/{id}` |

## Listar tokens

```http
GET /v1/orgs/{org}/tokens
```

Lista los tokens de API activos de la organización, nunca sus secretos. `prefix` ayuda a reconocer cada uno y `last_used_at` dice cuándo se usó por última vez.

**Rol necesario:** `admin` o superior. De toda la organización.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Respuesta

- `200`: Devuelve `items`, un array de [APIToken](https://developers.openwaf.dev/es/api/schemas/#api-token).

| Campo | Tipo | Descripción |
|---|---|---|
| `items[].id` | string (uuid) | Id. |
| `items[].org_id` | string (uuid) | Id de la organización. |
| `items[].zone_id` | string (uuid) | Id de la zona. |
| `items[].user_id` | string (uuid) | Id de usuario del miembro. |
| `items[].name` | string | Nombre. |
| `items[].role` | string | Rol. Uno de `owner`, `admin`, `tech`, `readonly`. |
| `items[].prefix` | string | Primeros caracteres del secreto, para reconocerlo. |
| `items[].purge_only` | boolean | Solo puede purgar la caché de su zona. |
| `items[].created_by` | string | Quién lo creó (actor). |
| `items[].created_at` | string (date-time) | Fecha de creación. |
| `items[].expires_at` | string (date-time) | Fecha de caducidad. |
| `items[].last_used_at` | string (date-time) | Último uso. |
| `items[].client_id` | string (uuid) o null | Cliente al que se limita el token (solo roles tech y readonly); null = toda la organización. |

#### Ejemplo

**curl**


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

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token de OPENWAF_TOKEN
const result = await owf.listTokens();
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token de OPENWAF_TOKEN
result = owf.list_tokens()
```



```json
{
  "items": [
    {
      "id": "11111111-2222-4333-8444-555555555555",
      "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
      "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
      "user_id": "5b8e2a1c-7d3f-4a9e-b6c2-1e4d7f0a3b9c",
      "name": "ci-deploy",
      "role": "tech",
      "prefix": "owf_8Jx2",
      "purge_only": false,
      "created_by": "user:5b8e2a1c-7d3f-4a9e-b6c2-1e4d7f0a3b9c",
      "created_at": "2026-10-27T09:30:00Z",
      "expires_at": "2027-01-25T09:30:00Z",
      "client_id": null
    }
  ]
}
```

## Crear un token

```http
POST /v1/orgs/{org}/tokens
```

Crea un token de API para el propio miembro de quien llama. Sin `role`, el token recibe el rol de quien lo crea. Se puede limitar a una zona (`zone_id`), a un cliente (`client_id`) o a purgar la caché de su zona (`purge_only`). Consulta [Limitar un token](https://developers.openwaf.dev/es/api/authentication/#limit-a-token).

El `secret` (`owf_…`) solo se devuelve en esta respuesta: guárdalo enseguida.

**Rol necesario:** `readonly` o superior. El rol del nuevo token no puede ser mayor que el de quien lo crea. No disponible para tokens limitados a una zona.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |

#### Cuerpo de la petición

Tipo de contenido `application/json`.

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `name` | string | Sí | Nombre. Como mucho 200 caracteres. |
| `role` | string | No | Rol del token; por defecto, el de quien lo crea (tech con purge_only). Uno de `owner`, `admin`, `tech`, `readonly`. |
| `zone_id` | string (uuid) | No | Limita el token a esa zona. |
| `expires_in_days` | integer | No | Por defecto `90`. De 1 a 365. |
| `purge_only` | boolean | No | Token que solo puede purgar la caché de su zona (POST cache/purge y GET cache/purges; cualquier otra ruta, MCP incluido, responde 403 token_scope). Exige zone_id, sin cliente; rol tech (por defecto). Por defecto `false`. |
| `client_id` | string (uuid) | No | Limita el token a las zonas de un cliente (solo roles tech y readonly). Una credencial limitada a un cliente solo emite tokens de su cliente. |

#### Respuesta

- `201`: Creado; `secret` se muestra una sola vez. Devuelve [IssuedToken](https://developers.openwaf.dev/es/api/schemas/#issued-token).

| Campo | Tipo | Descripción |
|---|---|---|
| `id` | string (uuid) | Id. |
| `org_id` | string (uuid) | Id de la organización. |
| `zone_id` | string (uuid) | Id de la zona. |
| `user_id` | string (uuid) | Id de usuario del miembro. |
| `name` | string | Nombre. |
| `role` | string | Rol. Uno de `owner`, `admin`, `tech`, `readonly`. |
| `prefix` | string | Primeros caracteres del secreto, para reconocerlo. |
| `purge_only` | boolean | Solo puede purgar la caché de su zona. |
| `created_by` | string | Quién lo creó (actor). |
| `created_at` | string (date-time) | Fecha de creación. |
| `expires_at` | string (date-time) | Fecha de caducidad. |
| `last_used_at` | string (date-time) | Último uso. |
| `client_id` | string (uuid) o null | Cliente al que se limita el token (solo roles tech y readonly); null = toda la organización. |
| `secret` | string | Se muestra una sola vez; solo se guarda su SHA-256. |

#### Errores

| Estado | Descripción |
|---|---|
| `403` | El rol o los límites del token no lo permiten (`forbidden`). |
| `404` | No existe o el token no lo ve (`not_found`). |

#### Ejemplo

**curl**


```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",
    "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
    "expires_in_days": 90
  }'
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token de OPENWAF_TOKEN
const result = await owf.createToken({
  body: {
    name: "ci-deploy",
    role: "tech",
    zone_id: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
    expires_in_days: 90
  }
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token de OPENWAF_TOKEN
result = owf.create_token(
    body={
        "name": "ci-deploy",
        "role": "tech",
        "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
        "expires_in_days": 90
    },
)
```



```json
{
  "id": "11111111-2222-4333-8444-555555555555",
  "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
  "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  "user_id": "5b8e2a1c-7d3f-4a9e-b6c2-1e4d7f0a3b9c",
  "name": "ci-deploy",
  "role": "tech",
  "prefix": "owf_8Jx2",
  "purge_only": false,
  "created_by": "user:5b8e2a1c-7d3f-4a9e-b6c2-1e4d7f0a3b9c",
  "created_at": "2026-10-27T09:30:00Z",
  "expires_at": "2027-01-25T09:30:00Z",
  "client_id": null,
  "secret": "owf_8Jx2…"
}
```

## Revocar un token

```http
DELETE /v1/orgs/{org}/tokens/{id}
```

Revoca un token; deja de valer al momento.

**Rol necesario:** `admin` o superior. De toda la organización, o cualquier rol para revocar el propio token de la petición.

#### Parámetros

| Nombre | En | Tipo | Obligatorio | Descripción |
|---|---|---|---|---|
| `org` | ruta | string (uuid) | Sí | Id de la organización. Cada ruta comprueba que es la del token (si no, `404`). |
| `id` | ruta | string (uuid) | Sí | Id del recurso. |

#### Respuesta

- `204`: Revocado. Sin cuerpo.

#### Errores

| Estado | Descripción |
|---|---|
| `404` | No existe o el token no lo ve (`not_found`). |

#### Ejemplo

**curl**


```sh
curl -X DELETE "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/tokens/11111111-2222-4333-8444-555555555555" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token de OPENWAF_TOKEN
const result = await owf.revokeToken({
  id: "11111111-2222-4333-8444-555555555555"
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token de OPENWAF_TOKEN
result = owf.revoke_token(id="11111111-2222-4333-8444-555555555555")
```
