Skip to content

Security & operations API

This page documents security and operations API endpoints. It covers the public content categories endpoint (read-only, no admin role required), the configuration changelog audit trail, and the shutdown/drain lifecycle API.

Base URL: https://platform.arbitex.ai


The public content categories endpoint returns the active category taxonomy without requiring admin privileges. This is useful for client applications that need to display category labels or build category-aware UIs.

Authentication: Authorization: Bearer <user-jwt> — any authenticated user.

GET /api/content-categories

Returns all enabled content categories visible to the authenticated user’s organization. Unlike the admin endpoint (/api/v1/admin/content-categories), this endpoint:

  • Only returns enabled categories (no enabled filter needed)
  • Omits admin-only fields (keyword_count, is_custom)
  • Does not support create/update/delete operations

Query parameters

Parameter Type Default Description
domain string Filter by domain (e.g., medical, financial, legal)
limit integer 100 Results per page (max 500)
offset integer 0 Pagination offset

Request

Terminal window
curl "https://platform.arbitex.ai/api/content-categories?domain=financial" \
-H "Authorization: Bearer $USER_TOKEN"

Response 200 OK

{
"categories": [
{
"id": "financial/investment-research",
"domain": "financial",
"subcategory": "investment-research",
"label": "Investment Research",
"description": "Equity analysis, market research, investment recommendations"
},
{
"id": "financial/ma-analysis",
"domain": "financial",
"subcategory": "ma-analysis",
"label": "M&A Analysis",
"description": "Deal structuring, due diligence, valuation"
},
{
"id": "financial/trading",
"domain": "financial",
"subcategory": "trading",
"label": "Trading Signals",
"description": "Market timing, trading strategies, price predictions"
},
{
"id": "financial/tax",
"domain": "financial",
"subcategory": "tax",
"label": "Tax Advice",
"description": "Tax planning, filing strategy, cross-border tax"
}
],
"total": 4,
"limit": 100,
"offset": 0
}

Response fields

Field Type Description
categories array List of category objects
categories[].id string Category identifier in domain/subcategory format
categories[].domain string Top-level classification domain
categories[].subcategory string Subcategory slug
categories[].label string Human-readable display name
categories[].description string Description of the category scope
total integer Total matching categories
limit integer Page size used
offset integer Pagination offset used

Error responses

Status Description
401 Missing or invalid authentication token
403 Content categories feature is not enabled for this organization

For full category management (create, update, delete, statistics), see the Platform Admin API — Content Categories.


The configuration changelog provides a tamper-evident audit trail of all administrative configuration changes. Every change to policy rules, DLP pipeline settings, content categories, feature flags, and system configuration is recorded with the actor, timestamp, and a structured diff of the change.

Authentication: Authorization: Bearer <platform-admin-jwt>

Field Type Description
id string Changelog entry UUID
timestamp datetime ISO 8601 timestamp of the change
actor object User who made the change
actor.user_id string User UUID
actor.email string User email address
actor.role string Role at time of change (platform_admin, org_admin)
actor.ip_address string Source IP address
resource_type string Type of resource changed (see table below)
resource_id string Identifier of the changed resource
action string created, updated, or deleted
field_changes array List of field-level changes (for updated actions)
field_changes[].field string Field name that changed
field_changes[].old_value any Previous value
field_changes[].new_value any New value
snapshot_before object Full resource state before the change (for updated and deleted)
snapshot_after object Full resource state after the change (for created and updated)
hmac string HMAC-SHA256 of the entry for tamper detection
Resource Type Description
policy_rule Policy engine rules
policy_pack Policy packs
policy_chain Policy chains
dlp_rule DLP pipeline rules
dlp_pattern Custom DLP patterns
content_category Content category definitions
content_category_keyword Category keyword changes
feature_flag Organization feature flags
system_config System configuration keys
model_route Model routing configuration
webhook Webhook definitions
siem_connector SIEM connector configuration
kill_switch Kill switch activation/deactivation
GET /api/v1/admin/config/changelog

