Skip to content

API overview

The OpenCrane control plane exposes a versioned HTTP API at /api/v1.

Looking for the endpoint list?

This page covers authentication, error envelopes, and pagination conventions. For the full, browsable endpoint and schema reference, see the interactive API reference.

A machine-readable OpenAPI 3.1 description is emitted from the build and served at runtime:

GET /api/v1/openapi.json

Use the OpenAPI document as the authoritative contract. This reference provides a human-readable overview and authentication guide.


Authentication

All endpoints (except the auth and OpenAPI routes listed below) require a bearer token.

Header format:

Authorization: Bearer <token>

Current paths:

  • Bearer token — set OPENCRANE_TOKEN or pass --token to the CLI. This is the automation and break-glass path.
  • OIDC — human operators authenticate via GET /api/v1/auth/login → callback → session cookie. See the Auth section below.

Projected ServiceAccount tokens are the current in-cluster authentication mechanism for pod-to-opencrane-api calls. Each tenant pod presents an audience-bound projected token that is validated via the Kubernetes TokenReview API (/api/internal/contract, /api/internal/awareness/participation). Static bearer tokens remain the automation and break-glass path for operators outside the cluster.


Base URL

All API routes are prefixed with /api/v1. Infrastructure routes (/healthz, /prom) are unprefixed.


Endpoints

Tenants

MethodPathDescription
GET/tenantsList all tenants
POST/tenantsCreate a tenant
GET/tenants/{name}Get a tenant by name
PUT/tenants/{name}Update a tenant
DELETE/tenants/{name}Delete a tenant
POST/tenants/{name}/suspendSuspend a tenant pod
POST/tenants/{name}/resumeResume a suspended tenant
GET/tenants/{name}/datasetsGet tenant dataset memberships
PUT/tenants/{name}/datasetsUpdate tenant dataset memberships
GET/tenants/{name}/effective-contractGet the compiled runtime contract for a tenant
GET/tenants/driftReport projection drift between CRDs and PostgreSQL
POST/tenants/repairRepair drifted tenant projections (dry-run by default; append ?dryRun=false to apply)

Access Policies

MethodPathDescription
GET/policiesList all access policies
POST/policiesCreate a policy
GET/policies/{name}Get a policy by name
PUT/policies/{name}Update a policy
DELETE/policies/{name}Delete a policy
GET/policies/driftReport drift for policy projections
POST/policies/repairRepair drifted policy projections

MCP Servers

MethodPathDescription
GET/mcp-serversList MCP server registrations
POST/mcp-serversRegister an MCP server
GET/mcp-servers/{id}Get an MCP server
PUT/mcp-servers/{id}Update an MCP server
DELETE/mcp-servers/{id}Delete an MCP server

Groups

MethodPathDescription
GET/groupsList groups
POST/groupsCreate a group
GET/groups/{id}Get a group
PUT/groups/{id}Update a group
DELETE/groups/{id}Delete a group

Skills Catalogue

MethodPathDescription
GET/skills/catalogList skill bundles
POST/skills/catalogPublish a skill bundle
GET/skills/catalog/{id}Get a skill bundle
PUT/skills/catalog/{id}Update a skill bundle
DELETE/skills/catalog/{id}Remove a skill bundle

Third-Party Sources

MethodPathDescription
GET/third-party-sourcesList registered third-party sources
POST/third-party-sourcesRegister a third-party source
GET/third-party-sources/{id}Get a source
PUT/third-party-sources/{id}Update a source
DELETE/third-party-sources/{id}Remove a source

Access Tokens

MethodPathDescription
GET/access-tokensList access tokens
POST/access-tokensCreate an access token
DELETE/access-tokens/{id}Revoke an access token

Provider Keys

MethodPathDescription
GET/providers/keysList configured provider API keys
PUT/providers/keysSet a provider API key
DELETE/providers/keys/{provider}Remove a provider key

BYOK provider keys

Org-admin–gated raw upstream provider key management. The key is stored in a Kubernetes Secret and registered with LiteLLM; the raw value is never returned by read endpoints.

MethodPathDescription
GET/providers/byokList BYOK provider status (presence + timestamps; no key material)
PUT/providers/byok/{provider}Set or refresh a raw provider key (org-admin only)
DELETE/providers/byok/{provider}Remove a provider key (org-admin only)

Provider credentials

Named references to External-Secrets-synced k8s Secrets. Use these to bind a model definition to a specific key without embedding raw credentials.

MethodPathDescription
GET/providers/credentialsList provider credentials
GET/providers/credentials/{id}Get a provider credential
POST/providers/credentialsRegister a provider credential
PUT/providers/credentials/{id}Update a provider credential
DELETE/providers/credentials/{id}Remove a provider credential

Model registry

Routable model definitions registered with LiteLLM (BYOM path).

MethodPathDescription
GET/modelsList model definitions (optional ?clusterTenant= filter)
GET/models/{id}Get a model definition
POST/modelsRegister a model definition
PUT/models/{id}Update a model definition
DELETE/models/{id}Delete a model definition

Skill model posture

Per-skill model routing posture (pinned vs. auto selection).

MethodPathDescription
GET/skills/postureList all skill postures
GET/skills/posture/skillGet a skill's posture by compound key (?name=&scope=&team=)
PUT/skills/posture/skillSet a skill's posture

Model routing

Shadow-savings measurement pipeline: eval cases, measurements, proposals, recommendations, and metrics.

