Skip to content

Outpost Admin API Reference

The Outpost Admin API is a separate FastAPI application that listens on port 8301 (local-only). It provides emergency override capabilities, local status inspection, and operational controls without requiring connectivity to the Arbitex platform.

Air-gap compatible. All admin API calls are local. No data is forwarded to the platform during admin operations.


All endpoints require a Bearer token in the Authorization header:

Authorization: Bearer <admin-api-key>

Token resolution order:

  1. admin_users[].api_key from the loaded policy bundle (HMAC compare — constant time)
  2. OUTPOST_EMERGENCY_ADMIN_KEY environment variable as a fallback
  3. A valid HS256/EdDSA JWT obtained from POST /admin/api/auth/login

Brute-force protection: 5 failed authentication attempts per IP within a 15-minute sliding window triggers HTTP 429. The window resets automatically.

CORS: The admin API only accepts requests from http://localhost:8301 and http://127.0.0.1:8301. All other origins are rejected.

Replay protection: When REPLAY_PROTECTION_ENABLED=true, state-changing endpoints (POST/PUT/DELETE) require an X-Request-ID header. Duplicate X-Request-ID values return 409 Conflict.


Method Path Section
POST /admin/api/auth/login Authentication & Authorization
POST /admin/api/auth/refresh Authentication & Authorization
POST /admin/api/auth/revoke Authentication & Authorization
GET /admin/api/auth/revocation-list Authentication & Authorization
POST /admin/api/auth/revocation-list/clear Authentication & Authorization
GET /admin/api/sessions Authentication & Authorization
DELETE /admin/api/sessions/{session_id} Authentication & Authorization
GET /admin/api/auth-events Authentication & Authorization
GET /admin/api/status Status & Health
GET /admin/api/sync-status Status & Health
GET /admin/api/airgap-config Status & Health
GET /admin/api/health Status & Health
GET /admin/api/health/summary Status & Health
GET /admin/api/health/components Status & Health
GET /admin/api/health/cluster Status & Health
GET /admin/api/connection-health Status & Health
GET /admin/api/connection-health/history Status & Health
GET /admin/api/compat Status & Health
GET /admin/api/rules Policy & DLP
POST /admin/api/rules/{rule_id}/toggle Policy & DLP
GET /admin/api/rulesets Policy & DLP
POST /admin/api/rulesets/{ruleset_id}/toggle Policy & DLP
POST /admin/api/policy/simulate Policy & DLP
GET /admin/api/policy/verify Policy & DLP
POST /admin/api/policy/reload Policy & DLP
GET /admin/api/custom-patterns Policy & DLP
POST /admin/api/custom-patterns Policy & DLP
DELETE /admin/api/custom-patterns/{name} Policy & DLP
GET /admin/api/providers Provider Management
POST /admin/api/providers/{provider}/disable Provider Management
POST /admin/api/providers/{provider}/enable Provider Management
GET /admin/api/credint/status Credential Intelligence
POST /admin/api/credint/reload Credential Intelligence
POST /admin/api/credint/kanon Credential Intelligence
GET /admin/api/usage Budget & Usage
GET /admin/api/budget/status Budget & Usage
GET /admin/api/budget/export.csv Budget & Usage
GET /admin/api/cert/status Certificate Management
POST /admin/api/cert/renew Certificate Management
GET /admin/api/certs/status Certificate Management
POST /admin/api/certs/rotate Certificate Management
GET /admin/api/audit-buffer Audit & SIEM
GET /admin/audit/recent Audit & SIEM
GET /admin/audit/stats Audit & SIEM
GET /admin/audit/search Audit & SIEM
GET /admin/audit/verify Audit & SIEM
GET /admin/api/audit/verify Audit & SIEM
GET /admin/api/audit-sync/checkpoint Audit & SIEM
GET /admin/api/siem/status Audit & SIEM
GET /admin/audit-queue/status Audit & SIEM
POST /admin/audit-queue/flush Audit & SIEM
DELETE /admin/audit-queue/purge Audit & SIEM
GET /admin/api/config/export Configuration
GET /admin/config/export Configuration
POST /admin/api/config/backup Configuration
GET /admin/api/config/backup/list Configuration
POST /admin/api/config/restore Configuration
POST /admin/config/diff Configuration
GET /admin/config/validate Configuration
GET /admin/api/config/reload-status Configuration
POST /admin/api/config/reload Configuration
POST /admin/api/config/apply Configuration
GET /admin/api/config/reload-history Configuration
GET /admin/api/orgs Multi-Org
GET /admin/api/orgs/{org_id}/policy-status Multi-Org
GET /admin/api/cache/stats Multi-Org
POST /admin/api/cache/clear Multi-Org
POST /admin/api/emergency-kill Kill Switch & Drain
GET /admin/api/drain/status Kill Switch & Drain
GET /admin/api/prompt-holds Kill Switch & Drain
POST /admin/api/prompt-holds/{hold_id}/approve Kill Switch & Drain
POST /admin/api/prompt-holds/{hold_id}/deny Kill Switch & Drain
GET /admin/api/prompt-holds/events Kill Switch & Drain
POST /admin/api/prompt-holds/bulk-approve Kill Switch & Drain
POST /admin/api/routing-override Kill Switch & Drain
GET /admin/api/plugins Plugins & Webhooks
POST /admin/api/plugins/{name}/enable Plugins & Webhooks
POST /admin/api/plugins/{name}/disable Plugins & Webhooks
GET /admin/api/webhook-emitter/stats Plugins & Webhooks
GET /admin/api/updates/status Software Updates
POST /admin/api/updates/check Software Updates
POST /admin/api/updates/download Software Updates
GET /admin/api/upgrade/status Software Updates
POST /admin/api/upgrade/run Software Updates
POST /admin/api/upgrade/rollback Software Updates
GET /admin/api/upgrade/history Software Updates
GET /admin/diagnostics Operational Tools
GET /admin/api/metrics-summary Operational Tools
GET /admin/api/metrics/connections Operational Tools
GET /admin/api/circuit-breakers Operational Tools
GET /admin/api/bandwidth Operational Tools
GET /admin/api/benchmarks Operational Tools
GET /admin/api/log-export/status Operational Tools
GET /admin/api/otel/status Operational Tools
GET /admin/api/pushgateway/status Operational Tools
GET /admin/api/ip-allowlist/status Operational Tools
GET /admin/api/body-hash/config Operational Tools
GET /admin/api/replay-protection/stats Operational Tools

This section covers JWT-based authentication, session management, and authentication event retrieval. Static Bearer token auth is described in the Authentication section above.

Issue a signed JWT for admin API access.

POST /admin/api/auth/login
Content-Type: application/json

Request body

{"api_key": "your-admin-api-key"}

Response 200 OK

{
"token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"expires_at": "2026-03-16T12:00:00Z"
}

Use the returned token in the Authorization: Bearer <token> header for subsequent requests.


Refresh a JWT that is within 5 minutes of expiry. Pass the current (non-expired) token as the Authorization header.

Terminal window
curl -s -X POST "http://localhost:8301/admin/api/auth/refresh" \
-H "Authorization: Bearer $CURRENT_JWT"

Response 200 OK

{
"token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"expires_at": "2026-03-16T13:00:00Z"
}

Returns 400 Bad Request if the token is not within 5 minutes of expiry. Returns 401 Unauthorized if the token is already expired.


Revoke a JWT by adding its JTI (JWT ID) to the in-memory revocation list. The revoked token is rejected on all subsequent requests until the revocation list is cleared or the outpost restarts.

Terminal window
curl -s -X POST "http://localhost:8301/admin/api/auth/revoke" \
-H "Authorization: Bearer $JWT_TO_REVOKE"

Response 200 OK


Return the count of revoked JTIs and the timestamp of the last list clear.

Response 200 OK

{
"revoked_count": 3,
"last_cleared": "2026-03-15T08:00:00Z"
}

POST /admin/api/auth/revocation-list/clear

Section titled “POST /admin/api/auth/revocation-list/clear”

Clear the entire revocation list. All previously revoked tokens become valid again.

Response 200 OK


List all currently active admin sessions. Expired sessions are cleaned up before the response is returned.

Terminal window
curl -s http://outpost.internal:8301/admin/api/sessions \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"sessions": [
{
"id": "sess_7a3b9f1c2e4d5a6b",
"username": "ops-admin",
"ip": "10.0.1.42",
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
"created_at": "2026-03-15T11:00:00Z",
"last_activity": "2026-03-15T11:28:45Z"
}
],
"count": 1
}
Field Type Description
id string Session identifier
username string Admin username associated with the session
ip string Source IP address
user_agent string HTTP User-Agent string from the login request
created_at datetime Session creation timestamp
last_activity datetime Most recent request timestamp

Force-logout an active admin session by ID. Writes an auth.session.revoked audit event.

Path parameters

