
# Elenca eventi di audit

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

Elenca i record di audit dell'ambiente con paginazione a cursore, dal più recente al più vecchio. Il flusso `admin` contiene le modifiche fatte tramite l'API di gestione, la dashboard e la piattaforma; il flusso `application` contiene gli eventi scritti dalla tua applicazione. Ogni record fa parte di una catena di hash per ambiente e flusso, quindi la cronologia può essere verificata in modo indipendente con un export (`POST /v1/audit-exports`).

L'ambiente proviene sempre dalla chiave API; non esiste un parametro per l'ambiente.

## Richiesta

| Parametro | In | Obbligatorio | Descrizione |
|---|---|---|---|
| `limit` | query | no | Dimensione della pagina, da 1 a 100. Predefinito 20. |
| `after` | query | no | Cursore opaco da `list_metadata.after` (record più vecchi). Esclusivo con `before`. |
| `before` | query | no | Cursore opaco da `list_metadata.before` (record più recenti). Esclusivo con `after`. |
| `stream` | query | no | `admin` (predefinito) oppure `application`. |
| `from` | query | no | Orario RFC 3339; record a partire da questo orario. Predefinito: il più recente tra l'inizio della finestra di conservazione e `to` meno 92 giorni. |
| `to` | query | no | Orario RFC 3339; record prima di questo orario. Predefinito: ora. L'intervallo da `from` a `to` è al massimo di 92 giorni. |
| `action` | query | no | Prefisso dell'azione, ad esempio `user.` o `connection.updated`. |
| `category` | query | no | `authentication`, `session`, `token`, `administration`, `provisioning`, `federation`, `authorization`, `data_access`, `security`, `key_management`, `configuration` oppure `application`. |
| `actor_type` | query | no | Tipo di attore, ad esempio `api_key`, `dashboard_user`, `m2m_client`, `agent` o `system`. |
| `actor_id` | query | no | ID esatto dell'attore come registrato (`key_…`, `usr_…`, `system:<service>`). |
| `target_type` | query | no | Tipo di destinazione, ad esempio `user`, `organization` o `audit_export`. |
| `target_id` | query | no | ID esatto della destinazione. Con `target_type`, entrambi devono corrispondere alla stessa destinazione. |
| `org_id` | query | no | Record relativi a un'organizzazione (`org_…`). |
| `outcome` | query | no | `success`, `failure`, `denied` oppure `error`. |
| `request_id` | query | no | `Idp-Request-Id` di una richiesta (UUID). |
| `correlation_id` | query | no | `Idp-Correlation-Id` di un flusso di lavoro (UUID). |
| `agent_only` | query | no | `true` restituisce solo le azioni degli agenti: `actor_type` `agent` oppure un `act_chain` non vuoto. |
| `client` | query | no | Tipo di client che ha effettuato la chiamata: `mcp` (il server MCP di gestione, `metadata.client` = `mcp/<version>`) oppure `cli` (la CLI di KeenAuth, `cli/<version>`). Il client dichiara questo valore da sé; non è una prova di chi ha agito, lo è l'attore del record. Solo per l'elenco: un export non ha il filtro `client`. |

I record sono sempre ordinati per `occurred_at` (poi `id`), dal più recente al più vecchio; non esiste un parametro `order` (`order=desc` è accettato, qualsiasi altro valore fallisce con `validation_failed`). Un cursore è valido solo con i filtri e l'ambiente per cui è stato emesso. Non viene restituito alcun conteggio totale.

Una ricerca che impiega più di 10 secondi si interrompe con `422 search_too_broad`: restringi i filtri o l'intervallo di tempo, oppure usa un export per intervalli ampi.

## Risposta

`200 OK`. `data` contiene i record della pagina; `list_metadata.after` punta ai record più vecchi e `list_metadata.before` a quelli più recenti (`null` quando non ce ne sono). I campi vuoti sono `null`.

`ip` e `user_agent` sono presenti solo quando la chiave ha l'autorizzazione `audit-events:read_ip` e sono valorizzati solo per i record più recenti di 13 mesi. Senza l'autorizzazione i campi vengono omessi del tutto (nessun valore mascherato). `ip_prefix`, `ip_country`, `ip_asn` e `user_agent_family` vengono sempre restituiti. `prev_hash`, `org_prev_hash` e `record_hash` sono valori SHA-256 in base64url senza padding.

```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>"
  }
}
```

## Errori

Ogni errore è un corpo `application/problem+json` con un `code` stabile.

| HTTP | `code` | Quando |
|---|---|---|
| 400 | `invalid_cursor` | Il cursore è malformato oppure non è stato emesso per questa richiesta. |
| 400 | `invalid_filter` | Il servizio di audit ha rifiutato un filtro, ad esempio un intervallo superiore a 92 giorni. |
| 400 | `range_outside_retention` | `from` o `to` è fuori dalla finestra di conservazione dell'audit del tuo piano. |
| 422 | `validation_failed` | Un parametro di query non è valido (`limit` fuori intervallo, timestamp errato, `to` non successivo a `from`, `stream`, `category` o `outcome` sconosciuto, ID malformato, parametro ripetuto, `order` diverso da `desc`). |
| 422 | `search_too_broad` | La ricerca ha impiegato più di 10 secondi; restringila. |
| 401 | `unauthenticated` | La chiave API manca, non è valida o è stata revocata. |
| 403 | `insufficient_permissions` | La chiave non ha `audit-events:read`. |
| 429 | `rate_limited` | È stato superato il limite di richieste; rispetta `Retry-After`. |
| 503 | `service_unavailable` | Una dipendenza è temporaneamente non disponibile; riprova più tardi. |

## Esempio

```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
```

## Dati personali

Questo endpoint contiene dati personali: eventi di audit. [Dati personali nelle API di KeenAuth](/docs/policies/personal-data) descrive cosa viene memorizzato, per quanto tempo viene conservato e come viene cancellato. Non inviare categorie particolari di dati personali (salute, dati biometrici, religione, opinioni politiche, orientamento sessuale) in nessun campo.
