Audit Log Endpoints

Immutable audit trail of every authenticated action performed through Bulwark — logins, agent sessions, credential vending, FGA tuple mutations, vault reads/writes, CIBA decisions, and admin operations.

All endpoints below are under /api/v1/audit/events. Earlier drafts of these docs used /api/v1/audit and /api/v1/audit/{eventId} — those routes do not exist (there is no per-event GET; query with filters instead).


Authentication

| Header | Description | |--------|-------------| | Authorization | Bearer <jwt> — Bulwark JWT (admin role required). | | X-Bulwark-Tenant | Tenant UUID. Optionally set X-Bulwark-App-Id to scope results to a single app. |


Query Events

GET /api/v1/audit/events

Returns audit events for the tenant, most recent first, with optional filters.

Query Parameters

| Param | Description | |-------|-------------| | type | Filter by event type (e.g. login.success, credential_accessed, vault.secret_read). Exact match. | | category | Filter by category. One of auth, agent, admin, credential, authorization, fga, vault. | | from | RFC3339 lower bound on timestamp (inclusive). | | to | RFC3339 upper bound on timestamp (inclusive). | | limit | Page size. Defaults to 100. | | offset | Pagination offset. Defaults to 0. |

Response 200

{
  "events": [
    {
      "id": "01j...",
      "tenant_id": "01j...",
      "app_id": "01j...",
      "timestamp": "2026-05-07T00:00:00Z",
      "type": "credential_accessed",
      "category": "credential",
      "action": "access",
      "result": "success",
      "actor_type": "agent",
      "actor_id": "01j...",
      "actor_agent_id": null,
      "target_type": "service",
      "target_id": "stripe",
      "source_ip": "203.0.113.42",
      "source_user_agent": "bulwark-agent/1.0",
      "source_geo_city": null,
      "source_geo_country": null,
      "details": {
        "service": "stripe",
        "fields": ["api_key"],
        "grant_id": "01j..."
      }
    }
  ],
  "count": 1,
  "offset": 0,
  "limit": 100
}

offset and limit are echoed back when pagination params or filters are used; they're omitted in the simple-query path (no from/to/category/offset).


Export CSV

GET /api/v1/audit/events.csv

Streams the matching events as a CSV file (Content-Disposition: attachment). Useful for ingesting into SIEM / SOC 2 evidence collection.

Query Parameters

Accepts the same filters as the JSON query (type, category, from, to, limit). The limit is capped at 10,000 rows for the CSV path to keep memory bounded; for larger exports, paginate by from/to windows.

Response 200

CSV with the following columns:

id, timestamp, type, category, action, result,
actor_type, actor_id, target_type, target_id,
source_ip, source_user_agent

details is intentionally NOT included in the CSV export — its JSONB shape varies by event type and would expand the column count unpredictably. Use the JSON query if you need it.


Event Schema

Every audit event has the following shape:

| Field | Description | |-------|-------------| | id | UUID primary key. | | tenant_id | The tenant the event belongs to. | | app_id | Originating application, if any. Null for workspace-level events. | | timestamp | When the event happened (UTC). | | type | Specific event identifier (e.g. login.success, credential_accessed, admin.fga.write_tuple). | | category | One of auth, agent, admin, credential, authorization, fga, vault. | | action | Verb describing the operation (e.g. create, access, deny, rotate). | | result | success, failure, or denied. | | actor_type | user, agent, system, or admin. | | actor_id | The actor's ID. For actor_type=user or admin, this is the user UUID. For agent, the agent identity ID. For system, a service identifier (e.g. vault, cleanup_worker). | | actor_agent_id | If a user acted via an agent session, the agent's ID. Otherwise null. | | target_type | The kind of resource the action affected (e.g. service, user, tenant, credential). | | target_id | The specific resource ID. | | source_ip | Originating IP, if known. | | source_user_agent | HTTP user-agent of the request, if known. | | source_geo_city, source_geo_country | GeoIP enrichment, if configured. | | details | Event-type-specific JSONB. Examples: credential vending records {service, fields, grant_id}; CIBA records {action, severity, ttl_seconds}. |


Retention

Events older than the org's audit_retention_days setting (default 90, clamped 7-365) are deleted by a daily cleanup worker. Configure retention via the org settings — see Settings for the org-settings shape.

For long-term archival, export to CSV at regular intervals.