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

Brute-force protection (OUT-017): 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.


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

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

Response

{
"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"
}
FieldDescription
active_override_countSum of all active provider, rule, ruleset, and routing overrides + kill switch
emergency_killtrue if the emergency kill switch is active (all requests blocked)
routing_overrideProvider name if routing is pinned; null if using policy-default routing
update_availabletrue 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

{
"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

{
"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).


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

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

Response

{
"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"
}
]
}

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"
}
FieldTypeRequiredDescription
duration_hoursfloatNoAuto-re-enable after this many hours. Omit for permanent disable
reasonstringNoReason recorded in the audit log

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

Response

{
"status": "disabled",
"provider": "openai",
"duration_hours": 4
}

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

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

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

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

Response

{
"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

{
"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

{
"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

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

Pins all traffic to a specific provider, or clears an existing routing override.

POST /admin/api/routing-override
Authorization: Bearer <token>
Content-Type: application/json
{
"provider": "anthropic"
}

To clear the routing override and restore policy-default routing, set provider to null:

{
"provider": null
}

Response

{
"routing_override": "anthropic"
}

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

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
}

To deactivate:

{
"active": false
}

Response

{
"emergency_kill": true
}

Prompt holds are raised when the DLP pipeline flags a request for human review. Holds are in-memory only — they do not persist across outpost restarts.

Lists all prompt holds (pending and resolved).

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

Response

{
"holds": [
{
"hold_id": "hold_abc123",
"status": "pending",
"created_at": "2026-03-12T09:00:00Z",
"prompt_length": 842,
"user_id": "u-xyz",
"rule_ids": ["custom-secret-leak"]
}
],
"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

{
"hold_id": "hold_abc123",
"decision": "approve"
}

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

{
"hold_id": "hold_abc123",
"decision": "deny"
}

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

GET /admin/api/prompt-holds/events
Authorization: Bearer <token>
Accept: text/event-stream

Event format

data: {"type": "prompt_hold", "hold_id": "hold_abc123", "status": "pending", ...}

The stream remains open until the client disconnects. Suitable for admin UI integrations.


Returns the current-period usage summary from the outpost’s local usage tracker (when usage tracking is enabled via policy bundle).

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

Response (tracking enabled)

{
"usage_tracking": "enabled",
"totals": {
"request_count": 4821,
"input_tokens": 72300,
"output_tokens": 18100,
"cost_estimate": 0.31
},
"budget_config": {
"monthly_request_limit": 50000,
"alert_pct": 80
}
}

Response (tracking disabled)

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

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-..."
}
FieldRequiredDescription
promptYesText to evaluate
providerNoProvider to use for rule-provider matching
modelNoModel ID for model-specific rules
org_idNoDefaults to the outpost’s configured org_id

Returns 503 if no policy bundle is loaded.

Response — see Policy Simulator guide for full response schema.


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

{
"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 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 (filter loaded)

{
"enabled": true,
"loaded": true,
"entry_count": 1200000,
"loaded_at": 1741780000.0,
"file_size_bytes": 2097152,
"snapshot_date": "2026-03-01",
"fpr_target": 0.1
}

Response (filter not configured)

{
"enabled": false,
"loaded": false,
"entry_count": 0,
"loaded_at": null,
"file_size_bytes": 0,
"snapshot_date": "",
"fpr_target": 0.0
}

loaded_at is a Unix timestamp (float). fpr_target is the false-positive rate the filter was built to achieve (e.g. 0.1 = 10%).

Reloads the CredInt bloom filter from the path configured in CREDINT_BLOOM_PATH. Hot-swaps the in-memory filter without an outpost restart. Returns success/failure and the new entry count.

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

No request body required.

Response (success)

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

Response (scanner 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). Check outpost logs for the error details.


StatusCause
401Missing Authorization header, or empty token
403Invalid admin API key
404Resource not found (provider, rule, hold, etc.)
429Brute-force rate limit exceeded — 5 failed auth attempts within 15 minutes
500Unhandled server error or uninitialised component
503Required component not initialised (e.g. no policy bundle loaded)

MethodPathDescription
GET/admin/api/statusOutpost operational status
GET/admin/api/sync-statusPolicy sync and heartbeat status
GET/admin/api/airgap-configAir-gap configuration (read-only)
GET/admin/api/providersList providers with override state
POST/admin/api/providers/{provider}/disableDisable a provider
POST/admin/api/providers/{provider}/enableRe-enable a provider
GET/admin/api/rulesList DLP rules with toggle state
POST/admin/api/rules/{rule_id}/toggleEnable or disable a DLP rule
GET/admin/api/rulesetsList compliance rulesets with toggle state
POST/admin/api/rulesets/{ruleset_id}/toggleEnable or disable a ruleset
POST/admin/api/routing-overridePin or clear routing override
POST/admin/api/emergency-killActivate/deactivate emergency kill switch
GET/admin/api/prompt-holdsList all prompt holds
POST/admin/api/prompt-holds/{hold_id}/approveApprove a prompt hold
POST/admin/api/prompt-holds/{hold_id}/denyDeny a prompt hold
GET/admin/api/prompt-holds/eventsSSE stream of prompt hold events
GET/admin/api/usageLocal usage summary
POST/admin/api/policy/simulateRun policy simulation
GET/admin/api/audit-bufferLast 200 local audit events
GET/admin/api/credint/statusCredInt bloom filter status
POST/admin/api/credint/reloadReload CredInt bloom filter