Parameter Type Description
session_id string Session ID from GET /admin/api/sessions
Terminal window
curl -s -X DELETE \
http://outpost.internal:8301/admin/api/sessions/sess_a1b2c3d4 \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"revoked": "sess_7a3b9f1c2e4d5a6b",
"username": "ops-admin"
}

Returns 404 Not Found if the session is not found or already expired.


Return the most recent authentication events (auth.*) from the local audit queue. Limited to the last 100 entries.

Query parameters

Parameter Type Default Description
limit int 20 Maximum events to return (capped at 100)

Response 200 OK

{
"events": [
{
"event": "auth.login.success",
"username": "ops-alice",
"ip": "10.0.1.42",
"timestamp": "2026-03-16T14:07:33Z"
},
{
"event": "auth.session.revoked",
"revoked_session_id": "sess_old123",
"revoked_by": "ops-alice",
"timestamp": "2026-03-16T14:05:00Z"
}
],
"count": 2
}

Returns {"events": [], "count": 0} if the audit queue is not initialized.


These endpoints provide operational visibility into the outpost state, health checks at varying granularity levels, and real-time connection metrics.

Returns the current outpost operational status: policy version, active override count, uptime, and emergency kill state.

GET /admin/api/status
Authorization: Bearer <token>

Response 200 OK

{
"outpost_id": "prod-outpost-01",
"policy_version": "v2026.03.12-4",
"uptime_seconds": 86400,
"active_override_count": 2,
"emergency_kill": false,
"last_override_modified": "2026-03-12T08:00:00Z",
"routing_override": null,
"update_available": true,
"latest_version": "0.19.2"
}
Field Description
active_override_count Sum of all active provider, rule, ruleset, and routing overrides + kill switch
emergency_kill true if the emergency kill switch is active (all requests blocked)
routing_override Provider name if routing is pinned; null if using policy-default routing
update_available true if latest_version differs from the running outpost version

Returns policy sync health: last sync timestamp, ETag, bundle version, heartbeat status, and TLS certificate expiry.

GET /admin/api/sync-status
Authorization: Bearer <token>

Response 200 OK

{
"last_sync_at": "2026-03-12T08:52:00Z",
"etag": "\"abc123\"",
"bundle_version": "v2026.03.12-4",
"latest_version": "0.19.2",
"heartbeat": {
"last_sent_at": "2026-03-12T08:55:00Z",
"consecutive_failures": 0
},
"cert_expiry_days": 82.5
}

cert_expiry_days is null if no certificate path is configured. A value below 30 should trigger a certificate renewal.


Returns the read-only air-gap configuration from OutpostSettings. Useful for verifying that air-gap mode is configured correctly.

GET /admin/api/airgap-config
Authorization: Bearer <token>

Response 200 OK

{
"airgap_enabled": true,
"policy_path": "/etc/arbitex/policy.json",
"model_path": "/etc/arbitex/models/",
"siem_output": "file:///var/log/arbitex/siem.jsonl",
"hmac_enabled": true,
"outpost_id": "prod-outpost-01"
}

hmac_enabled is false only when OUTPOST_INSECURE_SKIP_HMAC=true is set (development only).


Config validation health check — runs all startup validation checks and reports pass/fail/warn/skip per check. Includes degradation mode status and TLS configuration summary.

Terminal window
curl -s http://outpost.internal:8301/admin/api/health \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"overall": "pass",
"passed": 14,
"failed": 0,
"warned": 1,
"skipped": 2,
"checks": [
{
"name": "admin_api_key",
"status": "pass",
"message": "ADMIN_API_KEY is set"
},
{
"name": "tls_cert",
"status": "warn",
"message": "Certificate expires in 28 days"
}
],
"degradation_mode": false,
"degraded_since": null,
"tls_config": {
"min_version": "1.2",
"max_version": "1.3",
"verify_client": true
}
}

overall is "fail" if any check fails, "warn" if any check warns, otherwise "pass".


Condensed health response for fleet monitoring tools and dashboards.

Terminal window
curl -s http://outpost.internal:8301/admin/api/health/summary \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"status": "healthy",
"uptime_seconds": 86412.3,
"version": "0.14.2",
"mode": "single",
"active_orgs": 0,
"inflight_requests": 3,
"cache_hit_rate": 94.7,
"circuit_breaker_open": false
}
Field Description
status healthy / degraded / unhealthy — aggregate of proxy, DLP, and policy sync health
mode single (single-org) or multi (multi-org mode)
active_orgs Count of active orgs (multi-org mode only; 0 in single-org mode)
inflight_requests Current in-flight DLP scan count
cache_hit_rate Policy cache hit rate percentage

Component-level health breakdown with latency and detail fields. Suitable for dashboards and alerting.

Terminal window
curl -s http://outpost.internal:8301/admin/api/health/components \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK (or 503 Service Unavailable when overall is unhealthy)

{
"status": "healthy",
"components": {
"platform_connection": {
"status": "healthy",
"latency_ms": 42.3,
"last_check": "2026-03-16T14:07:10Z"
},
"model_service": {
"status": "healthy",
"last_check": "2026-03-16T14:07:15Z",
"dlp_enabled": true,
"ner_enabled": false
},
"cert": {
"status": "healthy",
"days_remaining": 89
},
"config": {
"status": "healthy",
"reload_count": 3
}
}
}

Component statuses: healthy / degraded / unhealthy. Platform connection is degraded when last sync is > 5 minutes old and unhealthy when > 1 hour old or the circuit breaker is open.


Aggregate health status across all outpost peers in the cluster. Queries peers configured via CLUSTER_PEERS. Returns 207 when any peer is degraded, 503 when any peer is unhealthy.

Terminal window
curl -s http://outpost.internal:8301/admin/api/health/cluster \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK (all healthy)

{
"status": "healthy",
"peers": [
{"url": "self (outpost-prod-01)", "status": "healthy"},
{"url": "http://outpost-prod-02:8301", "status": "healthy"}
],
"total": 2,
"healthy": 2,
"degraded": 0,
"unhealthy": 0
}
HTTP Status Meaning
200 All peers healthy
207 At least one peer degraded
503 At least one peer unhealthy or unreachable

Real-time connection health metrics from the connection health monitor: latency percentiles, packet loss, and jitter.

Terminal window
curl -s http://outpost.internal:8301/admin/api/connection-health \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"status": "healthy",
"enabled": true,
"total_probes": 1440,
"avg_latency_ms": 18.4,
"p95_latency_ms": 42.1,
"p99_latency_ms": 87.3,
"packet_loss_pct": 0.0,
"jitter_ms": 3.2,
"probe_count": 60,
"success_count": 60
}

Returns {"status": "unknown", "enabled": false, ...} when the connection health monitor is not configured.


Return the raw probe history for the connection health monitor. Each entry represents one probe cycle against each AI provider.

Terminal window
curl -s "http://localhost:8301/admin/api/connection-health/history" \
-H "Authorization: Bearer $ARBITEX_ADMIN_KEY"

Response 200 OK

[
{
"probed_at": "2026-03-16T09:00:00Z",
"results": [
{"provider": "openai", "latency_ms": 142, "status": "ok"},
{"provider": "anthropic", "latency_ms": 198, "status": "ok"}
]
},
{
"probed_at": "2026-03-16T08:55:00Z",
"results": [
{"provider": "openai", "latency_ms": 3001, "status": "timeout"},
{"provider": "anthropic", "latency_ms": 201, "status": "ok"}
]
}
]

Run version compatibility checks across all outpost components and return a structured matrix summary.

Terminal window
curl -s http://outpost.internal:8301/admin/api/compat \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"overall": "pass",
"components": [
{
"name": "platform_api",
"detected_version": "1.14.0",
"min_version": "1.12.0",
"recommended_version": "1.14.0",
"status": "pass",
"message": "Platform API version compatible"
},
{
"name": "outpost_agent",
"detected_version": "0.14.2",
"min_version": "0.12.0",
"recommended_version": "0.14.x",
"status": "pass",
"message": "Outpost version compatible"
}
]
}

Check statuses: pass / warn / fail / skip.


These endpoints manage DLP rules, rulesets, custom redaction patterns, policy simulation, policy verification, and air-gap policy reload.

Lists all DLP rules from the loaded policy bundle with their enabled/disabled state.

GET /admin/api/rules
Authorization: Bearer <token>

Response 200 OK

{
"rules": [
{
"id": "pii-ssn",
"name": "SSN Detection",
"tier": 1,
"action": "block",
"enabled": true
},
{
"id": "pii-ccn",
"name": "Credit Card Number",
"tier": 1,
"action": "redact",
"enabled": false
}
]
}

Enables or disables a specific DLP rule. The change takes effect immediately for all subsequent requests.

POST /admin/api/rules/{rule_id}/toggle
Authorization: Bearer <token>
Content-Type: application/json
{
"enabled": false
}

Response 200 OK

