Platform Operator API Reference
This reference covers the platform admin API endpoints that operators use to manage core gateway infrastructure. These endpoints are not part of the user-facing API and require admin authentication (Authorization: Bearer $ARBITEX_API_KEY).
For organization config backup and restore, see Config Backup API. For the kill switch API, see Kill Switch API.
Base URL: https://api.arbitex.ai
Endpoints summary
Section titled “Endpoints summary”| Method | Path | Description |
|---|---|---|
GET |
/api/providers/fallback/{model_id} |
Get fallback chain for a model |
PUT |
/api/providers/fallback/{model_id} |
Set fallback chain for a model |
GET |
/api/portal/models/fallback-chains |
List all fallback chains (portal) |
POST |
/api/providers/{name}/reset |
Reset provider circuit breaker |
GET |
/api/providers/thresholds |
Get provider health thresholds |
PUT |
/api/providers/thresholds |
Set provider health thresholds |
GET |
/api/v1/admin/config |
List all system configuration entries |
PUT |
/api/v1/admin/config/{key} |
Update a system configuration value |
POST |
/api/v1/admin/audit/verify |
Verify audit log HMAC chain integrity |
GET |
/api/v1/admin/users |
List all tenant users |
PUT |
/api/v1/admin/users/{user_id}/role |
Change user role |
PUT |
/api/v1/admin/users/{user_id}/active |
Toggle user active status |
PATCH |
/api/v1/admin/users/{user_id}/avatar |
Set user avatar |
POST |
/api/v1/admin/users/invite |
Create email invitation |
GET |
/api/v1/admin/users/invites |
List pending invitations |
DELETE |
/api/v1/admin/users/invites/{invite_id} |
Cancel invitation |
GET |
/api/v1/admin/rate-limits |
List model rate limit configs |
PUT |
/api/v1/admin/rate-limits/{model_id} |
Set model rate limits |
DELETE |
/api/v1/admin/rate-limits/{model_id} |
Remove custom rate limit |
Fallback chain management
Section titled “Fallback chain management”Fallback chains define ordered backup models to route traffic to when the primary model is unavailable. Chains are configured per primary model and applied globally across the tenant.
FallbackEntry object
Section titled “FallbackEntry object”| Field | Type | Description |
|---|---|---|
model_id |
string |
Fallback model identifier (e.g. claude-sonnet-4-20250514) |
provider_name |
string |
Provider hosting the fallback model (e.g. anthropic) |
priority |
int |
Priority rank — 1 is tried first, higher values tried later |
GET /api/providers/fallback/{model_id}
Section titled “GET /api/providers/fallback/{model_id}”Get the fallback chain configuration for a primary model.
Path parameters
| Parameter | Type | Description |
|---|---|---|
model_id |
string |
Primary model identifier |
Request
curl -s https://api.arbitex.ai/api/providers/fallback/gpt-4o \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 200 OK
{ "model_id": "gpt-4o", "fallbacks": [ { "model_id": "claude-sonnet-4-20250514", "provider_name": "anthropic", "priority": 1 }, { "model_id": "gemini-1.5-pro", "provider_name": "google", "priority": 2 } ]}Returns {"model_id": "...", "fallbacks": []} if no fallback chain is configured for the model.
PUT /api/providers/fallback/{model_id}
Section titled “PUT /api/providers/fallback/{model_id}”Set (replace) the fallback chain for a primary model. The entire chain is replaced — entries not included in the request are removed.
Path parameters
| Parameter | Type | Description |
|---|---|---|
model_id |
string |
Primary model identifier |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
model_id |
string |
yes | Must match the path parameter |
fallbacks |
FallbackEntry[] |
yes | Ordered fallback entries (empty array clears the chain) |
Request — set a two-hop fallback chain
curl -s -X PUT \ https://api.arbitex.ai/api/providers/fallback/gpt-4o \ -H "Authorization: Bearer $ARBITEX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model_id": "gpt-4o", "fallbacks": [ {"model_id": "claude-sonnet-4-20250514", "provider_name": "anthropic", "priority": 1}, {"model_id": "gemini-1.5-pro", "provider_name": "google", "priority": 2} ] }'Response 200 OK
{ "status": "saved", "model_id": "gpt-4o", "fallbacks": [ {"model_id": "claude-sonnet-4-20250514", "provider_name": "anthropic", "priority": 1}, {"model_id": "gemini-1.5-pro", "provider_name": "google", "priority": 2} ]}Request — clear fallback chain
curl -s -X PUT \ https://api.arbitex.ai/api/providers/fallback/gpt-4o \ -H "Authorization: Bearer $ARBITEX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model_id": "gpt-4o", "fallbacks": []}'GET /api/portal/models/fallback-chains
Section titled “GET /api/portal/models/fallback-chains”List all fallback chain configurations. This endpoint is available to authenticated (non-admin) portal users and returns the same global fallback config used by the gateway.
Authentication: User Bearer token (does not require admin)
Request
curl -s https://api.arbitex.ai/api/portal/models/fallback-chains \ -H "Authorization: Bearer $ARBITEX_SESSION_TOKEN"Response 200 OK — array of PortalFallbackChain
[ { "model_id": "gpt-4o", "fallbacks": [ {"model_id": "claude-sonnet-4-20250514", "provider_name": "anthropic", "priority": 1} ] }, { "model_id": "claude-opus-4-20250514", "fallbacks": [ {"model_id": "gpt-4o", "provider_name": "openai", "priority": 1} ] }]Returns [] if no fallback configuration has been saved.
Provider circuit breaker reset
Section titled “Provider circuit breaker reset”POST /api/providers/{name}/reset
Section titled “POST /api/providers/{name}/reset”Reset the circuit breaker for a provider or a specific model. Use this after resolving an outage to immediately restore traffic without waiting for the automatic half-open recovery interval.
Path parameters
| Parameter | Type | Description |
|---|---|---|
name |
string |
Provider name (e.g. openai, anthropic) |
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
model_id |
string |
no | Reset only the circuit breaker for this specific model |
Request — reset all circuit breakers for a provider
curl -s -X POST https://api.arbitex.ai/api/providers/openai/reset \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 200 OK
{ "status": "reset", "provider": "openai", "health": { "state": "closed", "health_score": 1.0, "failure_rate": 0.0, "available": true }}Request — reset a single model’s circuit breaker
curl -s -X POST \ "https://api.arbitex.ai/api/providers/openai/reset?model_id=gpt-4o" \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 200 OK
{ "status": "reset", "provider": "openai", "model_id": "gpt-4o", "health": { "state": "closed", "health_score": 1.0, "failure_rate": 0.0, "available": true }}Provider health thresholds
Section titled “Provider health thresholds”Health thresholds configure the p95 latency and error rate limits at which a provider is considered degraded. The health monitor uses these to decide when to open the circuit breaker.
ProviderThreshold object
Section titled “ProviderThreshold object”| Field | Type | Default | Description |
|---|---|---|---|
latency_ms |
int |
500 |
Maximum acceptable p95 latency in milliseconds |
error_rate_pct |
float |
5.0 |
Maximum acceptable error rate as a percentage (0–100) |
GET /api/providers/thresholds
Section titled “GET /api/providers/thresholds”Get all configured per-provider health thresholds.
Request
curl -s https://api.arbitex.ai/api/providers/thresholds \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 200 OK
{ "thresholds": { "openai": {"latency_ms": 400, "error_rate_pct": 3.0}, "anthropic": {"latency_ms": 600, "error_rate_pct": 5.0} }}Returns {"thresholds": {}} if no thresholds have been configured (defaults apply).
PUT /api/providers/thresholds
Section titled “PUT /api/providers/thresholds”Set per-provider health thresholds. Replaces all existing thresholds.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
thresholds |
object |
yes | Map of provider name → ProviderThreshold |
Request
curl -s -X PUT https://api.arbitex.ai/api/providers/thresholds \ -H "Authorization: Bearer $ARBITEX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "thresholds": { "openai": {"latency_ms": 400, "error_rate_pct": 3.0}, "anthropic": {"latency_ms": 600, "error_rate_pct": 5.0}, "google": {"latency_ms": 500, "error_rate_pct": 5.0} } }'Response 200 OK — the saved thresholds
{ "thresholds": { "openai": {"latency_ms": 400, "error_rate_pct": 3.0}, "anthropic": {"latency_ms": 600, "error_rate_pct": 5.0}, "google": {"latency_ms": 500, "error_rate_pct": 5.0} }}System configuration
Section titled “System configuration”System configuration keys control gateway runtime behavior. Values can be set via environment variables or overridden at runtime via the admin API. DB overrides take precedence over environment variables.
GET /api/v1/admin/config
Section titled “GET /api/v1/admin/config”List all system configuration entries grouped by category.
Request
curl -s https://api.arbitex.ai/api/v1/admin/config \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 200 OK
{ "groups": [ { "category": "audit", "entries": [ { "key": "AUDIT_HMAC_KEY", "value": "***", "source": "env", "editable": false, "description": "HMAC key for audit chain signing" } ] }, { "category": "routing", "entries": [ { "key": "DEFAULT_FALLBACK_ENABLED", "value": "true", "source": "db", "editable": true, "description": "Enable fallback chain routing" } ] } ]}Sensitive values (keys, secrets) are masked as "***".
PUT /api/v1/admin/config/{key}
Section titled “PUT /api/v1/admin/config/{key}”Update a single system configuration value. Only editable keys can be updated via the API — read-only keys (set by environment variables or deployment config) return 400.
Path parameters
| Parameter | Type | Description |
|---|---|---|
key |
string |
Configuration key to update |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
value |
string |
yes | New value for the configuration key |
Request
curl -s -X PUT https://api.arbitex.ai/api/v1/admin/config/DEFAULT_FALLBACK_ENABLED \ -H "Authorization: Bearer $ARBITEX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"value": "false"}'Response 200 OK — the updated configuration entry
Error codes
| Status | Condition |
|---|---|
400 Bad Request |
Key is read-only or value fails type validation |
404 Not Found |
Unknown configuration key |
Every config update writes an audit log entry with the old and new values and the acting admin’s identity.
Audit chain verification
Section titled “Audit chain verification”POST /api/v1/admin/audit/verify
Section titled “POST /api/v1/admin/audit/verify”Verify the HMAC chain integrity of all audit log entries. Fetches all AuditLog rows ordered by created_at and checks that each event’s HMAC matches its computed digest and that the previous_hmac chain is unbroken.
Request
curl -s -X POST https://api.arbitex.ai/api/v1/admin/audit/verify \ -H "Authorization: Bearer $ARBITEX_API_KEY"No request body.
Response 200 OK
{ "valid": true, "total_entries": 14823, "errors": []}Response 200 OK — chain broken
{ "valid": false, "total_entries": 14823, "errors": [ "Event at index 7421: HMAC mismatch — stored hmac does not match computed digest", "Event at index 7422: Chain break — previous_hmac does not match preceding event" ]}| Field | Type | Description |
|---|---|---|
valid |
bool |
true if the entire chain is intact |
total_entries |
int |
Number of audit log entries examined |
errors |
string[] |
Human-readable integrity violation descriptions |
A broken chain does not necessarily indicate malicious tampering — it can also result from HMAC key rotation without migration or database restoration from a partial backup.
Error codes
| Status | Condition |
|---|---|
400 Bad Request |
AUDIT_HMAC_KEY is not configured |
403 Forbidden |
Caller is not an admin |
User management
Section titled “User management”These endpoints let admins list users, update roles and active status, set avatars, and manage email invitations. All are scoped to the admin’s tenant.
GET /api/v1/admin/users
Section titled “GET /api/v1/admin/users”List all users in the tenant with pagination.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
int | 20 | Results per page (1–100) |
offset |
int | 0 | Number of results to skip |
Request
curl -s "https://api.arbitex.ai/api/v1/admin/users?limit=20&offset=0" \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 200 OK
{ "items": [ { "id": "aabbccdd-0000-0000-0000-000000000001", "role": "user", "is_active": true, "tenant_id": "a1b2c3d4-0000-0000-0000-000000000001", "created_at": "2026-01-10T08:00:00Z" } ], "total": 42, "limit": 20, "offset": 0}PUT /api/v1/admin/users/{user_id}/role
Section titled “PUT /api/v1/admin/users/{user_id}/role”Change a user’s role. Admins cannot change their own role.
Path parameters
| Parameter | Type | Description |
|---|---|---|
user_id |
UUID | Target user UUID |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
role |
string | yes | New role: "user" or "admin" |
Request
curl -s -X PUT \ https://api.arbitex.ai/api/v1/admin/users/${USER_ID}/role \ -H "Authorization: Bearer $ARBITEX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"role": "admin"}'Response 200 OK — updated user object.
Error codes
| Status | Condition |
|---|---|
400 Bad Request |
Admin attempting to change their own role |
404 Not Found |
User not found in tenant |
PUT /api/v1/admin/users/{user_id}/active
Section titled “PUT /api/v1/admin/users/{user_id}/active”Enable or disable a user account. Admins cannot deactivate themselves.
Path parameters
| Parameter | Type | Description |
|---|---|---|
user_id |
UUID | Target user UUID |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
is_active |
boolean | yes | true to enable, false to disable |
Request
curl -s -X PUT \ https://api.arbitex.ai/api/v1/admin/users/${USER_ID}/active \ -H "Authorization: Bearer $ARBITEX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"is_active": false}'Response 200 OK — updated user object.
PATCH /api/v1/admin/users/{user_id}/avatar
Section titled “PATCH /api/v1/admin/users/{user_id}/avatar”Set or replace a user’s avatar image. Accepts PNG, JPEG, WebP, or AVIF up to 2 MB. The image is optimized to 256×256 WebP and stored content-addressed.
Path parameters
| Parameter | Type | Description |
|---|---|---|
user_id |
UUID | Target user UUID |
Request — multipart/form-data
curl -s -X PATCH \ https://api.arbitex.ai/api/v1/admin/users/${USER_ID}/avatar \ -H "Authorization: Bearer $ARBITEX_API_KEY" \Response 200 OK — updated user object with new profile_settings.avatar_url.
Error codes
| Status | Condition |
|---|---|
400 Bad Request |
Invalid image format, too large, or processing failure |
404 Not Found |
User not found in tenant |
User invitations
Section titled “User invitations”Admins can invite new users by email. Invitations are valid for 7 days and can be listed and cancelled.
POST /api/v1/admin/users/invite
Section titled “POST /api/v1/admin/users/invite”Create a pending email invitation.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | yes | Email address to invite |
Request
curl -s -X POST https://api.arbitex.ai/api/v1/admin/users/invite \ -H "Authorization: Bearer $ARBITEX_API_KEY" \ -H "Content-Type: application/json" \Response 201 Created
{ "id": "ccdd1122-0000-0000-0000-000000000001", "invited_by_id": "aabbccdd-0000-0000-0000-000000000001", "token": "eeee1111-0000-0000-0000-000000000001", "status": "pending", "created_at": "2026-03-16T14:00:00Z", "expires_at": "2026-03-23T14:00:00Z"}An audit event user_invite_created is written with the target email and invite ID.
Error codes
| Status | Condition |
|---|---|
409 Conflict |
A PENDING invite already exists for this email in the tenant |
GET /api/v1/admin/users/invites
Section titled “GET /api/v1/admin/users/invites”List all pending invitations in the tenant.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
int | 50 | Maximum results (1–200) |
Request
curl -s "https://api.arbitex.ai/api/v1/admin/users/invites?limit=50" \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 200 OK — paginated list of invite objects.
DELETE /api/v1/admin/users/invites/{invite_id}
Section titled “DELETE /api/v1/admin/users/invites/{invite_id}”Cancel a pending invitation. Only PENDING invites can be cancelled — already-accepted invites return 400.
Path parameters
| Parameter | Type | Description |
|---|---|---|
invite_id |
UUID | Invite UUID to cancel |
Request
curl -s -X DELETE \ https://api.arbitex.ai/api/v1/admin/users/invites/${INVITE_ID} \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 204 No Content on success.
Error codes
| Status | Condition |
|---|---|
400 Bad Request |
Invite is not in PENDING status |
404 Not Found |
Invite not found in tenant |
Model rate limits
Section titled “Model rate limits”Per-model rate limit configuration controls throughput at the model level (requests per minute and tokens per minute). Limits can be set per model via the admin API; unconfigured models use tier-based defaults.
ModelRateLimitConfig object
Section titled “ModelRateLimitConfig object”| Field | Type | Description |
|---|---|---|
model_id |
string | Model identifier (e.g. gpt-4o) |
rpm_limit |
int | Requests per minute limit (≥1) |
tpm_limit |
int | Tokens per minute limit (≥1) |
enabled |
boolean | Whether rate limiting is active for this model |
source |
string | "custom" (DB-configured) or "default" (tier-based) |
GET /api/v1/admin/rate-limits
Section titled “GET /api/v1/admin/rate-limits”List all model rate limit configurations. Returns DB-configured limits plus tier-based defaults for well-known models with no custom configuration.
Request
curl -s https://api.arbitex.ai/api/v1/admin/rate-limits \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 200 OK — array of ModelRateLimitConfig
[ { "model_id": "gpt-4o", "rpm_limit": 60, "tpm_limit": 100000, "enabled": true, "source": "custom" }, { "model_id": "claude-sonnet-4-20250514", "rpm_limit": 50, "tpm_limit": 80000, "enabled": true, "source": "default" }]PUT /api/v1/admin/rate-limits/{model_id}
Section titled “PUT /api/v1/admin/rate-limits/{model_id}”Create or update the rate limit configuration for a specific model. Fields not included in the request body retain their current values.
Path parameters
| Parameter | Type | Description |
|---|---|---|
model_id |
string | Model identifier (URL-encoded if it contains /) |
Request body (all fields optional — only provided fields are updated)
| Field | Type | Description |
|---|---|---|
rpm_limit |
int | Requests per minute (≥1) |
tpm_limit |
int | Tokens per minute (≥1) |
enabled |
boolean | Enable or disable rate limiting for this model |
Request
curl -s -X PUT https://api.arbitex.ai/api/v1/admin/rate-limits/gpt-4o \ -H "Authorization: Bearer $ARBITEX_API_KEY" \ -H "Content-Type: application/json" \ -d '{"rpm_limit": 60, "tpm_limit": 100000, "enabled": true}'Response 200 OK — the saved ModelRateLimitConfig.
DELETE /api/v1/admin/rate-limits/{model_id}
Section titled “DELETE /api/v1/admin/rate-limits/{model_id}”Remove a custom rate limit for a model, reverting it to tier-based defaults.
Request
curl -s -X DELETE https://api.arbitex.ai/api/v1/admin/rate-limits/gpt-4o \ -H "Authorization: Bearer $ARBITEX_API_KEY"Response 204 No Content on success.
Error codes
| Status | Condition |
|---|---|
404 Not Found |
No custom rate limit exists for the model |
DLP rule administration
Section titled “DLP rule administration”DLP rules control which entity types are detected and what action is taken when a match is found. All mutations create version records for audit purposes.
Key endpoints summary
Section titled “Key endpoints summary”| Method | Path | Description |
|---|---|---|
POST |
/api/v1/admin/dlp-rules/ |
Create a new DLP rule |
GET |
/api/v1/admin/dlp-rules/ |
List all DLP rules |
GET |
/api/v1/admin/dlp-rules/{rule_id} |
Get a specific rule |
PUT |
/api/v1/admin/dlp-rules/{rule_id} |
Update a rule |
DELETE |
/api/v1/admin/dlp-rules/{rule_id} |
Delete a rule |
POST |
/api/v1/admin/dlp-rules/test |
Test a rule against sample text |
POST |
/api/v1/admin/dlp-rules/evaluate |
Evaluate patterns against text |
GET |
/api/v1/admin/dlp-rules/available-patterns |
List built-in regex patterns |
GET |
/api/v1/admin/dlp-rules/export |
Export all rules as a bundle |
POST |
/api/v1/admin/dlp-rules/import |
Import rules from a bundle |
GET |
/api/v1/admin/dlp-rules/{rule_id}/versions |
Get version history for a rule |
Every rule create, update, and delete writes a DLPRuleVersion record capturing the old and new values, the acting admin, and a timestamp.
See the DLP rules guide for configuration guidance.
See also
Section titled “See also”- Config Backup API — org config export and import (20 domains)
- Kill Switch API — provider and model kill switch controls
- Provider Management API — provider catalog, credentials, and health
- Routing — fallback chains, health monitoring, and circuit breaker behavior
- Audit log export — exporting and querying audit events
- Attachment DLP guide — file attachment scanning and quarantine admin