# Query Audit Logs The audit log is an immutable, append-only record of every significant action on the AgentIdP platform. This guide covers how to query it, what filters are available, and how retention works. Requires: `Authorization: Bearer ` with `audit:read` scope. --- ## What gets logged Every action below is automatically recorded. You cannot create, modify, or delete audit events — the log is read-only via the API. | Action | Triggered by | |--------|-------------| | `agent.created` | Successful `POST /agents` | | `agent.updated` | Successful `PATCH /agents/{agentId}` | | `agent.decommissioned` | Successful `DELETE /agents/{agentId}` | | `agent.suspended` | Status changed to `suspended` | | `agent.reactivated` | Status changed from `suspended` to `active` | | `token.issued` | Successful `POST /token` | | `token.revoked` | Successful `POST /token/revoke` | | `token.introspected` | Successful `POST /token/introspect` | | `credential.generated` | Successful `POST /agents/{agentId}/credentials` | | `credential.rotated` | Successful `POST /agents/{agentId}/credentials/{credentialId}/rotate` | | `credential.revoked` | Successful `DELETE /agents/{agentId}/credentials/{credentialId}` | | `auth.failed` | Failed authentication attempt on `POST /token` | > **Audit chain verification**: In addition to querying events, you can verify the cryptographic > integrity of the entire audit hash chain via `GET /api/v1/audit/verify`. This endpoint requires > `audit:read` scope and is rate-limited to 30 requests/min. See the > [API Reference](../api-reference.md#get-auditverify---verify-audit-chain-integrity) for details. --- ## Query the audit log `GET /api/v1/audit` Returns a paginated list of audit events, most recent first. ```bash curl -s "http://localhost:3000/api/v1/audit" \ -H "Authorization: Bearer $TOKEN" | jq . ``` Response: ```json { "data": [ { "eventId": "f1e2d3c4-b5a6-7890-cdef-123456789012", "agentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "action": "token.issued", "outcome": "success", "ipAddress": "127.0.0.1", "userAgent": "curl/7.88.1", "metadata": { "scope": "agents:read agents:write", "expiresAt": "2026-03-28T10:00:00.000Z" }, "timestamp": "2026-03-28T09:00:00.000Z" } ], "total": 47, "page": 1, "limit": 50 } ``` --- ## Audit event structure | Field | Type | Description | |-------|------|-------------| | `eventId` | UUID | Immutable unique ID for this event | | `agentId` | UUID | The agent that triggered the event | | `action` | string | What happened (see table above) | | `outcome` | string | `success` or `failure` | | `ipAddress` | string | Client IP (IPv4 or IPv6) | | `userAgent` | string | HTTP User-Agent from the request | | `metadata` | object | Action-specific details (varies by action) | | `timestamp` | ISO 8601 | When the event occurred | ### `metadata` by action | Action | Metadata fields | |--------|----------------| | `token.issued` | `scope`, `expiresAt` | | `credential.generated` | `credentialId` | | `credential.rotated` | `credentialId` | | `agent.created` | `agentType`, `owner` | | `auth.failed` | `reason`, `clientId` | --- ## Filters All filter parameters are optional and can be combined (logical AND). ### Filter by agent ```bash curl -s "http://localhost:3000/api/v1/audit?agentId=$AGENT_ID" \ -H "Authorization: Bearer $TOKEN" | jq . ``` ### Filter by action ```bash curl -s "http://localhost:3000/api/v1/audit?action=token.issued" \ -H "Authorization: Bearer $TOKEN" | jq . ``` ### Filter by outcome ```bash # Failed authentication attempts only curl -s "http://localhost:3000/api/v1/audit?outcome=failure" \ -H "Authorization: Bearer $TOKEN" | jq . ``` ### Filter by date range ```bash curl -s "http://localhost:3000/api/v1/audit?fromDate=2026-03-01T00:00:00.000Z&toDate=2026-03-28T23:59:59.999Z" \ -H "Authorization: Bearer $TOKEN" | jq . ``` ### Combine filters ```bash # All failed token requests for a specific agent today curl -s "http://localhost:3000/api/v1/audit?agentId=$AGENT_ID&action=auth.failed&outcome=failure&fromDate=2026-03-28T00:00:00.000Z" \ -H "Authorization: Bearer $TOKEN" | jq . ``` --- ## Pagination Default page size is 50, maximum is 200. ```bash curl -s "http://localhost:3000/api/v1/audit?page=2&limit=100" \ -H "Authorization: Bearer $TOKEN" | jq . ``` Use `total`, `page`, and `limit` from the response to calculate the number of pages: ``` total_pages = ceil(total / limit) ``` --- ## Get a single event `GET /api/v1/audit/{eventId}` ```bash curl -s "http://localhost:3000/api/v1/audit/$EVENT_ID" \ -H "Authorization: Bearer $TOKEN" | jq . ``` --- ## Retention — 90 days On the free tier, audit events are retained for 90 days. Events older than 90 days are automatically purged. - Querying for dates outside the 90-day window returns an empty result set — not an error - Requesting a specific `eventId` for a purged event returns `404 Not Found` - The `fromDate` filter cannot be set to a date older than 90 days; doing so returns `400 RETENTION_WINDOW_EXCEEDED` To check the earliest available date: ```json { "code": "RETENTION_WINDOW_EXCEEDED", "message": "Free tier audit log retention is 90 days. Requested date is outside the retention window.", "details": { "retentionDays": 90, "earliestAvailable": "2025-12-28T00:00:00.000Z" } } ```