
# Get an audit export

`GET /v1/audit-exports/{export_id}` · permission `audit-exports:read`

Returns an export job and its status: `queued`, `running`, `completed`, `failed` or `expired`.

## Request

| Parameter | In | Required | Description |
|---|---|---|---|
| `export_id` | path | yes | Export job id, prefixed with `aex_`. |

## Response

`200 OK` and the job. Empty fields are `null`.

- `record_count`, `file` and `manifest_sha256` are filled only for `completed` and `expired` jobs. `file` describes `records.ndjson.gz` inside the package (`sha256` is hexadecimal).
- `failure_reason` is filled only for `failed` jobs: `too_many_records`, `checkpoint_unavailable`, `integrity_error` or `attempts_exhausted`.
- The file is deleted at `expires_at` (`completed_at` plus 7 days); the job then shows `expired` and can no longer be downloaded.

```json
{
  "id": "aex_01j9xk3m7q8r2s4t6v8w0y2z4e",
  "status": "completed",
  "filter": {
    "stream": "admin",
    "from": "2026-07-01T00:00:00Z",
    "to": "2026-10-01T00:00:00Z",
    "action": "user.",
    "category": null,
    "actor_type": null,
    "actor_id": null,
    "target_type": null,
    "target_id": null,
    "org_id": null,
    "outcome": null,
    "request_id": null,
    "correlation_id": null,
    "agent_only": false
  },
  "include_ip": false,
  "record_count": 18240,
  "file": {
    "name": "records.ndjson.gz",
    "sha256": "9f2c4b8e1d7a3f6c0b5e8d2a4c7f1e3b6a9d0c2e5f8b1a4d7c0e3f6a9b2c5d8e",
    "size": 2381904
  },
  "manifest_sha256": "3b7e1f9c2d5a8e0b4f6c1a3d7e9b2f5c8a0d4e6b1c3f7a9e2d5b8c0f4a6e1d3b",
  "failure_reason": null,
  "created_at": "2026-10-19T09:00:00Z",
  "started_at": "2026-10-19T09:00:02Z",
  "completed_at": "2026-10-19T09:01:10Z",
  "expires_at": "2026-10-26T09:01:10Z",
  "recorded_before": "2026-10-19T09:00:00Z",
  "requested_by": {"type": "api_key", "id": "key_01j9xk3m7q8r2s4t6v8w0y2z4d"}
}
```

## Errors

Every error is an `application/problem+json` body with a stable `code`.

| HTTP | `code` | When |
|---|---|---|
| 401 | `unauthenticated` | The API key is missing, invalid or revoked. |
| 403 | `insufficient_permissions` | The key lacks `audit-exports:read`. |
| 404 | `not_found` | The job does not exist, belongs to another environment, or the id is malformed. |
| 429 | `rate_limited` | The rate limit was exceeded; honor `Retry-After`. |
| 503 | `service_unavailable` | A dependency is temporarily unavailable; retry later. |

## Example

```bash
curl https://api.eu.keenauth.com/v1/audit-exports/aex_01j9xk3m7q8r2s4t6v8w0y2z4e \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

```bash
keenauth audit-exports get aex_01j9xk3m7q8r2s4t6v8w0y2z4e
```

## Personal data

This endpoint carries personal data: audit events. [Personal data in the KeenAuth APIs](/docs/policies/personal-data) describes what is stored, how long it is kept and how it is deleted. Do not send special categories of personal data (health, biometric data, religion, political opinions, sexual orientation) in any field.