{
"rule_id": "pii-ccn",
"enabled": false
}

Lists all DLP compliance rulesets (compliance_bundles in the policy bundle) with their enabled/disabled state.

GET /admin/api/rulesets
Authorization: Bearer <token>

Response 200 OK

{
"rulesets": [
{
"id": "hipaa",
"name": "HIPAA PHI",
"enabled": true
},
{
"id": "pci-dss",
"name": "PCI DSS",
"enabled": false
}
]
}

POST /admin/api/rulesets/{ruleset_id}/toggle

Section titled “POST /admin/api/rulesets/{ruleset_id}/toggle”

Enables or disables an entire compliance ruleset. Disabling a ruleset suppresses all rules within it.

POST /admin/api/rulesets/{ruleset_id}/toggle
Authorization: Bearer <token>
Content-Type: application/json
{
"enabled": false
}

Response 200 OK

{
"ruleset_id": "pci-dss",
"enabled": false
}

Runs a synthetic prompt through the local DLP pipeline and returns a full evaluation trace. Read-only — no request is forwarded to any LLM, no usage is recorded, and the prompt text is not written to the audit log (only its length is logged).

POST /admin/api/policy/simulate
Authorization: Bearer <token>
Content-Type: application/json
{
"prompt": "My SSN is 123-45-6789, please help me...",
"provider": "anthropic",
"model": "claude-sonnet-4-6",
"org_id": "b3e2a1c0-..."
}
Field Required Description
prompt Yes Text to evaluate
provider No Provider to use for rule-provider matching
model No Model ID for model-specific rules
org_id No Defaults to the outpost’s configured org_id

Returns 503 if no policy bundle is loaded.

Response — see Policy Simulator guide for full response schema.


Return the last policy rule verification result from the most recent successful policy sync. Populated automatically after each HMAC-verified policy sync. Returns 404 if no bundle has been synced and verified in the current session.

Response 200 OK

{
"bundle_version": "v2026.03.16-1",
"verified_at": "2026-03-16T14:00:00Z",
"rules_count": 47,
"packs_count": 8,
"hmac_valid": true,
"schema_version": "3",
"warnings": []
}

Response 404 Not Found (no bundle synced yet)

{"detail": "No policy verification result available yet"}

Reload the policy bundle from the local filesystem. Only available when OUTPOST_AIRGAP=true. Reads policy_bundle.json from AIRGAP_POLICY_PATH, validates structure, and atomically replaces the active bundle in memory.

Terminal window
curl -s -X POST http://outpost.internal:8301/admin/api/policy/reload \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"success": true,
"bundle_version": "2026-03-16T12:00:00Z",
"rules_loaded": 47,
"message": "Policy bundle reloaded from /opt/arbitex/policy/policy_bundle.json"
}

Response 400 Bad Request

{
"detail": "Policy reload only available in air-gap mode"
}

Response 422 Unprocessable Entity — bundle validation failed

{
"success": false,
"bundle_version": null,
"rules_loaded": 0,
"message": "Policy bundle must contain a 'rules' array"
}

List all loaded custom redaction patterns. Custom patterns extend the built-in DLP regex tier with operator-defined patterns. Enabled via CUSTOM_PATTERNS_ENABLED=true.

Response 200 OK

{
"patterns": [
{
"name": "employee-id",
"pattern": "EMP-[0-9]{6}",
"replacement": "[EMPLOYEE_ID]",
"enabled": true
}
]
}

Returns {"patterns": []} if the custom pattern registry is not enabled.


Add a new custom redaction pattern.

Request body

{
"name": "employee-id",
"pattern": "EMP-[0-9]{6}",
"replacement": "[EMPLOYEE_ID]",
"enabled": true
}
Field Type Required Default
name string yes
pattern string yes
replacement string no "[REDACTED]"
enabled boolean no true

Response 201 Created

{
"status": "added",
"pattern": {
"name": "employee-id",
"pattern": "EMP-[0-9]{6}",
"replacement": "[EMPLOYEE_ID]",
"enabled": true
}
}

Response 400 Bad Request: Missing name or pattern, or invalid regex.

Response 503 Service Unavailable: Custom pattern registry not enabled.


Delete a custom redaction pattern by name.

Path parameter: name — the exact pattern name as registered.

Response 200 OK

{
"status": "deleted",
"name": "employee-id"
}

Response 404 Not Found: Pattern not found.


Providers can be temporarily disabled for maintenance, incident response, or cost control without modifying the policy bundle. All provider overrides are in-memory and reset on outpost restart.

Lists all providers from the loaded policy bundle along with their current override state.

GET /admin/api/providers
Authorization: Bearer <token>

Response 200 OK

{
"providers": [
{
"name": "anthropic",
"base_url": "https://api.anthropic.com",
"models": ["claude-sonnet-4-6", "claude-haiku-4-5-20251001"],
"disabled": false,
"disabled_until": null,
"disable_reason": ""
},
{
"name": "openai",
"base_url": "https://api.openai.com",
"models": ["gpt-4o", "gpt-4o-mini"],
"disabled": true,
"disabled_until": "2026-03-12T12:00:00Z",
"disable_reason": "Incident response — elevated error rate",
"override": {
"disabled_by": "admin",
"disabled_at": "2026-03-16T08:30:00Z",
"disabled_until": "2026-03-16T10:30:00Z",
"reason": "Maintenance window"
}
}
]
}

disabled_until is null for a permanent disable (no duration specified).


POST /admin/api/providers/{provider}/disable

Section titled “POST /admin/api/providers/{provider}/disable”

Disables a provider, optionally for a fixed duration. All requests routed to this provider will fail with 503 until re-enabled.

POST /admin/api/providers/{provider}/disable
Authorization: Bearer <token>
Content-Type: application/json
{
"duration_hours": 4,
"reason": "Incident response — elevated error rate"
}
Field Type Required Description
duration_hours float No Auto-re-enable after this many hours. Omit for permanent disable
duration_minutes integer No Alternative to duration_hours
reason string No Reason recorded in the audit log

Returns 400 if the provider name is not in the policy bundle.

Response 200 OK

{
"provider": "openai",
"disabled": true,
"disabled_until": "2026-03-16T10:30:00Z"
}

POST /admin/api/providers/{provider}/enable

Section titled “POST /admin/api/providers/{provider}/enable”

Re-enables a previously disabled provider. Clears the disable override immediately.

POST /admin/api/providers/{provider}/enable
Authorization: Bearer <token>

No request body required.

Response 200 OK

{
"provider": "openai",
"enabled": true
}

CredInt uses a bloom filter to detect leaked credentials in prompts. These endpoints manage the filter state and k-anonymity verification.

Returns bloom filter status: whether the filter is loaded, entry count, snapshot date, target false-positive rate, and file size.

GET /admin/api/credint/status
Authorization: Bearer <token>

Response 200 OK (filter loaded)

{
"enabled": true,
"loaded": true,
"entry_count": 847291054,
"loaded_at": "2026-03-15T08:00:00Z",
"file_size_bytes": 1073741824,
"snapshot_date": "2026-03-01",
"fpr_target": 0.001
}

Response 200 OK (filter not configured)

{
"enabled": false,
"loaded": false,
"entry_count": 0,
"loaded_at": null,
"file_size_bytes": 0,
"snapshot_date": "",
"fpr_target": 0.0
}
Field Type Description
entry_count integer Number of entries in the bloom filter
file_size_bytes integer On-disk size of the bloom filter file
snapshot_date string Date of the credential snapshot
fpr_target float Target false-positive rate (e.g., 0.001 = 0.1%)

Reloads the CredInt bloom filter from the path configured in CREDINT_BLOOM_PATH. Hot-swaps the in-memory filter without an outpost restart.

POST /admin/api/credint/reload
Authorization: Bearer <token>

No request body required.

Response 200 OK (success)

{
"success": true,
"message": "Bloom filter reloaded",
"entry_count": 847291054
}

Response 200 OK (not configured)

{
"success": false,
"message": "CredInt scanner not configured"
}

If reload fails (corrupt file, I/O error), the existing in-memory filter remains active (fail-open). Audit-logged as admin_credint_reload.


Toggles k-anonymity verification on the CredInt scanner at runtime without a restart.

When k-anonymity is enabled (default), the outpost checks candidate credentials against the Have I Been Pwned k-anonymity API before surfacing a match. Disabling it suppresses those external checks — useful for air-gapped deployments.

Requires: Content-Type: application/json (returns 415 if missing).

Request body

{"enabled": true}
Field Type Required Description
enabled boolean Yes Enable or disable k-anonymity verification

Response 200 OK

{"credint_kanon_enabled": true, "message": "K-anonymity enabled"}

Response 503: {"detail": "Settings not initialised"}


These endpoints provide visibility into token usage, estimated costs, and budget enforcement status for the current billing period.

Returns the current-period usage summary from the outpost’s local usage tracker.

