
# Elenca i log

`GET /v1/logs` · autorizzazione `logs:read`

Elenca i record di log dell'ambiente (accessi, sessioni, token, MFA, protezione dagli attacchi e altro) con paginazione a cursore, dal più recente. I record più vecchi della finestra di conservazione del tuo piano (Free 7, Startup 14, Business 30, Enterprise 90 giorni) non vengono mai restituiti.

## 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`. |
| `from` | query | no | Orario RFC 3339; record a partire da questo orario o successivi. Deve rientrare nella finestra di conservazione. |
| `to` | query | no | Orario RFC 3339; record precedenti a questo orario. Deve essere successivo a `from`. |
| `type` | query | no | Prefisso del tipo di log, come `authentication.` o `session.created`. Ripeti il parametro per fino a 20 valori; viene restituito un record che corrisponde a uno qualsiasi di essi. |
| `outcome` | query | no | `success`, `failure`, `denied` o `error`. |
| `user_id`, `org_id`, `application_id`, `connection_id`, `directory_id`, `session_id` | query | no | Corrispondenza esatta sull'id con prefisso (`usr_`, `org_`, `app_`, `conn_`, `dir_`, `ses_`). |
| `request_id` | query | no | `Idp-Request-Id` di una richiesta (UUID), per esempio l'id mostrato in una pagina di errore di accesso ospitata. |
| `correlation_id` | query | no | `Idp-Correlation-Id` di un flusso di lavoro (UUID). |
| `ip` | query | no | Indirizzo IP o blocco CIDR (`203.0.113.0/24`). Richiede `audit-events:read_ip`. |
| `ip_country` | query | no | Paese dell'IP, codice ISO 3166-1 alpha-2 in maiuscolo (`DE`). |
| `q` | query | no | Prefisso dell'indicazione mascherata dell'identificatore (`j***@`). Richiede `users:read_pii`. |

I record sono sempre ordinati per `occurred_at`, dal più recente; non esiste il parametro `order` (`order=desc` è accettato, qualsiasi altro valore fallisce con `validation_failed`). Un cursore è valido solo con i filtri per cui è stato emesso.

I filtri `ip` e `q` richiedono la rispettiva autorizzazione anche se servono solo a restringere il risultato: senza di essa la richiesta fallisce con `403 insufficient_permissions` prima di qualsiasi ricerca, così una chiave non può sondare valori che non è autorizzata a leggere.

## 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). Non viene restituito alcun conteggio totale. I campi vuoti sono `null`.

`ip`, `ip_asn`, `user_agent` e `user_agent_family` sono presenti solo quando la chiave ha l'autorizzazione `audit-events:read_ip`, e `identifier_hint` solo quando ha `users:read_pii`. Senza l'autorizzazione il campo viene omesso del tutto (nessun valore mascherato). `ip_country` viene sempre restituito.

```json
{
  "data": [
    {
      "id": "evt_01j9xk3m7q8r2s4t6v8w0y2z4a",
      "occurred_at": "2026-10-01T08:15:42.120Z",
      "type": "authentication.password.failed",
      "outcome": "failure",
      "reason_code": "invalid_credentials",
      "user_id": "usr_0a1b2c3d4e5f6g7h8j9k0m1n2p",
      "org_id": null,
      "application_id": "app_01j9xk3m7q8r2s4t6v8w0y2z4b",
      "connection_id": "conn_01j9xk3m7q8r2s4t6v8w0y2z4c",
      "directory_id": null,
      "session_id": null,
      "identifier_hint": "a***@e***.com",
      "ip": "203.0.113.7",
      "ip_country": "DE",
      "ip_asn": 64500,
      "user_agent": "Mozilla/5.0 (X11; Linux x86_64)",
      "user_agent_family": "Firefox",
      "risk": null,
      "auth_context": null,
      "act_chain": null,
      "details": {"attempt": 3},
      "request_id": "0192a6c1-7d3e-7a10-9b2c-3d4e5f607182",
      "correlation_id": null,
      "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
    }
  ],
  "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 o non è stato emesso per questa richiesta. |
| 400 | `invalid_filter` | Il servizio di log ha rifiutato un filtro o il cursore. |
| 400 | `range_outside_retention` | `from` è precedente alla finestra di conservazione del tuo piano. |
| 422 | `validation_failed` | Un parametro di query non è valido (`limit` fuori intervallo, timestamp errato, `to` non successivo a `from`, più di 20 valori `type`, id o IP malformato, parametro ripetuto). |
| 401 | `unauthenticated` | La chiave API manca, non è valida o è stata revocata. |
| 403 | `insufficient_permissions` | La chiave non ha `logs:read`, oppure usa `ip` senza `audit-events:read_ip` o `q` senza `users:read_pii` (`required_permissions` elenca ciò che la richiesta necessita). |
| 429 | `rate_limited` | È stato superato il rate limit; rispetta `Retry-After`. |
| 503 | `service_unavailable` | Una dipendenza non è temporaneamente disponibile; riprova più tardi. |

## Esempio

```bash
curl "https://api.eu.keenauth.com/v1/logs?type=authentication.&outcome=failure&from=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

## Dati personali

Questo endpoint contiene dati personali: log dell'ambiente. [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.
