Skip to main content

Audit Service — API Contracts

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · API Path Conventions

Base path: /api/v1/audit Auth: Bearer JWT (Keycloak RS256). All endpoints require authentication. Tenant isolation: Tenant Admins see only entries where tenant_id = their tenant. Super Admins see all.


1. Audit Entries

GET /api/v1/audit/entries

Query audit entries with filters and pagination.

Auth scopeTENANT_ADMIN or SUPER_ADMIN
Rate limit60 req/min per user

Query Parameters

ParamTypeRequiredDescription
tenantIdUUIDNoSuper Admin only; Tenant Admin's tenant auto-applied
actorIdUUIDNoFilter by actor
eventTypestringNoe.g. USER_SUSPENDED
resourceTypestringNoe.g. USER, PATIENT
resourceIdstringNoFilter by resource ID
outcomestringNoSUCCESS | FAILURE | PARTIAL
dateFromISO8601NoStart of range
dateToISO8601NoEnd of range; max 90 days from dateFrom
limitintegerNoDefault 100; max 1000
offsetintegerNoDefault 0

Response 200

{
"data": [
{
"id": "aud_01HXYZ",
"tenantId": "ten_def456",
"eventType": "USER_SUSPENDED",
"actorId": "usr_admin001",
"actorType": "USER",
"resourceType": "USER",
"resourceId": "usr_abc123",
"action": "UPDATE",
"outcome": "SUCCESS",
"sourceService": "identity-service",
"sourceEventId": "evt_iam_sus_001",
"nodeId": null,
"metadata": { "reason": "Policy violation", "previousStatus": "active" },
"chainHash": "a3f1...e9d7",
"occurredAt": "2026-02-26T11:00:00Z",
"recordedAt": "2026-02-26T11:00:03Z"
}
],
"total": 1284,
"limit": 100,
"offset": 0
}

Error Codes

CodeHTTPCondition
AUD_CROSS_TENANT403Tenant Admin accessing foreign tenant
AUD_DATE_RANGE_TOO_WIDE400Range > 90 days; use export instead

GET /api/v1/audit/entries/:id

Get a single audit entry by ID.

Auth scopeTENANT_ADMIN or SUPER_ADMIN

Path params: id — AuditEntryId (ULID aud_...)

Response 200 — Single AuditEntry object (same schema as list item above).

Error Codes

CodeHTTPCondition
AUD_ENTRY_NOT_FOUND404Entry not found
AUD_CROSS_TENANT403Entry belongs to another tenant

2. Accounting of Disclosures

GET /api/v1/audit/disclosures

Returns all events where a patient's clinical data was accessed (HIPAA accounting-of-disclosures).

Auth scopeTENANT_ADMIN or SUPER_ADMIN

Query Parameters

ParamTypeRequiredDescription
patientIdUUIDYesPatient's resource ID
dateFromISO8601NoStart date
dateToISO8601NoEnd date
limitintegerNoDefault 100
offsetintegerNoDefault 0

Response 200

{
"patientId": "pat_xyz789",
"data": [
{
"id": "aud_dis_001",
"eventType": "PATIENT_RECORD_READ",
"actorId": "usr_abc123",
"actorType": "USER",
"resourceType": "PATIENT_RECORD",
"resourceId": "pat_xyz789",
"action": "READ",
"outcome": "SUCCESS",
"sourceService": "patient-chart-service",
"metadata": { "purpose": "Clinical care", "nodeId": "node_dept_emergency" },
"occurredAt": "2026-02-26T10:30:00Z"
}
],
"total": 42,
"limit": 100,
"offset": 0
}

3. Exports

POST /api/v1/audit/exports

Request an asynchronous export. The export is queued and processed in the background.

Auth scopeSUPER_ADMIN

Request Body

{
"filters": {
"tenantId": "ten_def456",
"dateFrom": "2026-01-01T00:00:00Z",
"dateTo": "2026-02-01T00:00:00Z"
},
"format": "ndjson"
}

Response 202

{
"exportId": "exp_01HXYZ",
"status": "queued",
"createdAt": "2026-02-26T12:00:00Z"
}

The export request is itself audited with eventType: BULK_EXPORT (FR-AUD-EXP-002).


GET /api/v1/audit/exports/:id

Check export status and retrieve download URL when complete.

Auth scopeSUPER_ADMIN

Response 200 (queued or processing)

{
"exportId": "exp_01HXYZ",
"status": "processing",
"createdAt": "2026-02-26T12:00:00Z",
"completedAt": null,
"fileUrl": null,
"recordCount": null
}

Response 200 (completed)

{
"exportId": "exp_01HXYZ",
"status": "completed",
"createdAt": "2026-02-26T12:00:00Z",
"completedAt": "2026-02-26T12:02:34Z",
"fileUrl": "https://exports.ghasi-ehr.com/exp_01HXYZ.ndjson?token=...",
"recordCount": 15432
}

Error Codes

CodeHTTPCondition
AUD_EXPORT_NOT_FOUND404Export job not found

4. Error Code Registry

CodeHTTPDescription
AUD_ENTRY_NOT_FOUND404Audit entry not found
AUD_EXPORT_NOT_FOUND404Export job not found
AUD_CROSS_TENANT403Tenant Admin accessing foreign tenant data
AUD_DATE_RANGE_TOO_WIDE400Query range > 90 days — use export endpoint

All error responses follow the platform envelope:

{
"error": { "code": "AUD_CROSS_TENANT", "message": "..." },
"correlationId": "req_xxx",
"timestamp": "2026-04-18T..."
}

5. FHIR Mapping

Platform endpointFHIR equivalentNotes
GET /api/v1/audit/entriesGET /fhir/AuditEventRead-only projection via interop-service
GET /api/v1/audit/disclosuresGET /fhir/AuditEvent?type=patient-record-readFiltered by patient