Returns configuration change history in reverse chronological order (newest first).

Query parameters

Parameter Type Default Description
resource_type string Filter by resource type (e.g., policy_rule, kill_switch)
resource_id string Filter by specific resource identifier
actor_id string Filter by the user who made the change
action string Filter by action: created, updated, deleted
from datetime 30 days ago Start of time range (ISO 8601)
to datetime now End of time range (ISO 8601)
limit integer 50 Results per page (max 200)
cursor string Cursor for pagination (from next_cursor in response)

Request

Terminal window
curl "https://platform.arbitex.ai/api/v1/admin/config/changelog?resource_type=policy_rule&limit=10" \
-H "Authorization: Bearer $ADMIN_TOKEN"

Response 200 OK

{
"entries": [
{
"id": "cl_01HZ_A1B2C3",
"timestamp": "2026-03-14T14:22:05Z",
"actor": {
"user_id": "usr_01HZ_ADMIN1",
"email": "[email protected]",
"role": "platform_admin",
"ip_address": "10.0.1.50"
},
"resource_type": "policy_rule",
"resource_id": "rule_01HZ_MNPI_BLOCK",
"action": "updated",
"field_changes": [
{
"field": "action",
"old_value": "flag",
"new_value": "block"
},
{
"field": "alert.severity",
"old_value": "medium",
"new_value": "critical"
}
],
"snapshot_before": {
"name": "Investment research MNPI detection",
"action": "flag",
"alert": { "severity": "medium", "channels": ["compliance-team"] },
"enabled": true
},
"snapshot_after": {
"name": "Investment research MNPI detection",
"action": "block",
"alert": { "severity": "critical", "channels": ["compliance-team", "legal-team"] },
"enabled": true
},
"hmac": "sha256:a4f8e2c1d..."
},
{
"id": "cl_01HZ_D4E5F6",
"timestamp": "2026-03-14T09:15:30Z",
"actor": {
"user_id": "usr_01HZ_ADMIN2",
"email": "[email protected]",
"role": "org_admin",
"ip_address": "10.0.2.80"
},
"resource_type": "policy_rule",
"resource_id": "rule_01HZ_MEDICAL_RESTRICT",
"action": "created",
"field_changes": [],
"snapshot_before": null,
"snapshot_after": {
"name": "Medical content — non-clinical block",
"action": "block",
"conditions": [
{ "field": "content.category_domain", "operator": "equals", "value": "medical" },
{ "field": "user.groups", "operator": "not_contains", "value": "clinical-staff" }
],
"enabled": true
},
"hmac": "sha256:b7c3d4e5f..."
}
],
"total": 847,
"next_cursor": "cl_01HZ_G7H8I9",
"has_more": true
}

Response fields

Field Type Description
entries array List of changelog entry objects
total integer Total entries matching the query
next_cursor string or null Cursor for the next page
has_more boolean Whether more results exist

Error responses

Status Description
400 Invalid query parameters (bad date format, unknown resource_type)
401 Missing or invalid authentication token
403 Caller does not have platform admin role

Example: Audit policy changes by a specific admin

Section titled “Example: Audit policy changes by a specific admin”
Terminal window
# All changes by a specific admin in the last 7 days
curl "https://platform.arbitex.ai/api/v1/admin/config/changelog?\
actor_id=usr_01HZ_ADMIN1&\
from=2026-03-07T00:00:00Z&\
limit=50" \
-H "Authorization: Bearer $ADMIN_TOKEN"
Terminal window
# All kill switch activations and deactivations
curl "https://platform.arbitex.ai/api/v1/admin/config/changelog?\
resource_type=kill_switch&\
from=2026-01-01T00:00:00Z" \
-H "Authorization: Bearer $ADMIN_TOKEN"
Terminal window
# Policy rule changes where action was downgraded
# Filter client-side for field_changes where field=action and new_value is less restrictive
curl "https://platform.arbitex.ai/api/v1/admin/config/changelog?\
resource_type=policy_rule&\
action=updated&\
limit=200" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
| jq '.entries[] | select(.field_changes[] | .field == "action" and .old_value == "block" and (.new_value == "flag" or .new_value == "allow"))'

