
# Listar eventos de auditoría

`GET /v1/audit-events` · permiso `audit-events:read`

Lista los registros de auditoría del entorno con paginación por cursor, del más reciente al más antiguo. El flujo `admin` contiene los cambios realizados mediante la API de gestión, el panel de control y la plataforma; el flujo `application` contiene los eventos que escribió su aplicación. Cada registro forma parte de una cadena de hash por entorno y flujo, por lo que el historial puede verificarse de forma independiente con una exportación (`POST /v1/audit-exports`).

El entorno siempre se obtiene de la clave de API; no existe un parámetro de entorno.

## Solicitud

| Parámetro | En | Obligatorio | Descripción |
|---|---|---|---|
| `limit` | query | no | Tamaño de página, de 1 a 100. Por defecto, 20. |
| `after` | query | no | Cursor opaco de `list_metadata.after` (registros más antiguos). Excluyente con `before`. |
| `before` | query | no | Cursor opaco de `list_metadata.before` (registros más recientes). Excluyente con `after`. |
| `stream` | query | no | `admin` (por defecto) o `application`. |
| `from` | query | no | Hora RFC 3339; registros en esa hora o posteriores. Por defecto, la más tardía entre el inicio del periodo de retención y `to` menos 92 días. |
| `to` | query | no | Hora RFC 3339; registros anteriores a ella. Por defecto, el momento actual. El intervalo entre `from` y `to` es de 92 días como máximo. |
| `action` | query | no | Prefijo de acción, como `user.` o `connection.updated`. |
| `category` | query | no | `authentication`, `session`, `token`, `administration`, `provisioning`, `federation`, `authorization`, `data_access`, `security`, `key_management`, `configuration` o `application`. |
| `actor_type` | query | no | Tipo de actor, como `api_key`, `dashboard_user`, `m2m_client`, `agent` o `system`. |
| `actor_id` | query | no | Id exacto del actor tal como se registró (`key_…`, `usr_…`, `system:<service>`). |
| `target_type` | query | no | Tipo de objetivo, como `user`, `organization` o `audit_export`. |
| `target_id` | query | no | Id exacto del objetivo. Con `target_type`, ambos deben coincidir con el mismo objetivo. |
| `org_id` | query | no | Registros sobre una organización (`org_…`). |
| `outcome` | query | no | `success`, `failure`, `denied` o `error`. |
| `request_id` | query | no | `Idp-Request-Id` de una petición (UUID). |
| `correlation_id` | query | no | `Idp-Correlation-Id` de un flujo de trabajo (UUID). |
| `agent_only` | query | no | `true` devuelve solo las acciones de agentes: `actor_type` `agent` o un `act_chain` no vacío. |
| `client` | query | no | Tipo de cliente que realizó la llamada: `mcp` (el servidor MCP de gestión, `metadata.client` = `mcp/<version>`) o `cli` (la CLI de KeenAuth, `cli/<version>`). El cliente declara este valor por sí mismo; no es una prueba de quién actuó, para eso está el actor del registro. Solo para listados: una exportación no tiene filtro `client`. |

Los registros siempre se ordenan por `occurred_at` (y luego por `id`), del más reciente al más antiguo; no existe un parámetro `order` (se acepta `order=desc`, cualquier otro valor falla con `validation_failed`). Un cursor solo es válido con los filtros y el entorno para los que se emitió. No se devuelve un recuento total.

Una búsqueda que tarde más de 10 segundos se detiene con `422 search_too_broad`: restrinja los filtros o el intervalo de tiempo, o use una exportación para intervalos grandes.

## Respuesta

`200 OK`. `data` contiene los registros de la página; `list_metadata.after` apunta a registros más antiguos y `list_metadata.before` a registros más recientes (`null` cuando no hay ninguno). Los campos vacíos son `null`.