GET /admin/api/usage
Authorization: Bearer <token>

Response 200 OK (tracking enabled)

{
"period_start": "2026-03-01T00:00:00Z",
"period_end": "2026-03-31T23:59:59Z",
"tokens_input": 1240000,
"tokens_output": 890000,
"total_requests": 3412,
"estimated_cost_usd": 24.80,
"budget_cap_usd": 500.00,
"budget_remaining_usd": 475.20,
"budget_alert_threshold_pct": 80
}

Response 200 OK (tracking disabled)

{
"usage_tracking": "disabled",
"totals": null,
"budget_config": null
}

Current budget enforcement status for the active billing period. Reports spend against configured caps with percentage tracking.

Terminal window
curl -s http://outpost.internal:8301/admin/api/budget/status \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"period": "2026-03-01T00:00:00Z",
"period_type": "monthly",
"dollar_cap": 500.0,
"dollar_spent": 312.847291,
"dollar_percent": 62.57,
"request_cap": 100000,
"request_count": 67432,
"request_percent": 67.43,
"status": "ok",
"warning": false
}
Field Values Description
status ok / warning / exceeded warning when ≥ 80% of either cap; exceeded when ≥ 100%
warning bool true when status is warning
period_type monthly / hourly Billing period type from policy bundle

If usage tracking is disabled, returns {"usage_tracking": "disabled", "status": "ok", "warning": false}.


Export budget usage data as a downloadable CSV file. Returns up to 100,000 rows, newest-first. Writes an audit log event on each export.

Terminal window
curl -s http://outpost.internal:8301/admin/api/budget/export.csv \
-H "Authorization: Bearer $ADMIN_API_KEY" \
-o budget_usage_$(date +%Y%m%d).csv

Responsetext/csv with Content-Disposition: attachment; filename=budget_usage.csv

CSV columns: date, model, provider, org_id, input_tokens, output_tokens, estimated_cost, period.


