Skip to content

Audit Log Management

Arbitex Gateway records every request, policy decision, DLP finding, authentication event, and administrative action in a tamper-evident audit log. This guide covers how to view and filter logs, export records for compliance retention, verify the HMAC integrity chain, and connect your SIEM for real-time event streaming.

All audit log endpoints require the Org Admin role.


Every audit log entry captures:

FieldDescription
request_idUnique identifier for this log entry
timestampISO 8601 UTC timestamp
actionEvent type (see Action types)
user_idUUID of the user who triggered the event
modelModel identifier (e.g., claude-sonnet-4-20250514)
providerProvider name (e.g., anthropic)
outcomePolicy engine decision: ALLOW, BLOCK, REDACT, REQUIRE_APPROVAL
dlp_findingsArray of DLP detections (type, tier, confidence, location)
policy_rules_matchedNames of policy rules that matched
credint_hitWhether a credential matched the breach corpus
routing_modeHow the request was routed (Single, Fallback, Balanced)
prompt_tokensInput token count
completion_tokensOutput token count
latency_msEnd-to-end gateway latency
hmacHMAC-SHA256 signature of this entry
previous_hmacSignature of the preceding entry (chain link)

The hmac and previous_hmac fields form an unbroken chain. Any tampering, deletion, or reordering of entries is detectable by walking the chain.

ActionTrigger
chat_completionNormal model request
dlp_blockRequest blocked by DLP finding
dlp_redactRequest content was redacted
policy_blockRequest blocked by policy rule
policy_approval_requestedRequest held for human review
policy_approval_approvedHuman reviewer approved a held request
policy_approval_deniedHuman reviewer denied a held request
auth_successSuccessful API key authentication
auth_failureFailed authentication attempt
admin_loginAdmin portal sign-in
key_createdAPI key created
key_rotatedAPI key rotated
key_deletedAPI key deleted
rule_createdDLP or policy rule created
rule_updatedDLP or policy rule updated
rule_deletedDLP or policy rule deleted
siem_config_createdSIEM connector configured
provider_createdProvider credential added

GET /api/admin/audit-logs/
Authorization: Bearer arb_live_your-api-key-here

All filter parameters are optional and ANDed together:

ParameterTypeDescription
limitinteger (1–500, default 50)Results per page
offsetinteger (default 0)Pagination offset
actionstringExact action type (e.g., dlp_block)
user_idstring (UUID)Filter by user
model_idstringFilter by model (e.g., claude-sonnet-4-6)
providerstringFilter by provider (e.g., anthropic)
created_afterISO 8601Lower bound on created_at (inclusive)
created_beforeISO 8601Upper bound on created_at (inclusive)
searchstringSubstring search on prompt and response text
outcomestringFilter by policy outcome (ALLOW, BLOCK, REDACT)
Terminal window
curl "https://gateway.arbitex.ai/api/admin/audit-logs/?limit=20" \
-H "Authorization: Bearer $ARBITEX_API_KEY"
{
"entries": [
{
"request_id": "req_01HZ8X9K2P3QR4ST5UV6WX7YZ",
"timestamp": "2026-03-12T14:32:01.847Z",
"action": "chat_completion",
"user_id": "usr_alice_johnson",
"model": "claude-sonnet-4-20250514",
"provider": "anthropic",
"outcome": "ALLOW",
"dlp_findings": [],
"policy_rules_matched": [],
"credint_hit": false,
"routing_mode": "Single",
"prompt_tokens": 28,
"completion_tokens": 42,
"latency_ms": 387
}
],
"total": 14823,
"limit": 20,
"offset": 0
}

Filter by blocked requests in a date range

Section titled “Filter by blocked requests in a date range”
Terminal window
curl "https://gateway.arbitex.ai/api/admin/audit-logs/?outcome=BLOCK&created_after=2026-03-01T00:00:00Z&created_before=2026-03-11T23:59:59Z&limit=100" \
-H "Authorization: Bearer $ARBITEX_API_KEY"
Terminal window
curl "https://gateway.arbitex.ai/api/admin/audit-logs/?action=dlp_block&user_id=usr_alice_johnson&limit=50" \
-H "Authorization: Bearer $ARBITEX_API_KEY"

Use the X-Arbitex-Request-Id response header from any gateway call to find the exact audit entry:

Terminal window
REQUEST_ID="req_01HZ8X9K2P3QR4ST5UV6WX7YZ"
curl "https://gateway.arbitex.ai/api/admin/audit-logs/?request_id=$REQUEST_ID" \
-H "Authorization: Bearer $ARBITEX_API_KEY"

Use the export endpoint to download a signed audit log archive for compliance retention, offline analysis, or handoff to regulators:

