
# Audit-Ereignisse auflisten

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

Listet die Audit-Datensätze der Umgebung mit Cursor-Paginierung auf, neueste zuerst. Der Stream `admin` enthält Änderungen, die über die Management-API, das Dashboard und die Plattform vorgenommen wurden; der Stream `application` enthält Ereignisse, die Ihre Anwendung geschrieben hat. Jeder Datensatz ist Teil einer Hash-Kette pro Umgebung und Stream, sodass sich die Historie mit einem Export (`POST /v1/audit-exports`) unabhängig überprüfen lässt.

Die Umgebung ergibt sich immer aus dem API-Schlüssel; es gibt keinen Umgebungsparameter.

## Anfrage

| Parameter | In | Erforderlich | Beschreibung |
|---|---|---|---|
| `limit` | query | nein | Seitengröße, 1 bis 100. Standardwert 20. |
| `after` | query | nein | Undurchsichtiger Cursor aus `list_metadata.after` (ältere Datensätze). Schließt `before` aus. |
| `before` | query | nein | Undurchsichtiger Cursor aus `list_metadata.before` (neuere Datensätze). Schließt `after` aus. |
| `stream` | query | nein | `admin` (Standard) oder `application`. |
| `from` | query | nein | RFC-3339-Zeitpunkt; Datensätze ab diesem Zeitpunkt. Standardwert ist der spätere der beiden Werte: Beginn des Aufbewahrungszeitraums oder `to` minus 92 Tage. |
| `to` | query | nein | RFC-3339-Zeitpunkt; Datensätze vor diesem Zeitpunkt. Standardwert ist jetzt. Der Bereich von `from` bis `to` beträgt höchstens 92 Tage. |
| `action` | query | nein | Aktionspräfix, z. B. `user.` oder `connection.updated`. |
| `category` | query | nein | `authentication`, `session`, `token`, `administration`, `provisioning`, `federation`, `authorization`, `data_access`, `security`, `key_management`, `configuration` oder `application`. |
| `actor_type` | query | nein | Akteurtyp, z. B. `api_key`, `dashboard_user`, `m2m_client`, `agent` oder `system`. |
| `actor_id` | query | nein | Exakte Akteur-ID, wie erfasst (`key_…`, `usr_…`, `system:<service>`). |
| `target_type` | query | nein | Zieltyp, z. B. `user`, `organization` oder `audit_export`. |
| `target_id` | query | nein | Exakte Ziel-ID. Zusammen mit `target_type` müssen beide zum selben Ziel passen. |
| `org_id` | query | nein | Datensätze zu einer Organisation (`org_…`). |
| `outcome` | query | nein | `success`, `failure`, `denied` oder `error`. |
| `request_id` | query | nein | `Idp-Request-Id` einer Anfrage (UUID). |
| `correlation_id` | query | nein | `Idp-Correlation-Id` eines Workflows (UUID). |
| `agent_only` | query | nein | `true` gibt nur Agent-Aktionen zurück: `actor_type` `agent` oder ein nicht leeres `act_chain`. |
| `client` | query | nein | Art des Clients, der den Aufruf ausgeführt hat: `mcp` (der MCP-Server der Verwaltung, `metadata.client` = `mcp/<version>`) oder `cli` (die KeenAuth-CLI, `cli/<version>`). Der Client gibt diesen Wert selbst an; er ist kein Nachweis dafür, wer gehandelt hat – das ist der Akteur des Datensatzes. Nur für Listen: ein Export hat keinen `client`-Filter. |

Datensätze werden immer nach `occurred_at` (dann `id`) sortiert, neueste zuerst; es gibt keinen Parameter `order` (`order=desc` wird akzeptiert, jeder andere Wert schlägt mit `validation_failed` fehl). Ein Cursor ist nur mit den Filtern und der Umgebung gültig, für die er ausgestellt wurde. Es wird keine Gesamtanzahl zurückgegeben.

Dauert eine Suche länger als 10 Sekunden, wird sie mit `422 search_too_broad` abgebrochen: Grenzen Sie die Filter oder den Zeitraum ein oder verwenden Sie für große Zeiträume einen Export.

## Antwort

`200 OK`. `data` enthält die Datensätze der Seite; `list_metadata.after` verweist auf ältere Datensätze und `list_metadata.before` auf neuere (`null`, wenn keine vorhanden sind). Leere Felder sind `null`.

`ip` und `user_agent` sind nur enthalten, wenn der Schlüssel die Berechtigung `audit-events:read_ip` besitzt, und werden nur für Datensätze ausgefüllt, die jünger als 13 Monate sind. Ohne diese Berechtigung werden die Felder vollständig weggelassen (kein maskierter Wert). `ip_prefix`, `ip_country`, `ip_asn` und `user_agent_family` werden immer zurückgegeben. `prev_hash`, `org_prev_hash` und `record_hash` sind SHA-256-Werte in base64url ohne 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>"
  }
}
```

## Fehler

Jeder Fehler ist ein `application/problem+json`-Body mit einem stabilen `code`.

| HTTP | `code` | Wann |
|---|---|---|
| 400 | `invalid_cursor` | Der Cursor ist fehlerhaft oder wurde nicht für diese Anfrage ausgestellt. |
| 400 | `invalid_filter` | Der Audit-Dienst hat einen Filter abgelehnt, z. B. einen Bereich von mehr als 92 Tagen. |
| 400 | `range_outside_retention` | `from` oder `to` liegt außerhalb des Audit-Aufbewahrungszeitraums Ihres Tarifs. |
| 422 | `validation_failed` | Ein Abfrageparameter ist ungültig (`limit` außerhalb des Bereichs, fehlerhafter Zeitstempel, `to` nicht nach `from`, unbekannter `stream`, `category` oder `outcome`, fehlerhafte ID, wiederholter Parameter, `order` ungleich `desc`). |
| 422 | `search_too_broad` | Die Suche hat länger als 10 Sekunden gedauert; grenzen Sie sie ein. |
| 401 | `unauthenticated` | Der API-Schlüssel fehlt, ist ungültig oder wurde widerrufen. |
| 403 | `insufficient_permissions` | Dem Schlüssel fehlt `audit-events:read`. |
| 429 | `rate_limited` | Das Rate-Limit wurde überschritten; beachten Sie `Retry-After`. |
| 503 | `service_unavailable` | Eine Abhängigkeit ist vorübergehend nicht verfügbar; versuchen Sie es später erneut. |

## Beispiel

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

## Personenbezogene Daten

Dieser Endpunkt verarbeitet personenbezogene Daten: Audit-Ereignisse. [Personenbezogene Daten in den KeenAuth-APIs](/docs/policies/personal-data) beschreibt, welche Daten gespeichert werden, wie lange sie aufbewahrt werden und wie sie gelöscht werden. Übermitteln Sie in keinem Feld besondere Kategorien personenbezogener Daten (Gesundheit, biometrische Daten, Religion, politische Meinungen, sexuelle Orientierung).
