
# 감사 이벤트 목록 조회

`GET /v1/audit-events` · 권한 `audit-events:read`

환경의 감사 레코드를 커서 페이지네이션으로 최신순에 따라 조회합니다. `admin` 스트림에는 관리 API, 대시보드, 플랫폼을 통해 이루어진 변경 사항이 담기고, `application` 스트림에는 애플리케이션이 기록한 이벤트가 담깁니다. 모든 레코드는 환경 및 스트림별 해시 체인의 일부이므로, 내보내기(`POST /v1/audit-exports`)를 통해 이력을 독립적으로 검증할 수 있습니다.

환경은 항상 API 키에서 결정되며, 환경 매개변수는 없습니다.

## 요청

| 매개변수 | 위치 | 필수 | 설명 |
|---|---|---|---|
| `limit` | query | 아니요 | 페이지 크기, 1~100. 기본값 20. |
| `after` | query | 아니요 | `list_metadata.after`에서 받은 불투명 커서(더 오래된 레코드). `before`와 함께 사용할 수 없습니다. |
| `before` | query | 아니요 | `list_metadata.before`에서 받은 불투명 커서(더 최신 레코드). `after`와 함께 사용할 수 없습니다. |
| `stream` | query | 아니요 | `admin`(기본값) 또는 `application`. |
| `from` | query | 아니요 | RFC 3339 시각. 이 시각 이후 또는 같은 시각의 레코드를 조회합니다. 기본값은 보존 기간 시작 시점과 `to`에서 92일을 뺀 시점 중 더 늦은 시점입니다. |
| `to` | query | 아니요 | RFC 3339 시각. 이 시각 이전의 레코드를 조회합니다. 기본값은 현재 시각입니다. `from`부터 `to`까지의 범위는 최대 92일입니다. |
| `action` | query | 아니요 | `user.` 또는 `connection.updated`와 같은 액션 접두사. |
| `category` | query | 아니요 | `authentication`, `session`, `token`, `administration`, `provisioning`, `federation`, `authorization`, `data_access`, `security`, `key_management`, `configuration` 또는 `application`. |
| `actor_type` | query | 아니요 | `api_key`, `dashboard_user`, `m2m_client`, `agent` 또는 `system`과 같은 행위자 유형. |
| `actor_id` | query | 아니요 | 기록된 그대로의 정확한 행위자 ID(`key_…`, `usr_…`, `system:<service>`). |
| `target_type` | query | 아니요 | `user`, `organization` 또는 `audit_export`와 같은 대상 유형. |
| `target_id` | query | 아니요 | 정확한 대상 ID. `target_type`과 함께 사용하는 경우 두 값이 같은 대상과 일치해야 합니다. |
| `org_id` | query | 아니요 | 한 조직에 관한 레코드(`org_…`). |
| `outcome` | query | 아니요 | `success`, `failure`, `denied` 또는 `error`. |
| `request_id` | query | 아니요 | 요청의 `Idp-Request-Id`(UUID). |
| `correlation_id` | query | 아니요 | 워크플로의 `Idp-Correlation-Id`(UUID). |
| `agent_only` | query | 아니요 | `true`이면 에이전트 액션만 반환합니다. 즉, `actor_type`이 `agent`이거나 `act_chain`이 비어 있지 않은 레코드입니다. |
| `client` | query | 아니요 | 호출한 클라이언트의 종류. `mcp`(관리 MCP 서버, `metadata.client` = `mcp/<version>`) 또는 `cli`(KeenAuth CLI, `cli/<version>`). 이 값은 클라이언트가 스스로 선언하며, 누가 작업했는지를 증명하지 않습니다. 누가 작업했는지는 레코드의 행위자가 증명합니다. 목록 조회에서만 사용할 수 있으며, 내보내기에는 `client` 필터가 없습니다. |

레코드는 항상 `occurred_at`(그다음 `id`) 기준 최신순으로 정렬됩니다. `order` 매개변수는 없습니다. `order=desc`는 허용되며, 그 밖의 값은 `validation_failed`로 실패합니다. 커서는 발급된 필터 및 환경과 함께 사용할 때만 유효합니다. 전체 개수는 반환되지 않습니다.

10초를 넘게 걸리는 검색은 `422 search_too_broad`로 중단됩니다. 필터나 시간 범위를 좁히거나, 대용량 범위에는 내보내기를 사용하십시오.

## 응답

`200 OK`. `data`에는 해당 페이지의 레코드가 담깁니다. `list_metadata.after`는 더 오래된 레코드를, `list_metadata.before`는 더 최신 레코드를 가리킵니다. 해당 레코드가 없으면 `null`입니다. 비어 있는 필드는 `null`입니다.

`ip`와 `user_agent`는 키에 `audit-events:read_ip` 권한이 있는 경우에만 포함되며, 13개월 이내의 레코드에만 값이 채워집니다. 권한이 없으면 해당 필드는 마스킹된 값 없이 전체가 생략됩니다. `ip_prefix`, `ip_country`, `ip_asn`, `user_agent_family`는 항상 반환됩니다. `prev_hash`, `org_prev_hash`, `record_hash`는 패딩이 없는 base64url SHA-256 값입니다.

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

## 오류

모든 오류는 안정적인 `code`를 포함한 `application/problem+json` 본문으로 반환됩니다.

| HTTP | `code` | 발생 조건 |
|---|---|---|
| 400 | `invalid_cursor` | 커서 형식이 잘못되었거나, 이 요청을 위해 발급되지 않았습니다. |
| 400 | `invalid_filter` | 감사 서비스가 필터를 거부했습니다(예: 92일을 넘는 범위). |
| 400 | `range_outside_retention` | `from` 또는 `to`가 요금제의 감사 보존 기간 밖에 있습니다. |
| 422 | `validation_failed` | 쿼리 매개변수가 잘못되었습니다(`limit` 범위 초과, 잘못된 시각, `to`가 `from` 이후가 아님, 알 수 없는 `stream`, `category` 또는 `outcome`, ID 형식 오류, 매개변수 중복, `desc` 이외의 `order`). |
| 422 | `search_too_broad` | 검색이 10초를 넘었습니다. 범위를 좁히십시오. |
| 401 | `unauthenticated` | API 키가 없거나, 잘못되었거나, 폐기되었습니다. |
| 403 | `insufficient_permissions` | 키에 `audit-events:read` 권한이 없습니다. |
| 429 | `rate_limited` | 요청 한도를 초과했습니다. `Retry-After` 헤더를 존중하십시오. |
| 503 | `service_unavailable` | 종속 서비스를 일시적으로 사용할 수 없습니다. 나중에 다시 시도하십시오. |

## 예시

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

## 개인정보

이 엔드포인트는 개인정보인 감사 이벤트를 다룹니다. [KeenAuth API의 개인정보](/docs/policies/personal-data)에서 저장되는 항목, 보관 기간, 삭제 방법을 확인하십시오. 어떤 필드에도 민감정보(건강, 생체 정보, 종교, 정치적 견해, 성적 지향)를 보내지 마십시오.