Terminal window
curl -X POST "https://gateway.arbitex.ai/api/admin/audit-logs/export" \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"created_after": "2026-03-01T00:00:00Z",
"created_before": "2026-03-11T23:59:59Z",
"format": "jsonl"
}'
{
"export_id": "exp_01HZ...",
"status": "processing",
"record_count": null,
"download_url": null,
"expires_at": null
}

Export jobs are asynchronous. Poll for completion:

Terminal window
EXPORT_ID="exp_01HZ..."
curl "https://gateway.arbitex.ai/api/admin/audit-logs/export/$EXPORT_ID" \
-H "Authorization: Bearer $ARBITEX_API_KEY"
{
"export_id": "exp_01HZ...",
"status": "complete",
"record_count": 4823,
"format": "jsonl",
"download_url": "https://exports.arbitex.ai/signed/exp_01HZ....jsonl?token=...",
"signature": "sha256=a3f2c1...",
"expires_at": "2026-03-14T14:00:00Z"
}

The download_url is a pre-signed URL valid for 48 hours. The signature is an HMAC-SHA256 over the export file contents — verify it before ingesting the data.

For very large exports (millions of entries), use streaming export with chunked transfer:

Terminal window
curl -X POST "https://gateway.arbitex.ai/api/admin/audit-logs/export/stream" \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
--no-buffer \
-d '{
"created_after": "2026-01-01T00:00:00Z",
"created_before": "2026-03-31T23:59:59Z",
"format": "jsonl"
}' \
> audit-q1-2026.jsonl

Streaming exports write one JSON object per line as records are read from the database. No intermediate storage is required on the server side.

FormatDescriptionBest for
jsonlOne JSON object per lineLog pipelines, SIEM ingestion, programmatic processing
csvComma-separated, headers on first rowSpreadsheet analysis, reporting
ndjsonIdentical to jsonlCompatibility alias

Every audit entry contains an hmac field (HMAC-SHA256 over the entry’s data) and a previous_hmac field (the hmac of the preceding entry). This forms a linked chain — deleting, modifying, or reordering any entry breaks the chain.

Trigger a full chain verification on demand:

Terminal window
curl -X POST "https://gateway.arbitex.ai/api/admin/audit-logs/verify" \
-H "Authorization: Bearer $ARBITEX_API_KEY"
{
"valid": true,
"entries_checked": 14823,
"errors": []
}

If tampering is detected:

{
"valid": false,
"entries_checked": 14823,
"errors": [
{
"entry_id": "req_01HZ...",
"position": 4201,
"error": "HMAC mismatch: computed a3f2c1... expected b7e9d4..."
}
]
}

The position field identifies which entry in the chain is broken. Check errors for the exact entry IDs and error descriptions.

To verify the integrity of an export file before ingesting it:

import hashlib
import hmac
import json
HMAC_KEY = b"your-audit-hmac-key"
def verify_export(filepath: str) -> bool:
with open(filepath) as f:
entries = [json.loads(line) for line in f]
previous_hmac = None
for i, entry in enumerate(entries):
# Reconstruct the HMAC (exclude hmac and previous_hmac fields)
data = {k: v for k, v in entry.items() if k not in ("hmac", "previous_hmac")}
if previous_hmac is not None:
data["previous_hmac"] = previous_hmac
expected = hmac.new(
HMAC_KEY,
json.dumps(data, sort_keys=True).encode(),
hashlib.sha256,
).hexdigest()
if entry["hmac"] != expected:
print(f"Chain broken at entry {i}: {entry['request_id']}")
return False
previous_hmac = entry["hmac"]
print(f"Chain verified: {len(entries)} entries intact")
return True
verify_export("audit-q1-2026.jsonl")

The AUDIT_HMAC_KEY is configured by your platform admin in the gateway environment variables. Contact your admin if you need the verification key.


Connect a SIEM to receive audit events in real time via push connector. Events are forwarded as they are generated — no polling required.

Connectorconnector_type value
Splunk HTTP Event Collectorsplunk_hec
Microsoft Sentinel (Log Analytics)sentinel
Elastic (Elasticsearch / ESQL)elastic
Datadog Log Managementdatadog
Sumo Logicsumo_logic
Palo Alto Cortex XSIAMcortex_xsiam
IBM QRadarqradar

1. In Splunk: Create an HTTP Event Collector token under Settings > Data Inputs > HTTP Event Collector. Note the HEC endpoint URL and token.

2. In Arbitex: Create the SIEM connector config:

Terminal window
curl -X POST "https://gateway.arbitex.ai/v1/org/siem-configs" \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"connector_type": "splunk_hec",
"name": "Splunk Production",
"config": {
"hec_url": "https://splunk.example.com:8088/services/collector/event",
"token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"index": "arbitex_audit",
"source": "arbitex_gateway",
"sourcetype": "arbitex:audit"
},
"enabled": true
}'

