APIs

REST API

The control-plane API is how the console, your scripts, CI jobs, and the agent talk to Sirius. There is no /api or /v1 prefix. Paths look like GET /components and POST /workflows.

Local default: http://localhost:8080.

This page covers the contract: discovery, auth, tenancy, errors, and conventions. Then read:

  • Resources — every domain and the routes you will call
  • Identity — sessions, tokens, IdP, users, RBAC
  • Operations — messages, logs, alerts, dashboard
  • Advanced — codecs, BPMN, streams, migration, agent
  • Recipes — end-to-end curl, Python, and JavaScript
  • Studio API — the /studio/* workbench

Discover the surface

The live catalog is the source of truth. It is generated from the runtime, so it does not drift from a hand-written list.

EndpointReturns
GET /openapi.jsonOpenAPI 3.1 for every path
GET /agent/toolsEach operation with method, path, permission, read_only, and an input schema
GET /agent/mcpThe same catalog as a Model Context Protocol tools/list
GET /healthLiveness and build (public)
GET /readyFail-closed readiness — use this as a load-balancer gate
GET /liveProcess liveness for Kubernetes
GET /metricsPrometheus metrics (unauthenticated for scraping)
curl -s "$SIRIUS/agent/tools?category=builder" \
  | jq '.tools[] | {name, method, path, permission, read_only}'

Filter with ?category= (builder, studio, operate, …) or ?read_only=true.

Authenticate

Credentials are tried in a chain. Unrecognized schemes are skipped so session tokens, API tokens, and OIDC can coexist.

CredentialHow to sendUse
SessionAuthorization: Bearer sess_…Console sign-in; short-lived, refreshable
API tokenAuthorization: Bearer sk_… or X-API-Key: sk_…Scripts, CI, services
OIDC JWTAuthorization: Bearer <jwt>Production SSO
Break-glassDeployment-configured emergency keyIncident access; audited
ACCESS=$(curl -s -X POST "$SIRIUS/auth/login" \
  -H 'content-type: application/json' \
  -d '{"tenant_id":"default","username":"admin","password":"password"}' \
  | jq -r .access_token)

curl -s "$SIRIUS/components?tenant_id=default" \
  -H "Authorization: Bearer $ACCESS"

Login returns access_token, refresh_token, expires_at, subject_id, and tenant_id. Access tokens are short-lived (15 minutes by default). When one expires, POST /auth/refresh with the refresh token; both tokens rotate.

MethodPathPurpose
POST/auth/loginExchange username and password (public)
POST/auth/refreshRotate the session pair (public)
POST/auth/logoutRevoke this session
POST/auth/logout-allRevoke every session for the subject
GET/auth/sessionsList active sessions

API tokens

Mint a long-lived, revocable bearer that authenticates as a principal with a fixed set of roles. The raw secret is shown once.

curl -s -X POST "$SIRIUS/api-tokens" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'content-type: application/json' \
  -d '{"tenant_id":"default","name":"CI pipeline","roles":["operator"],"expires_in_days":90}'
{ "secret": "sk_…", "token": { "id": "…", "roles": ["operator"], "revoked": false } }
MethodPathPermission
GET/api-tokens?tenant_id=runtime:identity:read
POST/api-tokensruntime:identity:write
DELETE/api-tokens/{id}?tenant_id=runtime:identity:write

Prefer tokens over interactive login for unattended jobs. See Issue an API token.

Public routes

These never require a credential: GET /health, GET /ready, GET /live, GET /metrics, POST /auth/login, POST /auth/refresh. Studio WebSockets (/studio/collab/ws, /studio/terminal/ws) use a one-time ticket minted over the authenticated API.

Local evaluation stacks may run without an authenticator. Production should not.

Tenancy

Every resource is tenant-scoped. The effective tenant is resolved in this order:

  1. tenant_id in the body (writes) or query string (reads)
  2. The authenticated subject’s tenant
  3. The X-Sirius-Tenant header

Cross-tenant access returns 404 not_found, not 403, so one tenant cannot probe another’s identifiers. * means account-wide scope and needs elevated permission.

Request and response conventions

  • Bodies are JSON (Content-Type: application/json). Binary routes use application/octet-stream.
  • GET reads, POST creates or acts, PUT replaces, PATCH patches, DELETE removes.
  • Timestamps are RFC 3339 UTC.
  • IDs are stable strings. If you omit one, Sirius derives a slug from the name.
  • List routes accept filters (?state=, ?tag=, ?status=) and often ?limit=.

Cursor paging

Three lists grow with traffic rather than configuration. They page with an opaque cursor and a server-side ceiling.

EndpointDefault / ceilingCursor location
GET /audit100 / 1000X-Next-Cursor header
GET /logs200 / 1000X-Next-Cursor header
GET /bpmn/instances100 / 500next_cursor in the body

Walk the list: first request without a cursor, then ?cursor= until the token is absent. A bad cursor is 400 — the server will not silently restart at the top. Paging is stable under writes: the cursor names the last row served, not an offset.

Idempotency

High-blast-radius mutations (supervisor actions, deployments, some replays) accept request_id or idempotency_key. Reuse the same key to retry. Do not issue a new key for the same intent.

Replays always create new history. They never rewrite the original record.

Errors

{ "error": { "code": "validation_error", "message": "name is required", "status": 400 } }

Branch on error.code, not the human message.

HTTPcode (examples)Meaning
400invalid_json, validation_error, bad_requestMalformed or invalid request
401invalid_credentials, authentication_requiredMissing or invalid credential
403forbiddenAuthenticated but not allowed
404not_foundMissing resource, or cross-tenant
409conflict, duplicate_identifierState conflict
422(policy)Semantically rejected (for example a failed promotion gate)
429too_many_queriesConcurrent SQL console ceiling
501not_configuredCapability not wired in this deployment
503build_unavailable, unavailableDependency down

Authorization

When RBAC is on, each route enforces a permission. Discover it on GET /agent/tools (permission field). A denied call is 403 forbidden.

Examples: POST /components needs runtime:component:write. POST /studio/workspaces/{id}/run needs studio:writerun is a write. POST /api-tokens needs runtime:identity:write.

Audit

Mutating calls are recorded. Attribute an agent or service with:

  • X-Sirius-Agent-IDactor_type=agent plus the principal the agent acts as
  • X-Sirius-Actor-Typeagent | service | human
  • X-Sirius-Actor-ID / X-Sirius-Actor-Email — operator attribution

Read the trail with GET /audit.

Retry guidance

  • On 401 with a session token, refresh once and replay.
  • On 429 or 503, back off. For writes, reuse the idempotency key.
  • Do not retry a write with a new key unless you intend a second action.