Audit log export
The Arbitex audit log records every platform event — chat completions, policy decisions, DLP triggers, authentication events, and administrative changes. This guide covers how to query the audit log via the search API, export records as a signed package for offline analysis or compliance retention, and verify the HMAC-SHA256 signature on exported data.
All audit log endpoints require an admin role.
Search API
Section titled “Search API”GET /api/admin/audit-logs/
Returns a paginated, filterable list of audit log entries. Results are ordered by created_at descending (newest first).
Query parameters
Section titled “Query parameters”| Parameter | Type | Description |
|---|---|---|
limit | integer (1–500, default 50) | Maximum number of results to return |
offset | integer (default 0) | Number of results to skip for pagination |
action | string | Filter by exact action type (e.g., chat_completion, dlp_block) |
user_id | string (UUID) | Filter by user UUID |
model_id | string | Filter by model identifier (e.g., claude-sonnet-4-6) |
provider | string | Filter by provider name (e.g., anthropic, openai) |
created_after | datetime (ISO 8601) | Lower bound on created_at (inclusive) |
created_before | datetime (ISO 8601) | Upper bound on created_at (inclusive) |
search | string | Case-insensitive substring search on prompt_text and response_text |
Example: list recent entries
Section titled “Example: list recent entries”curl "https://api.arbitex.ai/api/admin/audit-logs/?limit=20&offset=0" \ -H "Authorization: Bearer <admin_api_key>"Example: filter by action and date range
Section titled “Example: filter by action and date range”curl "https://api.arbitex.ai/api/admin/audit-logs/?action=dlp_block&created_after=2026-03-01T00:00:00Z&created_before=2026-03-11T23:59:59Z&limit=100" \ -H "Authorization: Bearer <admin_api_key>"Example: full-text search
Section titled “Example: full-text search”curl "https://api.arbitex.ai/api/admin/audit-logs/?search=confidential&limit=50" \ -H "Authorization: Bearer <admin_api_key>"The search parameter performs a case-insensitive substring match against both prompt_text and response_text.
Response format
Section titled “Response format”{ "items": [ { "id": "a1b2c3d4-...", "user_id": "3fa85f64-...", "action": "chat_completion", "model_id": "claude-sonnet-4-6", "provider": "anthropic", "prompt_text": "What is the capital of France?", "response_text": "Paris.", "token_count_input": 12, "token_count_output": 4, "cost_estimate": 0.0002, "latency_ms": 340, "created_at": "2026-03-11T08:30:00.000Z" } ], "total": 4721, "limit": 20, "offset": 0}total is the count of all matching records (not just the current page). Use total, limit, and offset to compute pagination:
page_count = (total + limit - 1) // limitnext_offset = offset + limit if offset + limit < total else NonePaginating through all results
Section titled “Paginating through all results”import requests
base_url = "https://api.arbitex.ai/api/admin/audit-logs/"headers = {"Authorization": "Bearer <admin_api_key>"}limit = 500offset = 0all_items = []
while True: resp = requests.get( base_url, headers=headers, params={"limit": limit, "offset": offset, "action": "dlp_block"}, ) resp.raise_for_status() data = resp.json() all_items.extend(data["items"]) offset += limit if offset >= data["total"]: breakSigned export API
Section titled “Signed export API”POST /api/admin/audit/export
Exports audit log records for a date range as a signed JSON package. The package includes:
- metadata: date range, record count, exporter username, export timestamp, HMAC chain status
- records: the full audit records in chronological order
- signature: HMAC-SHA256 over the serialized records
- verification_instructions: human-readable steps to verify the signature offline
Export request body
Section titled “Export request body”{ "start_date": "2026-03-01", "end_date": "2026-03-11", "action": null, "user_id": null, "model_id": null, "provider": null}| Field | Type | Required | Description |
|---|---|---|---|
start_date | date (YYYY-MM-DD) | Yes | Start of export window (inclusive, UTC midnight) |
end_date | date (YYYY-MM-DD) | Yes | End of export window (inclusive, UTC end-of-day) |
action | string | No | Filter to a specific action type |
user_id | UUID | No | Filter to a specific user |
model_id | string | No | Filter to a specific model |
provider | string | No | Filter to a specific provider |
Constraints:
- Maximum window: 90 days (
MAX_WINDOW_DAYS = 90). Requests exceeding this return422 Unprocessable Entity. AUDIT_HMAC_KEYmust be configured on the Platform. Requests without it return400 Bad Request.
Example: export a 7-day window
Section titled “Example: export a 7-day window”curl -X POST https://api.arbitex.ai/api/admin/audit/export \ -H "Authorization: Bearer <admin_api_key>" \ -H "Content-Type: application/json" \ -d '{ "start_date": "2026-03-04", "end_date": "2026-03-11" }'Export response format
Section titled “Export response format”{ "metadata": { "exported_at": "2026-03-11T09:00:00.000Z", "exported_by": "admin@example.com", "date_range": "2026-03-04 to 2026-03-11", "record_count": 14821, "hmac_chain_status": "intact" }, "records": [ { "id": "a1b2c3d4-...", "user_id": "3fa85f64-...", "action": "chat_completion", "model_id": "claude-sonnet-4-6", "provider": "anthropic", "prompt_text": "...", "response_text": "...", "token_count_input": 312, "token_count_output": 847, "cost_estimate": 0.0024, "latency_ms": 1840, "hmac": "sha256:3f2a1b...", "previous_hmac": "sha256:7c4e9d...", "created_at": "2026-03-04T08:00:00.000Z" } ], "signature": "a3f8e2d1c9b4...", "verification_instructions": "To verify this export: 1) Extract the 'records' array from the export JSON. 2) Serialize it with json.dumps(records, sort_keys=True, default=str). 3) Compute HMAC-SHA256 over the serialized string using your AUDIT_HMAC_KEY. 4) Compare the hex digest with the 'signature' field. They must match exactly."}HMAC chain status
Section titled “HMAC chain status”The hmac_chain_status field in metadata reflects the integrity of the per-record HMAC chain across the exported records:
| Status | Meaning |
|---|---|
intact | All record HMACs are valid and the chain is unbroken |
broken | One or more records have invalid HMACs — possible tampering or data corruption |
disabled | AUDIT_HMAC_KEY is not configured; records do not have HMACs |
Large exports and streaming
Section titled “Large exports and streaming”For exports containing more than 10,000 records, the response is returned as a streaming JSON response with Content-Disposition: attachment; filename=audit-export.json. The response body is a single JSON document written incrementally to keep memory usage bounded.
When processing a large export:
# Save directly to file to avoid buffering the full response in memorycurl -X POST https://api.arbitex.ai/api/admin/audit/export \ -H "Authorization: Bearer <admin_api_key>" \ -H "Content-Type: application/json" \ -d '{"start_date": "2026-01-01", "end_date": "2026-03-31"}' \ --output audit-export-q1-2026.jsonFor very large date ranges (weeks to months), split the export into weekly or monthly windows:
for week in 01 08 15 22; do curl -X POST https://api.arbitex.ai/api/admin/audit/export \ -H "Authorization: Bearer <admin_api_key>" \ -H "Content-Type: application/json" \ -d "{\"start_date\": \"2026-03-$week\", \"end_date\": \"2026-03-$(printf '%02d' $((10#$week+6)))\"}" \ --output "audit-export-2026-03-week-$week.json"doneVerifying the export signature
Section titled “Verifying the export signature”The signature field is an HMAC-SHA256 hex digest computed over the records array serialized with json.dumps(records, sort_keys=True, default=str). Use this to verify that the export has not been tampered with after download.
Verification procedure (Python):
import hashlibimport hmacimport json
def verify_export(export_path: str, audit_hmac_key: str) -> bool: with open(export_path) as f: export = json.load(f)
records = export["records"] claimed_signature = export["signature"]
records_json = json.dumps(records, sort_keys=True, default=str) computed = hmac.new( audit_hmac_key.encode("utf-8"), records_json.encode("utf-8"), hashlib.sha256, ).hexdigest()
match = hmac.compare_digest(computed, claimed_signature) if match: print(f"Signature verified. {len(records)} records intact.") else: print(f"SIGNATURE MISMATCH. Expected: {computed}, got: {claimed_signature}") return matchThe AUDIT_HMAC_KEY is the same value configured on the Platform via the AUDIT_HMAC_KEY environment variable. This key should be stored in your secrets manager and provided to the verification script at runtime — do not embed it in the script itself.
Audit record fields
Section titled “Audit record fields”| Field | Type | Description |
|---|---|---|
id | UUID | Unique record identifier |
user_id | UUID | User who made the request |
action | string | Event type (e.g., chat_completion, dlp_block, login) |
model_id | string | Model identifier (e.g., claude-sonnet-4-6) |
provider | string | Provider name (e.g., anthropic) |
prompt_text | string | Input prompt text (may be [REDACTED] if DLP policy applied) |
response_text | string | Model response text (may be [REDACTED]) |
token_count_input | integer | Input token count |
token_count_output | integer | Output token count |
cost_estimate | float | Estimated cost in USD |
latency_ms | integer | End-to-end request latency in milliseconds |
hmac | string | Per-record HMAC for chain integrity verification |
previous_hmac | string | HMAC of the preceding record in the chain |
created_at | datetime | Record creation timestamp (UTC) |
Retention and compliance
Section titled “Retention and compliance”Audit records are retained indefinitely by default. Org-level retention policies can be configured by administrators via the admin operations panel — see Admin operations guide. For SOC 2 and ISO 27001 compliance programs, a minimum 90-day retention window is recommended; 12 months is typical for comprehensive incident response readiness.
If your compliance framework requires audit log immutability evidence, use the signed export package as a tamper-evident snapshot: export records monthly, verify the signature at export time, and store the export file alongside the signature value in an append-only store (S3 with Object Lock, Azure Blob immutable storage, etc.).
See also
Section titled “See also”- Audit log admin guide — Admin UI for browsing and searching audit records
- Audit log verification — HMAC chain verification (per-record tamper detection)
- SIEM integration guide — Forward audit events to your SIEM in real time
- API key management — API keys appear in audit log
action: api_key_created,api_key_deleted