3. Test the connection:

Terminal window
SIEM_CONFIG_ID="siem_01HZ..."
curl -X POST "https://gateway.arbitex.ai/v1/org/siem-configs/$SIEM_CONFIG_ID/test" \
-H "Authorization: Bearer $ARBITEX_API_KEY"
{
"success": true,
"latency_ms": 42,
"message": "Test event delivered successfully"
}

1. In Azure: Navigate to your Log Analytics workspace. Under Agents management, note the Workspace ID and Primary Key.

2. In Arbitex:

Terminal window
curl -X POST "https://gateway.arbitex.ai/v1/org/siem-configs" \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"connector_type": "sentinel",
"name": "Azure Sentinel Production",
"config": {
"workspace_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"primary_key": "base64encodedprimarykey==",
"log_type": "ArbitexAuditLog"
},
"enabled": true
}'

Arbitex uses the Log Analytics Data Collector API to POST events. Events appear in Sentinel under the ArbitexAuditLog_CL custom log table within 5–10 minutes.

3. Sentinel KQL query to find blocked requests:

ArbitexAuditLog_CL
| where outcome_s == "BLOCK"
| where TimeGenerated > ago(24h)
| project TimeGenerated, user_id_s, action_s, dlp_findings_s, policy_rules_matched_s
| order by TimeGenerated desc

1. In Elasticsearch: Create an API key with index permissions on the target index pattern (arbitex-*):

Terminal window
curl -X POST "https://elastic.example.com:9200/_security/api_key" \
-H "Content-Type: application/json" \
-u elastic:password \
-d '{
"name": "arbitex-ingest",
"role_descriptors": {
"arbitex-writer": {
"cluster": ["monitor"],
"indices": [{"names": ["arbitex-*"], "privileges": ["create_index", "index", "create"]}]
}
}
}'

2. In Arbitex:

Terminal window
curl -X POST "https://gateway.arbitex.ai/v1/org/siem-configs" \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"connector_type": "elastic",
"name": "Elastic Production",
"config": {
"url": "https://elastic.example.com:9200",
"api_key": "base64encodedapikey==",
"index": "arbitex-audit"
},
"enabled": true
}'

Events are indexed as documents in arbitex-audit-{YYYY.MM.DD} using daily index rotation.

Terminal window
curl "https://gateway.arbitex.ai/v1/org/siem-configs" \
-H "Authorization: Bearer $ARBITEX_API_KEY"
{
"configs": [
{
"id": "siem_01HZ...",
"connector_type": "splunk_hec",
"name": "Splunk Production",
"enabled": true,
"last_delivery_at": "2026-03-12T14:35:00Z",
"last_delivery_status": "success",
"error_count_24h": 0
}
]
}

last_delivery_status shows the outcome of the most recent event delivery. error_count_24h shows delivery failures in the past 24 hours. If this is non-zero, check the connector configuration and test the connection.

For platform-level connector health across all organizations, see SIEM Admin API.


SOC 2 — Access and change management evidence

Section titled “SOC 2 — Access and change management evidence”

Export all admin_login, key_created, key_rotated, rule_created, and rule_updated events for a period and retain them for 12 months:

Terminal window
curl -X POST "https://gateway.arbitex.ai/api/admin/audit-logs/export" \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action_types": ["admin_login", "key_created", "key_rotated", "rule_created", "rule_updated"],
"created_after": "2026-01-01T00:00:00Z",
"created_before": "2026-12-31T23:59:59Z",
"format": "jsonl"
}'

HIPAA — Access log for PHI-adjacent requests

Section titled “HIPAA — Access log for PHI-adjacent requests”

Filter for requests that triggered NER findings of type MEDICAL_RECORD or NPI:

Terminal window
curl "https://gateway.arbitex.ai/api/admin/audit-logs/?dlp_finding_type=MEDICAL_RECORD,NPI&limit=500" \
-H "Authorization: Bearer $ARBITEX_API_KEY"

Filter for CREDIT_CARD findings and export quarterly:

Terminal window
curl -X POST "https://gateway.arbitex.ai/api/admin/audit-logs/export" \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dlp_finding_types": ["CREDIT_CARD"],
"created_after": "2026-01-01T00:00:00Z",
"created_before": "2026-03-31T23:59:59Z",
"format": "jsonl"
}'

ResourceLink
Audit Event API (search, filter, pagination)Audit Event API
Audit Log Export (signed packages, streaming)Audit Log Export
SIEM Admin API (connector registry)SIEM Admin API
SIEM Integration GuideSIEM Integration Guide
Data Retention configurationData Retention
Alert configurationAlert Configuration