For using the changelog in security investigations, see the Security Operations — Policy Tampering Runbook.


The shutdown/drain API provides graceful shutdown capabilities for the Arbitex platform. A drain operation stops accepting new requests while allowing in-flight requests to complete, enabling zero-downtime maintenance and emergency shutdowns.

Authentication: Authorization: Bearer <platform-admin-jwt>

State Description
running Normal operation — accepting and processing requests
draining Not accepting new requests; in-flight requests completing
drained All in-flight requests completed; ready for shutdown
shutdown Process is terminating
running ──→ draining ──→ drained ──→ shutdown
↑ │
└────────────┘ (cancel drain)
POST /api/v1/admin/shutdown/drain

Begins a graceful drain sequence. The platform immediately stops accepting new AI requests (returns 503 Service Unavailable to new callers) and waits for in-flight requests to complete.

Request body

Field Type Required Default Description
reason string Yes Reason for the drain (recorded in audit log)
timeout_seconds integer No 300 Maximum time to wait for in-flight requests before force-terminating (30–3600)
scope string No platform Drain scope: platform (all services) or api (API gateway only)
notify_webhook boolean No true Send webhook notification when drain completes

Request

Terminal window
curl -X POST "https://platform.arbitex.ai/api/v1/admin/shutdown/drain" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reason": "Scheduled maintenance window — 2026-03-14 22:00 UTC",
"timeout_seconds": 600,
"scope": "platform",
"notify_webhook": true
}'

Response 202 Accepted

{
"drain_id": "drain_01HZ_M1N2O3",
"state": "draining",
"started_at": "2026-03-14T22:00:05Z",
"timeout_seconds": 600,
"timeout_at": "2026-03-14T22:10:05Z",
"scope": "platform",
"reason": "Scheduled maintenance window — 2026-03-14 22:00 UTC",
"initiated_by": {
"user_id": "usr_01HZ_ADMIN1",
"email": "[email protected]"
},
"in_flight": {
"total": 23,
"chat_completions": 18,
"admin_operations": 5
}
}

Response fields

Field Type Description
drain_id string Unique drain operation identifier
state string Current drain state
started_at datetime When the drain began
timeout_seconds integer Configured timeout
timeout_at datetime When force-termination will occur if drain is not complete
scope string Drain scope
reason string Operator-provided reason
initiated_by object Admin who initiated the drain
in_flight.total integer Total in-flight requests at drain start
in_flight.chat_completions integer In-flight chat completion requests
in_flight.admin_operations integer In-flight admin API operations

Error responses

Status Description
400 Invalid request body (missing reason, timeout out of range)
403 Caller does not have platform admin role
409 A drain operation is already in progress
GET /api/v1/admin/shutdown/status

Returns the current shutdown/drain state of the platform. This endpoint remains available even during a drain (it is exempt from the request rejection).

Request

Terminal window
curl "https://platform.arbitex.ai/api/v1/admin/shutdown/status" \
-H "Authorization: Bearer $ADMIN_TOKEN"

Response 200 OK — when running normally

{
"state": "running",
"drain_id": null,
"in_flight": {
"total": 142,
"chat_completions": 128,
"admin_operations": 14
},
"uptime_seconds": 864000
}

Response 200 OK — during active drain

{
"state": "draining",
"drain_id": "drain_01HZ_M1N2O3",
"started_at": "2026-03-14T22:00:05Z",
"timeout_at": "2026-03-14T22:10:05Z",
"reason": "Scheduled maintenance window — 2026-03-14 22:00 UTC",
"initiated_by": {
"user_id": "usr_01HZ_ADMIN1",
"email": "[email protected]"
},
"in_flight": {
"total": 3,
"chat_completions": 2,
"admin_operations": 1
},
"elapsed_seconds": 45,
"uptime_seconds": 864045
}