MethodPathDescription
GET/model-routing/eval-casesList routing eval cases
GET/model-routing/eval-cases/{id}Get an eval case
POST/model-routing/eval-casesCreate an eval case
PUT/model-routing/eval-cases/{id}Update an eval case
DELETE/model-routing/eval-cases/{id}Delete an eval case
GET/model-routing/measurementsList shadow-savings measurements
GET/model-routing/measurements/{id}Get a measurement
POST/model-routing/measurements/runTrigger a shadow-savings measurement
GET/model-routing/proposalsList routing-change proposals
GET/model-routing/proposals/{id}Get a proposal
POST/model-routing/proposals/{id}/approveApprove a proposal
POST/model-routing/proposals/{id}/rejectReject a proposal
GET/model-routing/recommendationsList ranked savings recommendations
GET/model-routing/metricsFetch Langfuse routing metrics (loosely typed)
GET/model-routing/defaultsGet default model routing settings
PUT/model-routing/defaultsUpdate default model routing settings
How the effective model is resolved

At call time the control plane walks this precedence and writes the winner into the tenant's effective contract — no pod restart:

explicit request override
  → skill-pinned model
    → skill auto-config
      → ClusterTenant default
        → Global default

Each tenant's LiteLLM virtual key carries a models[] allowlist, populated from the registry at key-mint time and kept in sync by the operator's reconcile loop. A call to a model outside the allowlist is rejected at the gateway.

How measurement estimates savings. A run replays every eval case through both the baseline and the candidate model, grades each output with an independent judge model, reads the real per-call USD cost from LiteLLM, and estimates the saving with a bootstrap 95% confidence interval. A proposal is emitted only when that interval excludes zero.

The measurement seams are live — they require a deployed LiteLLM, provider keys, and a ROUTING_JUDGE_MODEL. With any unset, a run is a safe no-op. Full operator recipe: docs/operators/routing-measurement.md.

Trust the judge, but verify it

Keep the judge model independent of the candidate's family — a model graded by a sibling of itself scores too highly. LLM-as-judge grading also carries position and verbosity bias, so calibrate against a small human-graded slice before trusting the absolute savings figure.

Sharing

Inter-user entitlement sharing (MCP servers, skill bundles) and direct resource sharing (files, chats, datasets).

MethodPathDescription
GET/sharesList shares created by the caller
POST/sharesGrant an entitlement you hold to another user or group
DELETE/shares/{id}Revoke a share you created
GET/resource-sharesList file/chat resource shares the caller is a member of
POST/resource-sharesShare a file, chat, or dataset with a user
DELETE/resource-shares/{groupId}/recipients/{subject}Revoke a recipient from a resource share

Awareness

Contract rollout canary control and fleet participation monitoring.

MethodPathDescription
GET/awareness/rolloutShow rollout state
PUT/awareness/rolloutSet the rollout target version
POST/awareness/rollout/promoteAdvance the promotion frontier
POST/awareness/rollout/rollbackRoll all waves back to stable
GET/awareness/rollout/resolve/{tenant}Resolve the contract version for a tenant
GET/awareness/participationFleet participation health (optional ?severity=critical|warning)

Sessions

MethodPathDescription
GET/sessionsList active assistant sessions

Spend

MethodPathDescription
GET/spendQuery spend records

AI Budget

MethodPathDescription
GET/ai-budget/globalGet global budget settings
PUT/ai-budget/globalUpdate global budget settings
GET/ai-budget/accountsList per-user account budgets
PUT/ai-budget/accounts/{userId}Set a user account budget
DELETE/ai-budget/accounts/{userId}Remove a user account budget
GET/ai-budget/{tenantName}/spendGet current spend for a tenant
GET/ai-budget/{tenantName}/litellm-keyGet a tenant's LiteLLM virtual key
POST/ai-budget/{tenantName}/litellm-key/revokeRevoke a tenant's LiteLLM virtual key

Audit

MethodPathDescription
GET/auditQuery audit log entries with optional tenant filter and cursor pagination

Query parameters: tenant, limit (default 100), cursor.

Responses include { data, pagination: { limit, hasMore, nextCursor? } }.

Token Usage

MethodPathDescription
GET/token-usageQuery token usage records

Metrics

MethodPathDescription
GET/metrics/serverServer health and aggregate platform metrics
GET/metrics/projection-driftTenant and AccessPolicy CRD-to-PostgreSQL drift counts, lag, and alert state

Prometheus-format metrics are also available at /prom (unprefixed).

Auth

These endpoints do not require a bearer token.

MethodPathDescription
GET/auth/loginInitiate OIDC login; redirects to the identity provider
GET/auth/callbackOIDC callback; establishes a session
POST/auth/logoutEnd the current session
GET/auth/meReturn the current session principal

Error Envelopes

All 4xx and 5xx responses return a consistent envelope:

json
{
  "error": "Human-readable message",
  "code": "MACHINE_READABLE_CODE"
}

Common codes: TENANT_NOT_FOUND, POLICY_NOT_FOUND, VALIDATION_ERROR, UPSTREAM_ERROR, INTERNAL_ERROR, DATASET_DENIED, UNAUTHORIZED.


Pagination

Endpoints that return collections use cursor-based keyset pagination:

json
{
  "data": [ ... ],
  "pagination": {
    "limit": 100,
    "hasMore": true,
    "nextCursor": "eyJ..."
  }
}

Pass ?cursor=<nextCursor> to fetch the next page.


Infrastructure Routes

These are served without the /api/v1 prefix and require no auth:

RouteDescription
GET /healthzLiveness probe
GET /promPrometheus metrics
GET /api/v1/openapi.jsonOpenAPI 3.1 spec

Released under the AGPL-3.0-or-later License.