The outpost operates two certificate contexts: mTLS certificates for the outpost-to-platform mutual TLS connection (/admin/api/cert/*), and TLS serving certificates for the outpost’s own HTTPS listener (/admin/api/certs/*).

Returns mTLS certificate metadata and rotation daemon state.

Terminal window
curl -s "http://localhost:8301/admin/api/cert/status" \
-H "Authorization: Bearer $ARBITEX_ADMIN_KEY"

Response 200 OK

{
"cert_path": "certs/outpost.pem",
"subject": "CN=outpost-prod-us-east.arbitex.ai",
"issuer": "CN=Arbitex Outpost CA",
"not_before": "2026-01-01T00:00:00Z",
"not_after": "2026-06-30T00:00:00Z",
"days_remaining": 106,
"status": "amber",
"last_check_at": "2026-03-15T10:00:00Z",
"last_rotation_at": "2025-12-01T08:30:00Z",
"consecutive_failures": 0,
"total_rotations": 3,
"needs_rotation": false,
"rotation_state": "idle"
}
Field Type Description
status string Traffic-light: green (>30 days), amber (7–30 days), red (<7 days or unreadable)
consecutive_failures integer Consecutive rotation failures
total_rotations integer Lifetime successful rotations

If the cert rotation client is not configured, rotation fields return zero/null.


Triggers an immediate mTLS certificate rotation cycle via the CertRotationClient (calls back to Platform’s cert issuance endpoint). Installs the new certificate without restarting.

Terminal window
curl -s -X POST "http://localhost:8301/admin/api/cert/renew" \
-H "Authorization: Bearer $ARBITEX_ADMIN_KEY"

Response 200 OK (rotated)

{"status": "renewed", "valid_until": "2026-09-30T00:00:00Z"}

Response 200 OK (not needed)

{"success": false, "message": "no_renewal_needed"}

Response 503: {"error": "Cert rotation client not configured"} or control plane unreachable.

Audit-logged as admin_cert_renew.


Returns TLS serving certificate CN, expiry, and auto-rotation configuration.

Response 200 OK

{
"cert_path": "certs/outpost.pem",
"cn": "outpost-prod.example.com",
"expiry": "2026-12-31T00:00:00Z",
"not_after": "2026-12-31T00:00:00Z",
"days_remaining": 290,
"needs_rotation": false,
"threshold_days": 30,
"auto_rotate_enabled": true
}
Field Type Description
needs_rotation boolean True when days_remaining < threshold_days
threshold_days integer From CERT_ROTATION_THRESHOLD_DAYS (default 30)
auto_rotate_enabled boolean From CERT_AUTO_ROTATE setting

Rotates the TLS serving certificate. Accepts a PEM payload or generates a self-signed cert.

Requires: CERT_AUTO_ROTATE=true (returns 403 if disabled).

Request body (optional)

{
"cert_pem": "-----BEGIN CERTIFICATE-----\n...",
"key_pem": "-----BEGIN PRIVATE KEY-----\n..."
}

If no body is provided, generates an RSA-2048 self-signed certificate (365-day validity). If cert_pem and key_pem are supplied, they are validated before writing.

Response 200 OK

{"status": "rotated", "cn": "outpost-prod.example.com", "expiry": "2027-03-16T00:00:00Z"}

Response 400: {"error": "Invalid PEM data: ..."} — malformed cert or key

Response 403: {"error": "Certificate auto-rotation is disabled. Set CERT_AUTO_ROTATE=true."}

Response 500: {"error": "Failed to write cert files: ..."} — filesystem or dependency error

Writes to OUTPOST_CERT_PATH and OUTPOST_KEY_PATH. Audit-logged as admin_cert_rotate.


These endpoints provide local audit visibility through multiple interfaces: the JSONL file-backed buffer, the in-memory ring buffer, HMAC chain integrity verification, SIEM direct sink status, audit queue management, and the persistent sync checkpoint.

Returns the last 200 events from the local JSONL audit buffer on disk. Useful for immediate review without exporting to a SIEM.

GET /admin/api/audit-buffer
Authorization: Bearer <token>

Response 200 OK

{
"events": [
{
"timestamp": "2026-03-12T09:00:01Z",
"action": "proxy_request",
"user_id": "u-xyz",
"provider": "anthropic",
"model": "claude-sonnet-4-6",
"dlp_result": "pass",
"latency_ms": 210
}
],
"total": 47
}

total reflects the number of events in the response (up to 200), not the total events in the file.


Returns DLP scan events from the in-memory ring buffer (50-event capacity) with pagination.

Query parameters

Parameter Type Default Constraints
limit integer 50 max 200
offset integer 0

Response 200 OK

{
"events": [
{
"event_id": "dlp_01HZ9KQBW4J8YQNXT3R6MFD2AE",
"prev_event_id": "dlp_01HZ9KQBW4J8YQNXT3R6MFD29X",
"hmac_signature": "a3f7...",
"timestamp": "2026-03-15T10:23:44Z",
"org_id": "org_abc",
"action_taken": "BLOCK",
"was_blocked": true,
"was_redacted": false,
"scan_duration_ms": 2.34,
"entities_detected": [
{"type": "aws_access_key_id", "confidence": 0.98, "redacted": true}
],
"entity_types_detected": ["CREDIT_CARD"],
"request_body_hash": "sha256:ab12...",
"response_body_hash": "sha256:cd34..."
}
],
"total": 847,
"limit": 50,
"offset": 0
}

Returns aggregated DLP scan statistics since outpost startup.

Response 200 OK

{
"total_scans": 12450,
"total_blocked": 34,
"total_redacted": 127,
"avg_scan_duration_ms": 8.7,
"entity_type_counts": {
"aws_access_key_id": 22,
"credit_card": 89,
"ssn": 41
},
"action_distribution": {
"ALLOW": 12289,
"BLOCK": 34,
"REDACT": 127
},
"uptime_seconds": 86420,
"scans_per_minute": 14.2
}

scans_per_minute is computed over a rolling 5-minute window. entity_type_counts and action_distribution are cumulative since startup.


Searches DLP scan events in the ring buffer with filters. Filters are applied cumulatively (AND).

Query parameters

Parameter Type Default Description
action string Substring filter on action_taken (case-insensitive)
entity_type string Substring filter on detected entity types (case-insensitive)
min_duration_ms float Minimum scan_duration_ms
blocked_only boolean false Filter to action_taken == "BLOCK" only (overrides action)
limit integer 20 max 100
offset integer 0

Response 200 OK

{
"events": [...],
"total": 34,
"limit": 20,
"offset": 0
}

Verifies HMAC chain integrity of the in-memory DLP scan ring buffer. Walks all events, recomputes HMACs, and checks prev_event_id chain linkage.

Response 200 OK (chain valid)

{
"valid": true,
"events_checked": 847,
"first_broken_at": null,
"error": null
}

Response 200 OK (chain not enabled)

{
"valid": true,
"events_checked": 0,
"first_broken_at": null,
"error": "Audit chain not enabled (AUDIT_CHAIN_ENABLED=false)"
}

Response 200 OK (chain broken)

{
"valid": false,
"events_checked": 50,
"first_broken_at": "a1b2c3d4-...",
"error": null
}

first_broken_at is the event_id of the first event with a mismatched HMAC or broken chain link. The first event in the buffer is exempt from prev-chain checks (it may reference an evicted event).


Extended variant with richer response schema. Also verifies the HMAC chain of the ring buffer, but additionally includes first_event_id and last_event_id for cross-referencing against platform audit records.

Response 200 OK (chain valid)

{
"verified": true,
"total_events": 847,
"first_event_id": "dlp_01HZ9KQBW4J8YQNXT3R6MFD100",
"last_event_id": "dlp_01HZ9KQBW4J8YQNXT3R6MFD2AE",
"chain_valid": true,
"broken_at_event": null
}

Response 200 OK (chain broken)

{
"verified": false,
"total_events": 50,
"first_event_id": "a1b2c3d4-...",
"last_event_id": "e5f6a7b8-...",
"chain_valid": false,
"broken_at_event": "c9d0e1f2-..."
}

When AUDIT_CHAIN_ENABLED=false, returns verified: true with a note field explaining the chain is not enabled.


Return the current state of the audit write-ahead log (WAL), persistent sync checkpoint, and live sync worker. Useful for diagnosing audit delivery gaps after network disconnects or outpost restarts.

Response 200 OK

{
"wal": {
"pending_entries": 12,
"oldest_entry_at": "2026-03-16T13:55:00Z",
"disk_usage_bytes": 24576,
"wal_path": "/var/outpost/data/audit.wal"
},
"checkpoint": {
"last_synced_event_id": "dlp_01HZ9KQBW4J8YQNXT3R6MFD29X",
"last_synced_at": "2026-03-16T14:05:00Z",
"total_synced": 835
},
"sync_worker": {
"running": true,
"last_flush_at": "2026-03-16T14:05:00Z",
"flush_interval_seconds": 30,
"consecutive_failures": 0,
"degraded": false
}
}
Field Description
wal.pending_entries Events written to WAL but not yet confirmed as synced to platform
checkpoint.last_synced_event_id Event ID of the last successfully delivered audit event
sync_worker.consecutive_failures Number of consecutive sync failures; triggers degradation mode

Any of wal, checkpoint, or sync_worker may be null if that component is not configured.


SIEM direct sink status: sink type, enablement state, event counters, and last error.

Terminal window
curl -s http://outpost.internal:8301/admin/api/siem/status \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK (SIEM enabled)

{
"enabled": true,
"sink_type": "splunk_hec",
"events_sent": 84320,
"events_failed": 3,
"last_error": "connection timeout after 10s",
"last_flush_at": "2026-03-16T14:07:01Z"
}

Response 200 OK (SIEM disabled)

{
"enabled": false,
"sink_type": null,
"events_sent": 0,
"events_failed": 0,
"last_error": null,
"last_flush_at": null
}
Field Type Description
sink_type string | null "splunk", "splunk_hec", or "http" when enabled; null when disabled
events_sent integer Cumulative count of successfully forwarded events since process start
events_failed integer Cumulative count of events that failed to forward
last_error string | null Most recent forwarding error message, or null if no errors

Return current local audit queue statistics. The outpost writes audit events to a local SQLite queue during platform outages (circuit breaker open / degradation mode).

Terminal window
curl -s http://outpost.internal:8301/admin/audit-queue/status \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"count": 247,
"oldest_queued_at": "2026-03-16T08:14:22Z",
"disk_usage_bytes": 1048576,
"degradation_mode": true
}

Trigger an immediate flush of all queued audit events to the Platform, bypassing the regular sync interval.

Terminal window
curl -s -X POST http://outpost.internal:8301/admin/audit-queue/flush \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"flushed": 247,
"failed": 0,
"duration_ms": 382.1
}

Returns 409 Conflict if the queue is empty.


Permanently discard all events in the local audit queue. Requires the X-Purge-Confirm: yes header to prevent accidental data loss.

Terminal window
curl -s -X DELETE http://outpost.internal:8301/admin/audit-queue/purge \
-H "Authorization: Bearer $ADMIN_API_KEY" \
-H "X-Purge-Confirm: yes"

Response 200 OK

{"purged": 247}

Returns 400 Bad Request if the X-Purge-Confirm: yes header is missing.


These endpoints manage configuration export, backup/restore, diff/validate, hot-reload, and live key apply. Two config export variants are available: a structured JSON diagnostic export and a browser-downloadable backup file.

Diagnostic config export — returns a structured JSON snapshot of the outpost’s effective runtime configuration. All secret and credential fields are replaced with "[REDACTED]". An admin_config_export entry is written to the local audit log.

Terminal window
curl -s http://outpost.internal:8301/admin/api/config/export \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"exported_at": "2026-03-15T12:10:00Z",
"exported_by": "ops-admin",
"runtime": {
"log_level": "info",
"listen_port": 8300,
"admin_port": 8301,
"admin_api_key": "[REDACTED]",
"platform_url": "https://platform.arbitex.ai",
"platform_mtls_cert": "/etc/outpost/certs/client.crt",
"platform_mtls_key": "[REDACTED]"
},
"airgap": {
"airgap_enabled": false,
"policy_path": "/etc/outpost/policy",
"model_path": "/etc/outpost/models"
},
"dlp": {
"tier1_enabled": true,
"tier2_enabled": true,
"tier3_enabled": false,
"ner_enabled": true,
"deberta_enabled": false,
"credint_enabled": true
},
"siem": {
"type": "splunk",
"url": "https://splunk.corp.example.com:8088/services/collector",
"token": "[REDACTED]",
"buffer_capacity": 10000,
"siem_output": true
},
"geoip": {
"city_mmdb_path": "/etc/outpost/geoip/GeoLite2-City.mmdb",
"asn_mmdb_path": "/etc/outpost/geoip/GeoLite2-ASN.mmdb"
},
"oauth": {
"jwks_url": "https://platform.arbitex.ai/.well-known/jwks.json",
"cache_ttl_seconds": 300,
"scope_enforcement": true,
"oauth_jwt_public_key": "[REDACTED]"
},
"policy_bundle": {
"loaded": true,
"version": "2026.03.14-r1",
"etag": "\"a3f9c2b1d4e5\"",
"updated_at": "2026-03-14T06:00:00Z",
"provider_count": 12,
"dlp_rule_count": 34,
"compliance_bundle_count": 4,
"signature_valid": true
},
"budget": {
"daily_limit_usd": 500.00,
"monthly_limit_usd": 12000.00,
"enforcement": "block"
}
}
Section Contents
runtime All top-level config keys; secrets replaced with "[REDACTED]"
airgap airgap_enabled, policy_path, model_path
dlp Tier enablement flags and NER/DeBERTa/CredInt settings
siem Type, URL, buffer capacity, output flag; SIEM token redacted
geoip City and ASN MMDB file paths
oauth JWKS URL, cache TTL, scope enforcement flag; JWT public key redacted
policy_bundle Loaded state, version, etag, updated_at, provider/rule/compliance counts, signature validity
budget Budget limits and enforcement mode from the loaded policy bundle (omitted if bundle not loaded)

Browser-download variant. Returns all non-secret configuration fields as a downloadable JSON file. The following fields are omitted entirely (rather than redacted): admin_api_key, provider_key_encryption_key, siem_direct_token, oauth_jwt_public_key.

Terminal window
curl -s http://outpost.internal:8301/admin/config/export \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response headers

Content-Type: application/json
Content-Disposition: attachment; filename="outpost-config-backup-2026-03-15T12-10-00Z.json"

The response body is the same shape as /admin/api/config/export but with secret fields omitted rather than redacted, and without the exported_by field.


Create a JSON snapshot of the current running configuration. Secret fields are masked as "***". The snapshot is stored in an in-memory ring (last 10 backups) and optionally persisted to disk if BACKUP_DIR is configured.

Response 200 OK

{
"success": true,
"timestamp": "2026-03-16T14:05:00Z",
"fields": 42
}

fields is the count of configuration keys captured in the snapshot.


List available config backups — timestamps and sizes (in-memory ring, up to 10 entries).

Response 200 OK

{
"backups": [
{
"timestamp": "2026-03-16T14:05:00Z",
"size": 2048
},
{
"timestamp": "2026-03-16T12:00:00Z",
"size": 2031
}
],
"count": 2
}

Backups are stored in memory only (ring buffer, last 10). They do not persist across restarts unless BACKUP_DIR is set.


Restore configuration from a backup payload. Secret fields in the payload are ignored and cannot be restored via this endpoint.

Request body

{
"config": {
"log_level": "DEBUG",
"policy_sync_interval": 60,
"dlp_enabled": true
}
}

Response 200 OK

{
"success": true,
"applied": 3,
"skipped": 0,
"skipped_keys": []
}

Response 400 Bad Request: Unknown config keys in payload, or missing config key.

Fields masked as "***" in the payload are automatically skipped. Secret fields (audit_hmac_key, policy_hmac_key, outpost_api_key, etc.) are always skipped. Audit-logged as admin_config_restore.


Compare a proposed configuration against the running settings. Read-only — does not modify any state.

Request body

{
"proposed_config": {
"log_level": "DEBUG",
"policy_sync_interval": 120
}
}

Response 200 OK

{
"changes": [
{ "key": "log_level", "from": "INFO", "to": "DEBUG" },
{ "key": "policy_sync_interval", "from": 60, "to": 120 }
],
"change_count": 2,
"has_breaking_changes": false,
"summary": "2 changes: 2 modified"
}

has_breaking_changes is true if any changed key is in the breaking-change set (e.g., outpost_id, org_id, platform_management_url). All 26 configured settings fields are compared.


Validate a proposed configuration JSON without applying it. Returns validation result, errors, warnings, and the diff against running settings.

Request body

{
"log_level": "DEBUG",
"rate_limit_requests_per_minute": 0,
"tls_min_version": "TLSv1.0"
}

Response 200 OK

{
"valid": false,
"errors": [
"rate_limit_requests_per_minute must be > 0, got 0",
"tls_min_version must be 'TLSv1.2' or 'TLSv1.3', got 'TLSv1.0'"
],
"warnings": [],
"changes": [
{ "key": "log_level", "from": "INFO", "to": "DEBUG" }
]
}

Validation checks: rate-limit fields must be > 0; confidence/threshold fields must be 0–1; TLS cert paths must exist on disk; tls_min_version/tls_max_version must be "TLSv1.2" or "TLSv1.3". Unknown keys produce warnings, not errors.


Return the timestamp and changed keys from the last config hot-reload.

Terminal window
curl -s http://outpost.internal:8301/admin/api/config/reload-status \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"last_reload_at": 1742137200.5,
"last_reload_changes": [
"LOG_LEVEL: debug -> info",
"DLP_NER_ENABLED: true -> false"
]
}

last_reload_at is a Unix timestamp. last_reload_changes lists changed keys with old → new values.


Trigger a config hot-reload programmatically — equivalent to sending SIGHUP to the outpost process. Re-reads all reloadable environment keys and applies changes in-place. Writes an admin_config_reload audit event.

Query parameters

Parameter Type Default Description
dry_run bool false Compute diff and validate but do not apply changes
Terminal window
# Preview what would change
curl -s -X POST "http://outpost.internal:8301/admin/api/config/reload?dry_run=true" \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"status": "ok",
"changed_keys": ["LOG_LEVEL: debug -> info"],
"restart_required_keys": [],
"reloaded_at": 1742137200.5,
"dry_run": false,
"validation_errors": null
}

Response 422 Unprocessable Entity — pre-reload validation failed

{
"status": "rejected",
"validation_errors": [
{
"name": "AUDIT_HMAC_KEY",
"status": "fail",
"message": "AUDIT_HMAC_KEY must be at least 32 bytes"
}
]
}

Apply a single reloadable configuration key immediately without a restart. Only keys listed in RELOADABLE_KEYS can be applied at runtime. Non-reloadable keys (TLS cert paths, database URLs, crypto keys) require a full restart.

Request body

{"key": "log_level", "value": "DEBUG"}
Field Type Description
key string The OutpostSettings field name to update
value string New value — coerced to the field’s declared type

Response 200 OK

{
"applied": true,
"key": "log_level",
"old_value": "INFO",
"new_value": "DEBUG",
"restart_required": false
}

Error responses

Code Condition
400 Key not in RELOADABLE_KEYS, or missing key/value fields
422 Value cannot be coerced to the field’s declared type

Reloadable keys (common)

Key Type Description
log_level string Logging level: DEBUG, INFO, WARNING, ERROR
audit_flush_interval_seconds int Audit queue flush interval
credint_kanon_enabled bool CredInt k-anonymity (also available via /admin/api/credint/kanon)
heartbeat_interval_seconds int Platform heartbeat frequency
dlp_scan_timeout_ms int DLP scan timeout per request
budget_check_enabled bool Enable/disable budget enforcement

Sensitive values (api_key, secret, password, token) are redacted to *** in the response and audit trail. All applied changes are recorded in the config reload history ring buffer and written to the audit log.


Return a paginated log of all config key changes applied via POST /admin/api/config/apply since startup.

Query parameters

Parameter Default Maximum Description
limit 20 50 Entries per page
offset 0 Pagination offset

Response 200 OK

{
"entries": [
{
"timestamp": 1742151720.4,
"key": "log_level",
"old_value": "INFO",
"new_value": "DEBUG"
},
{
"timestamp": 1742151600.1,
"key": "audit_flush_interval_seconds",
"old_value": "30",
"new_value": "10"
}
],
"total": 2,
"limit": 20,
"offset": 0
}

The history ring buffer is in-memory and resets on outpost restart. Sensitive values are always redacted to ***.


Multi-org mode allows a single outpost to serve multiple organizations simultaneously. Enabled via MULTI_ORG_MODE=true. This section also covers the policy cache, which is closely tied to per-org policy management.

Return org mode and active organisations.

Response 200 OK (single-org mode)

{
"mode": "single",
"orgs": [
{
"org_id": "org_abc",
"last_seen": null,
"request_count": 0
}
]
}

Response 200 OK (multi-org mode)

{
"mode": "multi",
"max_orgs": 10,
"active_orgs": 3,
"orgs": [
{
"org_id": "org_abc",
"last_seen": "2026-03-16T14:00:00Z",
"request_count": 842
},
{
"org_id": "org_xyz",
"last_seen": "2026-03-16T13:59:00Z",
"request_count": 315
}
]
}

GET /admin/api/orgs/{org_id}/policy-status

Section titled “GET /admin/api/orgs/{org_id}/policy-status”

Return policy status for a specific org in multi-org mode.

Path parameter: org_id — the org identifier.

Response 200 OK

{
"org_id": "org_abc",
"policy_loaded": true,
"last_fetched": "2026-03-16T13:55:00Z",
"cache_hits": 412,
"cache_misses": 23
}

Response 400 Bad Request: Outpost is not in multi-org mode (MULTI_ORG_MODE=false).


Return policy cache statistics.

Response 200 OK

{
"entries": 42,
"hit_count": 9821,
"miss_count": 412,
"hit_rate_percent": 95.97,
"eviction_count": 18,
"ttl_seconds": 300,
"enabled": true
}

If the policy cache is not configured, all counters are zero and enabled is false.


Clear all policy cache entries immediately.

Response 200 OK

{
"success": true,
"cleared": 42
}

cleared is the number of entries that were removed.


These endpoints provide immediate traffic control: the emergency kill switch halts all AI proxy traffic, drain mode enables graceful shutdown, routing overrides pin traffic to a specific provider, and prompt holds allow admin review of flagged requests.

Activates or deactivates the emergency kill switch. When active, all LLM requests are rejected immediately with 503 — no DLP evaluation, no provider contact.

POST /admin/api/emergency-kill
Authorization: Bearer <token>
Content-Type: application/json
{
"active": true,
"reason": "Security incident — halting all AI traffic"
}
Field Type Required Description
active boolean yes true to activate, false to deactivate
reason string no Reason logged to the audit trail

Response 200 OK

{
"kill_switch_active": true,
"activated_at": "2026-03-16T09:00:00Z",
"reason": "Security incident — halting all AI traffic"
}

Return graceful drain status. Draining mode is entered when the outpost is shutting down — no new requests are accepted and in-flight requests are allowed to complete.

Response 200 OK

{
"draining": false,
"inflight_requests": 7,
"drain_start_time": null
}

When draining is active, drain_start_time is an ISO 8601 timestamp and draining is true.


Pins all traffic to a specific provider and optional model, or clears an existing routing override. Routing overrides are in-memory and reset on outpost restart.

POST /admin/api/routing-override
Authorization: Bearer <token>
Content-Type: application/json

To set an override:

{
"provider": "anthropic",
"model": "claude-haiku-4-5-20251001",
"reason": "OpenAI outage — routing all traffic to Anthropic fallback"
}

To clear the routing override and restore policy-default routing:

{"provider": null}

or:

{"clear": true}

Response 200 OK

{
"override_active": true,
"provider": "anthropic",
"model": "claude-haiku-4-5-20251001",
"set_at": "2026-03-16T09:05:00Z"
}

Returns 400 if the provider name is not in the policy bundle.


Lists all prompt holds (pending and resolved). Prompt holds are raised when the DLP pipeline flags a request for human review. Holds are in-memory only and do not persist across outpost restarts.

GET /admin/api/prompt-holds
Authorization: Bearer <token>

Response 200 OK

{
"holds": [
{
"hold_id": "hold_01J...",
"user_id": "usr_01J...",
"conversation_id": "conv_01J...",
"status": "pending",
"prompt_message": "Code generation requires confirmation.",
"prompt_text_preview": "Write a Python script that...",
"rule_ids": ["custom-secret-leak"],
"created_at": "2026-03-16T09:10:00Z",
"resolved_at": null,
"resolved_by": null
}
],
"pending_count": 1
}

POST /admin/api/prompt-holds/{hold_id}/approve

Section titled “POST /admin/api/prompt-holds/{hold_id}/approve”

Approves a pending prompt hold, forwarding the held request to the LLM.

POST /admin/api/prompt-holds/{hold_id}/approve
Authorization: Bearer <token>

Returns 404 if the hold is not found or already resolved.

Response 200 OK

{"hold_id": "hold_01J...", "status": "approved", "resolved_at": "2026-03-16T09:11:00Z"}

POST /admin/api/prompt-holds/{hold_id}/deny

Section titled “POST /admin/api/prompt-holds/{hold_id}/deny”

Denies a pending prompt hold, returning an error to the requesting client.

POST /admin/api/prompt-holds/{hold_id}/deny
Authorization: Bearer <token>

Returns 404 if the hold is not found or already resolved.

Response 200 OK

{"hold_id": "hold_01J...", "status": "denied", "resolved_at": "2026-03-16T09:11:00Z"}

Server-Sent Events (SSE) stream. Emits prompt_hold events in real time as new holds arrive. Backlogs all current pending holds on initial connect. Suitable for admin UI integrations.

Terminal window
curl -s -N "http://localhost:8301/admin/api/prompt-holds/events" \
-H "Authorization: Bearer $ARBITEX_ADMIN_KEY" \
-H "Accept: text/event-stream"

Event format

event: prompt_hold
data: {"hold_id": "hold_01J...", "status": "pending", "created_at": "2026-03-16T09:10:00Z"}
event: prompt_hold_resolved
data: {"hold_id": "hold_01J...", "status": "approved", "resolved_at": "2026-03-16T09:11:00Z"}

The stream remains open until the client disconnects.


Approve multiple pending prompt holds in one request.

Request body

Field Type Required Description
hold_ids string[] yes List of hold IDs to approve
Terminal window
curl -s -X POST \
http://outpost.internal:8301/admin/api/prompt-holds/bulk-approve \
-H "Authorization: Bearer $ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"hold_ids": ["hold_abc", "hold_def", "hold_ghi"]}'

Response 200 OK

{
"results": {
"hold_abc": true,
"hold_def": true,
"hold_ghi": false
},
"approved_count": 2
}

results maps each hold ID to true (approved) or false (not found or already resolved). Writes an admin_bulk_approve_prompt_holds audit event.


The plugin system allows optional extensions to be loaded at startup (e.g., custom DLP detectors, routing hooks). Enabled via PLUGINS_ENABLED=true. Plugins are discovered from PLUGIN_DIR (default ./plugins). Each plugin .py file must expose a register_plugin() function returning an object implementing the PluginInterface protocol.

Lists all loaded plugins with their status.

Response 200 OK (plugins enabled)

{
"plugins_enabled": true,
"plugins": [
{
"name": "custom-redact-pii",
"version": "1.2.0",
"status": "enabled",
"description": "Additional PII redaction patterns for EU deployments",
"loaded_at": "2026-03-16T08:00:00Z",
"hooks_registered": ["on_scan_complete", "on_startup", "on_shutdown"]
},
{
"name": "siem-forwarder-v2",
"version": "0.9.1",
"status": "disabled",
"description": "Alternate SIEM forwarding with batching",
"loaded_at": "2026-03-16T08:00:00Z"
}
]
}

Response 200 OK (plugins not enabled)

{"plugins": [], "plugins_enabled": false}

hooks_registered lists only hooks that are callable on the plugin instance.


Enable a loaded plugin by name. Plugin name is case-sensitive and must match plugin.name.

Request body: {} (empty JSON; Content-Type: application/json required — returns 415 if missing)

Response 200 OK

{"status": "enabled", "name": "custom-redact-pii"}

Response 404: {"detail": "Plugin 'custom-redact-pii' not found"}

Response 503: {"detail": "Plugin system not enabled"}


Disable a loaded plugin by name.

Request body: {} (empty JSON required)

Response 200 OK

{"status": "disabled", "name": "custom-redact-pii"}

Response 404: {"detail": "Plugin 'custom-redact-pii' not found"}

Response 503: {"detail": "Plugin system not enabled"}


Returns webhook emitter statistics.

Response 200 OK (emitter configured)

{
"enabled": true,
"events_queued": 12,
"events_sent": 4821,
"events_delivered": 4821,
"events_failed": 3,
"events_in_flight": 2,
"last_delivered_at": "2026-03-16T09:01:00Z",
"last_event_at": "2026-03-15T10:23:44.123456+00:00",
"last_failure_at": "2026-03-15T22:14:00Z",
"last_failure_reason": "HTTP 503 from webhook endpoint"
}

Response 200 OK (emitter not configured)

{
"enabled": false,
"events_sent": 0,
"events_failed": 0,
"last_event_at": null
}

Configuration

Setting Description
WEBHOOK_EMIT_ENABLED Master switch (default false)
WEBHOOK_EMIT_URL Destination URL for webhook POSTs
WEBHOOK_EMIT_SECRET HMAC-SHA256 signing secret

Webhook payload format:

{
"event_type": "scan.complete",
"org_id": "org_abc",
"action": "BLOCK",
"entity_types": ["CREDIT_CARD"],
"scan_duration_ms": 2.1,
"timestamp": "2026-03-15T10:23:44.123456+00:00"
}

The request includes an X-Webhook-Signature header containing the HMAC-SHA256 hex digest of the payload body. Retries up to 3 times with exponential backoff (1s, 2s). events_failed increments after all retries are exhausted.


The outpost has two software update paths: the software update system (/admin/api/updates/*) manages downloading and staging update bundles for operator-applied container restarts, and the upgrade orchestrator (/admin/api/upgrade/*) manages the full automated lifecycle including apply and rollback.

Return the current software update state: check result, download progress, staged version, and Ed25519 signature verification status. Requires SOFTWARE_UPDATE_RELEASE_URL to be configured.

Response 200 OK

{
"status": "staged",
"current_version": "0.19.1",
"latest_version": "0.19.2",
"release_notes": "Fix: routing override not persisting across restarts",
"download_progress": 100,
"staged_at": "2026-03-16T14:22:00Z",
"staged_version": "0.19.2",
"staged_path": "/var/outpost/updates/outpost-0.19.2.tar.gz",
"signature_verified": true,
"error": null
}
Field Description
status disabled | idle | checking | available | downloading | staged | error
download_progress Integer 0–100. null until a download is in progress
staged_path Filesystem path to the staged bundle. null if not yet staged
signature_verified true when the Ed25519 bundle signature passed verification. null if not yet downloaded

When SOFTWARE_UPDATE_RELEASE_URL is not set, status is "disabled" and error is "SOFTWARE_UPDATE_RELEASE_URL not configured".


Trigger an immediate version check against the configured release manifest URL. Returns 503 if SOFTWARE_UPDATE_RELEASE_URL is not configured.

Response 200 OK

{
"update_available": true,
"current_version": "0.19.1",
"latest_version": "0.19.2",
"release_notes": "Fix: routing override not persisting across restarts"
}

Download and cryptographically verify the update bundle for the latest version. The bundle is verified against the embedded Ed25519 public key before being staged. Fail-closed: bundles with invalid signatures are rejected.

A staged update requires an operator-initiated apply (container restart with the new binary). There is no auto-apply path.

Returns 422 if signature verification fails.

Response 200 OK

{
"status": "staged",
"staged_version": "0.19.2",
"staged_path": "/var/outpost/updates/outpost-0.19.2.tar.gz",
"signature_verified": true,
"bytes_downloaded": 18432000
}

Response 422 Unprocessable Entity (signature failure)

{
"status": "error",
"error": "Ed25519 signature verification failed — bundle rejected"
}

Return the current upgrade orchestrator status.

Terminal window
curl -s "http://localhost:8301/admin/api/upgrade/status" \
-H "Authorization: Bearer $ARBITEX_ADMIN_KEY"

Response 200 OK

{
"phase": "idle",
"last_result": "success",
"last_upgraded_at": "2026-03-10T14:22:00Z",
"current_version": "0.14.2",
"history_count": 4
}
Phase Description
idle No upgrade in progress
checking Checking for available updates
downloading Downloading update package
verifying Verifying download signature
backing_up Creating backup of current installation
applying Applying the update
post_verify Verifying the updated installation
rolling_back Automatic rollback in progress

Execute the full upgrade lifecycle. The orchestrator runs all steps sequentially: check → download → verify → backup → apply → post-verify. On any step failure, the orchestrator automatically attempts to roll back.

Response 200 OK

{
"status": "success",
"from_version": "0.14.1",
"to_version": "0.14.2",
"steps": [
{"step": "check", "result": "ok", "duration_ms": 1200},
{"step": "download", "result": "ok", "duration_ms": 8400},
{"step": "verify", "result": "ok", "duration_ms": 230},
{"step": "backup", "result": "ok", "duration_ms": 1100},
{"step": "apply", "result": "ok", "duration_ms": 3200},
{"step": "post_verify", "result": "ok", "duration_ms": 850}
]
}

Returns 409 Conflict if an upgrade is already in progress.


Manually roll back the last staged upgrade. Use when upgrade/run failed without automatic rollback, or when a post-upgrade issue is discovered.

Response 200 OK

{"status": "rolled_back", "restored_version": "0.14.1"}

Return the last 10 upgrade run summaries.

Response 200 OK

[
{
"run_id": "upg_01J...",
"status": "success",
"from_version": "0.14.1",
"to_version": "0.14.2",
"started_at": "2026-03-10T14:20:00Z",
"completed_at": "2026-03-10T14:22:00Z"
}
]

These endpoints provide observability tooling: diagnostic bundles, metrics summaries, connection pool stats, circuit breakers, bandwidth adapter, DLP benchmarks, log export status, OpenTelemetry tracing status, Prometheus Pushgateway status, IP allowlist status, body hash config, and replay protection stats.

Export a sanitized diagnostic bundle for support and troubleshooting. All secret fields (API keys, HMAC keys, signing keys) are scrubbed from the output. Safe to share with Arbitex support.

Response 200 OK

{
"generated_at": "2026-03-16T14:00:00Z",
"generated_by": "[email protected]",
"version": "0.12.0",
"uptime_seconds": 3600,
"config_summary": {
"outpost_id": "outpost-prod-01",
"org_id": "org_abc",
"platform_management_url": "https://api.arbitex.ai",
"log_level": "INFO",
"dlp_enabled": true,
"credint_enabled": true,
"admin_api_key": "***",
"audit_hmac_key": "***"
},
"audit_tail": [
{
"event_id": "a1b2c3d4-...",
"timestamp": "2026-03-16T13:58:00Z",
"action_taken": "ALLOW"
}
],
"metrics": [
{
"name": "outpost_requests_total",
"count": 4821,
"sum": 4821.0,
"avg": 1.0
}
],
"health_checks": [
{
"check": "admin_key_set",
"status": "pass",
"message": "Admin API key configured"
}
]
}

audit_tail contains the last 10 entries from the audit log file. config_summary omits all secret fields (shown as "***"). This endpoint writes an admin_diagnostics_export audit log entry.


Return a JSON summary of the six custom OTel metrics with traffic-light status indicators, plus circuit breaker states. Returns 503 if prometheus-client is not installed.

Response 200 OK

{
"metrics": [
{
"name": "outpost_requests_total",
"display_name": "Total Requests",
"unit": "requests",
"status": "green",
"display_value": 4821.0,
"count": 4821,
"sum": 4821.0,
"avg": 1.0
},
{
"name": "outpost_platform_reachable",
"display_name": "Platform Reachable",
"unit": "bool",
"status": "green",
"display_value": 1.0,
"value": 1.0
}
],
"metric_count": 7,
"circuit_breakers": [
{
"name": "platform_sync",
"state": "closed",
"status": "green"
}
]
}

Traffic-light values: "green" (healthy), "yellow" (warning threshold), "red" (critical threshold). Histograms report count, sum, avg. Gauges report value. The synthetic outpost_platform_reachable metric reflects degradation manager state — 1.0 = reachable, 0.0 = degraded.


HTTP connection pool statistics for the outpost proxy.

Terminal window
curl -s http://outpost.internal:8301/admin/api/metrics/connections \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"active_connections": 12,
"idle_connections": 28,
"max_connections": 200,
"pool_started": true
}

List the state of every registered circuit breaker — both provider-level and per-model breakers.

Terminal window
curl -s http://outpost.internal:8301/admin/api/circuit-breakers \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"circuit_breakers": [
{
"name": "anthropic",
"state": "closed",
"failure_count": 0,
"success_count": 8421,
"last_failure": null
},
{
"name": "openai:gpt-4o",
"state": "half_open",
"failure_count": 3,
"success_count": 7,
"last_failure": 1742137190.3
}
]
}

States: closed (normal), open (blocking requests), half_open (testing recovery).


Bandwidth adapter statistics: throughput measurement, window sizing, and recommended audit batch size.

Terminal window
curl -s http://outpost.internal:8301/admin/api/bandwidth \
-H "Authorization: Bearer $ADMIN_API_KEY"

Response 200 OK

{
"enabled": true,
"throughput_bps": 1048576,
"window_size": 50,
"window_capacity": 100,
"recommended_batch_size": 50,
"tier_name": "standard",
"batch_min": 10,
"batch_max": 100,
"connection_health_status": "healthy"
}

Returns {"enabled": false, ...} when the bandwidth adapter is not configured.


Return DLP pipeline benchmark results from the most recent benchmark run.

Response 200 OK

{
"run_at": "2026-03-15T08:00:00Z",
"pipeline": "5-tier",
"total_samples": 1000,
"avg_latency_ms": 2.34,
"p95_latency_ms": 6.12,
"p99_latency_ms": 11.45,
"tier_breakdown": {
"tier0_tfidf": { "avg_ms": 0.08, "p95_ms": 0.15 },
"tier1_regex": { "avg_ms": 0.21, "p95_ms": 0.45 },
"tier2_ner": { "avg_ms": 1.87, "p95_ms": 4.92 },
"tier3_deberta": { "avg_ms": 8.43, "p95_ms": 18.20 },
"tier4_credint": { "avg_ms": 0.34, "p95_ms": 0.72 }
}
}

Response 404 Not Found: No benchmark results on disk — run benchmarks/dlp_pipeline_bench.py first.


Return log export status (file-based structured log export).

Response 200 OK

{
"enabled": true,
"path": "/var/log/arbitex/outpost",
"format": "jsonl",
"current_file_size_bytes": 204800,
"total_files": 7,
"oldest_file": "2026-03-10T00:00:00Z",
"newest_file": "2026-03-16T14:00:00Z"
}

If log export is not configured, enabled is false and all other fields are empty/zero defaults.


Return OpenTelemetry tracing status.

Response 200 OK

{
"enabled": true,
"endpoint": "http://otel-collector:4317",
"service_name": "arbitex-outpost",
"export_protocol": "grpc",
"spans_exported": 12450,
"export_errors": 0
}

If OTel is not configured, enabled is false.


Return Prometheus Pushgateway exporter status.

Response 200 OK

{
"enabled": true,
"url": "http://pushgateway:9091",
"job": "outpost",
"instance": "outpost-prod-01",
"last_push_at": "2026-03-16T13:59:55Z",
"last_push_status": "success",
"consecutive_failures": 0,
"is_circuit_open": false
}

If the Pushgateway exporter is not configured, enabled is false and all other fields are empty/zero defaults.


Return IP allowlist configuration and denied request count since startup.

Response 200 OK

{
"enabled": true,
"cidrs": ["10.0.0.0/8", "192.168.1.0/24"],
"admin_exempt": true,
"denied_count": 12
}

admin_exempt indicates whether the admin API (port 8301) is exempt from IP allowlist enforcement. When the allowlist is disabled (IP_ALLOWLIST_ENABLED=false), enabled is false and cidrs is an empty array.


Return body hash logging configuration. Body hash logging writes HMAC-SHA256 hashes of request/response bodies into the DLP scan audit events. Enabled via BODY_HASH_LOGGING_ENABLED=true.

Response 200 OK

{
"enabled": true,
"algorithm": "sha256",
"log_response": false,
"key_source": "audit_hmac_key"
}
Field Values
algorithm "sha256" (default)
log_response true = response body is also hashed; false = request body only
key_source "audit_hmac_key" | "admin_jwt_secret" | "not_configured"

Return replay protection cache statistics.

Response 200 OK

{
"enabled": true,
"cache_size": 248,
"duplicates_blocked": 3
}

Replay protection rejects duplicate requests (same X-Request-ID) within the protection window. When disabled (REPLAY_PROTECTION_ENABLED=false), enabled is false and counters are zero.


Status Cause
400 Bad request — missing or invalid field
401 Missing Authorization header, or empty token
403 Invalid admin API key, or operation not permitted
404 Resource not found (provider, rule, hold, etc.)
409 Conflict (duplicate request ID, upgrade already in progress, empty queue flush)
415 Missing Content-Type: application/json
422 Validation error (type coercion failure, bundle validation)
429 Brute-force rate limit exceeded — 5 failed auth attempts within 15 minutes
500 Unhandled server error or uninitialised component
503 Required component not initialised (e.g. no policy bundle loaded)