Files
sentryagent-idp/docs/developers/guides/query-audit-logs.md
SentryAgent.ai Developer 61ea975c79 docs: bedroom developer documentation — complete docs/developers/ set
Adds the full bedroom-developer-docs OpenSpec change implementation:

- docs/developers/README.md — index page
- docs/developers/quick-start.md — bootstrap to working token in 7 steps
- docs/developers/concepts.md — AgentIdP, AGNTCY, lifecycle, OAuth 2.0, free tier
- docs/developers/guides/README.md — guide index
- docs/developers/guides/register-an-agent.md — all fields, validation, common errors
- docs/developers/guides/manage-credentials.md — generate, list, rotate, revoke
- docs/developers/guides/issue-and-revoke-tokens.md — OAuth 2.0 flow, introspect, revoke
- docs/developers/guides/query-audit-logs.md — filters, pagination, 90-day retention
- docs/developers/api-reference.md — all 14 endpoints, all error codes, curl examples

Also commits deferred OpenSpec housekeeping from previous session:
- Archives phase-1-mvp-implementation change to openspec/changes/archive/
- Adds bedroom-developer-docs change artifacts (30/30 tasks complete)
- Syncs 4 delta specs to openspec/specs/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 14:13:03 +00:00

5.0 KiB

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

Query the audit log

GET /api/v1/audit

Returns a paginated list of audit events, most recent first.

curl -s "http://localhost:3000/api/v1/audit" \
  -H "Authorization: Bearer $TOKEN" | jq .

Response:

{
  "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

curl -s "http://localhost:3000/api/v1/audit?agentId=$AGENT_ID" \
  -H "Authorization: Bearer $TOKEN" | jq .

Filter by action

curl -s "http://localhost:3000/api/v1/audit?action=token.issued" \
  -H "Authorization: Bearer $TOKEN" | jq .

Filter by outcome

# Failed authentication attempts only
curl -s "http://localhost:3000/api/v1/audit?outcome=failure" \
  -H "Authorization: Bearer $TOKEN" | jq .

Filter by date range

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

# 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.

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}

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:

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