`ip` y `user_agent` solo aparecen cuando la clave tiene el permiso `audit-events:read_ip`, y solo se rellenan para registros de menos de 13 meses. Sin ese permiso, los campos se omiten por completo (no se devuelve ningún valor enmascarado). `ip_prefix`, `ip_country`, `ip_asn` y `user_agent_family` siempre se devuelven. `prev_hash`, `org_prev_hash` y `record_hash` son valores SHA-256 en base64url sin relleno.

```json
{
  "data": [
    {
      "id": "evt_01j9xk3m7q8r2s4t6v8w0y2z4a",
      "stream": "admin",
      "seq": 4182,
      "schema_version": 1,
      "action": "user.blocked",
      "category": "administration",
      "outcome": "success",
      "reason_code": null,
      "occurred_at": "2026-10-01T08:15:42.120Z",
      "received_at": "2026-10-01T08:15:42.131Z",
      "recorded_at": "2026-10-01T08:15:42.140Z",
      "clock_anomaly": false,
      "actor_type": "api_key",
      "actor_id": "key_01j9xk3m7q8r2s4t6v8w0y2z4d",
      "act_chain": null,
      "session_id": null,
      "auth_context": null,
      "elevation_ref": null,
      "org_id": null,
      "targets": [
        {"type": "user", "id": "usr_0a1b2c3d4e5f6g7h8j9k0m1n2p", "org_id": null, "name": null}
      ],
      "application_id": null,
      "ip_prefix": "203.0.113.0/24",
      "ip_country": "DE",
      "ip_asn": 64500,
      "user_agent_family": "keenauth-go",
      "request_id": "0192a6c1-7d3e-7a10-9b2c-3d4e5f607182",
      "correlation_id": null,
      "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
      "producer_service": "directory",
      "policy_ref": "perm:users:write",
      "changes": {"status": {"old": "active", "new": "blocked"}},
      "metadata": null,
      "prev_hash": "n4bQgYhMfWWaL-qgxVrQFaO_TxsrC4Is0V1sFbDwCgg",
      "org_prev_hash": null,
      "record_hash": "LCa0a2j_xo_5m0U8HTBBNBNCLXBkg7-g-YpeiGJm564"
    }
  ],
  "list_metadata": {
    "before": null,
    "after": "<opaque cursor>"
  }
}
```

## Errores

Cada error es un cuerpo `application/problem+json` con un `code` estable.

| HTTP | `code` | Cuándo |
|---|---|---|
| 400 | `invalid_cursor` | El cursor tiene un formato incorrecto o no se emitió para esta petición. |
| 400 | `invalid_filter` | El servicio de auditoría rechazó un filtro, por ejemplo un intervalo de más de 92 días. |
| 400 | `range_outside_retention` | `from` o `to` están fuera del periodo de retención de auditoría de su plan. |
| 422 | `validation_failed` | Un parámetro de consulta no es válido (`limit` fuera de rango, marca de tiempo incorrecta, `to` no posterior a `from`, `stream`, `category` u `outcome` desconocidos, id con formato incorrecto, parámetro repetido, `order` distinto de `desc`). |
| 422 | `search_too_broad` | La búsqueda tardó más de 10 segundos; restrínjala. |
| 401 | `unauthenticated` | Falta la clave de API, no es válida o ha sido revocada. |
| 403 | `insufficient_permissions` | La clave no tiene `audit-events:read`. |
| 429 | `rate_limited` | Se ha superado el límite de peticiones; respete `Retry-After`. |
| 503 | `service_unavailable` | Una dependencia no está disponible temporalmente; reintente más tarde. |

## Ejemplo

```bash
curl "https://api.eu.keenauth.com/v1/audit-events?action=user.&from=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

```bash
keenauth audit-events list --action user. --from 2026-10-01T00:00:00Z
```

## Datos personales

Este endpoint contiene datos personales: eventos de auditoría. [Datos personales en las API de KeenAuth](/docs/policies/personal-data) describe qué se almacena, cuánto tiempo se conserva y cómo se elimina. No envíe categorías especiales de datos personales (salud, datos biométricos, religión, opiniones políticas, orientación sexual) en ningún campo.
