API reference

Management API

Tenant management, billing, policies, deletion, operator sessions, and the read-only D1/D2 contracts.

The management API is a Python FastAPI service. Established tenant-management routes and mounted-but-provisional operator read contracts share one process. A mounted route is not production operator readiness.

Provisional Ledger class: provisional
Verified 2026-10-21Routes are mounted and locally tested; hosted session, origin, CORS/CSRF, and recovery evidence are not accepted

Base URL and contract artifacts

Local default: http://127.0.0.1:8010.

  • GET /openapi.json, /docs, /redoc
  • GET /health, /ready, /metrics
  • GET /v1/tenant/ping — authenticated tenant smoke route

The mounted route inventory is generated from the FastAPI app and checked in under services/api/scripts/route_inventory.json. The OpenAPI snapshot is checked separately. Both must be regenerated when a route or schema changes.

services/api/.venv/bin/python services/api/scripts/route_inventory.py --check
bash .github/scripts/check-openapi-snapshot.sh

Two authentication modes

ModeUsed byRules
Bearer PATTenant management routesPermission bitmap, path org must match the token org, role checks where declared
Operator cookieConsole-facing D1/D2 and operator session routesServer-owned access/refresh cookies, CSRF on cookie mutations, session subject and permissions

A browser bearer token is not an alternative operator-session design. Operator session issuance is default-off and requires the auth/session feature path; the development HS256 stub is not a production issuer. See Operator sessions.

Route families

FamilyMounted pathsBoundary
OrganizationsGET/PATCH /v1/organizations/{org_id}, POST .../suspend, DELETE ...Role/permission check; deletion returns 202 and a job
Deletion jobsGET /v1/organizations/{org_id}/deletion-jobs/{job_id}Owner/admin read; per-store receipts
UsersGET/POST /v1/users, GET/PATCH/DELETE /v1/users/{user_id}Last-owner protection; admin/owner rules
AgentsGET/POST /v1/agents, GET/PATCH/DELETE /v1/agents/{agent_id}, `POST .../{agent_id}/activatepause
TokensGET/POST /v1/tokens, GET/DELETE /v1/tokens/{token_id}Plaintext returned only at creation; never re-readable
ProvidersGET/POST /v1/organizations/{org_id}/providers, DELETE .../{provider_name}Metadata only; secret sealing delegated to auth
Rate limitsGET/PATCH /v1/organizations/{org_id}/rate-limitsOrg and per-agent RPM overrides
Model policiesGET/POST /v1/organizations/{org_id}/model-policies, GET/PATCH/DELETE .../{policy_id}Tenant policy CRUD; proxy enforces the resolved policy
Capture policiesGET/POST /v1/organizations/{org_id}/capture-policies, GET .../resolved, PATCH/DELETE .../{policy_id}Retention/redaction policy CRUD and resolution
BillingGET/POST .../rate-cards, POST .../rate-cards/{card_id}/versions, GET/POST .../budget-periodsVersioned rates, immutable published versions
UsagePOST /v1/organizations/{org_id}/usage/queryToken-scoped; requires an org predicate in generated ClickHouse SQL
Legal holdsGET/POST .../legal-holds, POST .../{hold_id}/clearLegalHoldManage; set/clear require a session subject
Operator session`POST /v1/operator/session/loginrefresh
Operator D1GET /v1/operator/context, /overview, /platform/health, /events/streamRead/event transport; provisional
Operator D2GET /v1/operator/traces, /traces/{trace_id}, /traces/runs/{run_id}Metadata-only list and deterministic multi-run read

The D2 list uses an opaque, signed cursor and a bounded time range; invalid or expired cursors are VALIDATION_ERROR, not a silent restart. A trace lookup that is unknown or outside the tenant returns NOT_FOUND.

Authorization sequence

  1. Authenticate the credential (PAT bearer or operator session).
  2. For a path-scoped route, compare the path org_id with the verified organization.
  3. Check the required permission bit or role.
  4. Open a tenant-scoped database session and set app.current_org_id for the transaction.
  5. Apply explicit org_id predicates even where RLS is enabled.
  6. Map missing or cross-tenant resources to 404 where existence leakage is a risk.

A path mismatch is not permission to use the path organization. The token's organization wins, and the request is rejected.

Example: list token metadata

curl -s \
  -H "Authorization: Bearer ${IBEX_DEV_TOKEN}" \
  "http://127.0.0.1:8010/v1/tokens"

A token response returns metadata such as ID, name, type, permissions, and timestamps. It never returns the plaintext secret after creation. Do not put the token in a URL.

Error behavior

ConditionHTTPCode examples
Missing/invalid credential401Authentication failure from the auth layer
Missing permission or role403INSUFFICIENT_PERMISSIONS
Step-up required403INSUFFICIENT_PERMISSIONS with step-up detail
Path org mismatch403INSUFFICIENT_PERMISSIONS
Unknown/cross-tenant resource404NOT_FOUND
Invalid input, cursor, or query range400VALIDATION_ERROR
Last owner removal409LAST_OWNER_PROTECTED
Dependency/store unavailable503SERVICE_DEGRADED

The shared error envelope is defined by the API error package; do not return ad-hoc JSON. A 202 deletion response is an accepted request, not a completed purge.

Operator D1/D2 boundary

D1/D2 are read-only and return Cache-Control: no-store. D2 exposes approved run metadata only: no prompts, completions, hidden reasoning, raw tool arguments, or unredacted payloads. The Console must not fabricate a detail when the upstream returns unavailable.

The API has no general provenance inspector, replay action, export endpoint, or operator write tool in this slice. Mounted presentation in the Console is not an owning contract.

Configuration

VariablePurpose
IBEX_API_DATABASE_URLAsync PostgreSQL DSN
IBEX_AUTH_GRPC_ADDR / IBEX_API_AUTH_GRPC_ADDRAuthService gRPC target
IBEX_API_AUTH_TIMEOUT_MSAuth deadline; default 50 ms
IBEX_API_REDIS_URLSuspension/rate-limit pub/sub and idempotency support
IBEX_API_CELERY_BROKER_URLRequired for organization-deletion enqueue; fail closed
IBEX_API_HOST / IBEX_API_PORTBind settings; default port 8010
IBEX_API_DOCS_BASE_URLPublic error-docs prefix
DASHBOARD_JWT_PUBLIC_KEYS_PEMOperator-session RS256 verification keys; distinct from auth issuer keys

Operator session feature flags and TOTP settings belong to the auth/API session path; do not infer them from a Console environment variable.

Readiness boundary

Production promotion still requires AuthService/session/MFA integration, deployment-origin and CORS/CSRF evidence, two-tenant negative tests, redaction and hostile-content tests, performance/availability evidence, and rollback/incident runbooks. The full management product and provenance inspector are not complete until those gates are accepted.