Response 200 OK — when drained

{
"state": "drained",
"drain_id": "drain_01HZ_M1N2O3",
"started_at": "2026-03-14T22:00:05Z",
"drained_at": "2026-03-14T22:00:52Z",
"reason": "Scheduled maintenance window — 2026-03-14 22:00 UTC",
"in_flight": {
"total": 0,
"chat_completions": 0,
"admin_operations": 0
},
"elapsed_seconds": 47,
"uptime_seconds": 864052
}

Response fields

Field Type Description
state string Current state: running, draining, drained, shutdown
drain_id string or null Active drain operation ID (null when running)
started_at datetime When the active drain began (present when draining/drained)
drained_at datetime When all in-flight requests completed (present when drained)
timeout_at datetime Force-termination deadline (present when draining)
reason string Drain reason (present when draining/drained)
initiated_by object Admin who started the drain (present when draining/drained)
in_flight object Current in-flight request counts
elapsed_seconds integer Seconds since drain started (present when draining/drained)
uptime_seconds integer Platform uptime in seconds
DELETE /api/v1/admin/shutdown/drain

Cancels an in-progress drain and returns the platform to normal operation. Only valid when state is draining (not yet drained).

Request

Terminal window
curl -X DELETE "https://platform.arbitex.ai/api/v1/admin/shutdown/drain" \
-H "Authorization: Bearer $ADMIN_TOKEN"

Response 200 OK

{
"state": "running",
"cancelled_drain_id": "drain_01HZ_M1N2O3",
"cancelled_at": "2026-03-14T22:01:30Z",
"message": "Drain cancelled. Platform is accepting new requests."
}

Error responses

Status Description
403 Caller does not have platform admin role
409 No drain in progress, or drain has already completed (state is drained)

A typical maintenance window follows this sequence:

Terminal window
# 1. Check current state
curl "https://platform.arbitex.ai/api/v1/admin/shutdown/status" \
-H "Authorization: Bearer $ADMIN_TOKEN"
# → state: "running", in_flight: 142
# 2. Initiate drain
curl -X POST "https://platform.arbitex.ai/api/v1/admin/shutdown/drain" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason": "Kernel update - maintenance window MW-2026-0314", "timeout_seconds": 300}'
# → state: "draining", in_flight: 142
# 3. Poll status until drained
curl "https://platform.arbitex.ai/api/v1/admin/shutdown/status" \
-H "Authorization: Bearer $ADMIN_TOKEN"
# → state: "draining", in_flight: 3 ... wait ...
# → state: "drained", in_flight: 0
# 4. Proceed with maintenance (restart, upgrade, etc.)
# The platform process can now be safely stopped.
# 5. After restart, verify
curl "https://platform.arbitex.ai/api/v1/admin/shutdown/status" \
-H "Authorization: Bearer $ADMIN_TOKEN"
# → state: "running", uptime_seconds: 12

All drain operations are recorded in the configuration changelog:

Event resource_type action
Drain initiated shutdown_drain created
Drain completed shutdown_drain updated (state → drained)
Drain cancelled shutdown_drain deleted
Force-termination (timeout) shutdown_drain updated (state → shutdown, force: true)

Use the Configuration Changelog API to query drain history.


Method Path Auth Description
GET /api/content-categories User JWT List active content categories
GET /api/v1/admin/config/changelog Admin JWT List configuration change history
POST /api/v1/admin/shutdown/drain Admin JWT Initiate graceful drain
GET /api/v1/admin/shutdown/status Admin JWT Check shutdown/drain state
DELETE /api/v1/admin/shutdown/drain Admin JWT Cancel an in-progress drain