Skip to content

REST API

The Orchestra API is a FastAPI service that manages workshop templates and running workshop instances. The frontend dashboard is just a client of this API, and you can call it directly for scripting or automation.

The API serves its own interactive, always-up-to-date spec. On the API host:

  • Swagger UI: https://app.<your-domain>/docs
  • ReDoc: https://app.<your-domain>/redoc
  • OpenAPI JSON: https://app.<your-domain>/openapi.json

These are generated from the live code, so they are the source of truth for exact request/response schemas, query parameters, and status codes. The table below is a quick map; reach for /docs for the full detail.

Orchestra does not implement its own login. All authentication is handled by oauth2-proxy at the ingress (see Authentication and ADR-0001). After a user logs in via Google or GitHub, the proxy forwards every upstream request with a trusted header:

X-Auth-Request-Email: alice@example.com

The API reads this header (configurable via ORCHESTRA_TRUSTED_AUTH_HEADER, default X-Auth-Request-Email) and treats its value as the caller’s identity. A request that reaches the API without it gets 401 Unauthorized.

Because the proxy terminates auth, you don’t send a bearer token to the API — you authenticate to oauth2-proxy (carrying its session cookie) and it injects the header. The Traefik middleware strips any inbound X-Auth-Request-* headers before re-setting them, so callers cannot forge an identity.

Admin vs. regular users. A caller is treated as an admin when their email is in the server’s admin_emails list. Admin-only routes return 403 Forbidden otherwise. Regular users see and act on only their own instances; admins see all.

Local development. With ORCHESTRA_REQUIRE_AUTHENTICATION=false and ORCHESTRA_DEV_IDENTITY set, the API short-circuits to that identity so you can call it without a proxy. Never use this in production.

All paths are relative to the API root. {id} is a template UUID; {name} is a workshop instance’s Kubernetes name.

MethodPathPurpose
GET/auth/meIdentity of the current user (email, is_admin).
GET/auth/auth-configLogin/logout URLs and dev-mode flag for the frontend.

Templates are git-managed YAML served read-only (see ADR-0006). There are no create/update/delete endpoints — edit the files under deploy/charts/orchestra/files/templates/ via a pull request. Template ids are deterministic (derived from the slug).

MethodPathPurpose
GET/templates/List templates (paginated). include_inactive is admin-only.
GET/templates/{id}Get a template by ID.
GET/templates/statsLaunch counts for all templates.
GET/templates/{id}/statsLaunch/utilization stats for one template. Admin.
MethodPathPurpose
POST/templates/{id}/launchLaunch a new workshop instance from a template. Name is auto-generated as {slug}-{suffix}.
GET/instances/List running instances. Users see their own; admins see all.
GET/instances/{name}Get one instance, syncing live status from Kubernetes.
GET/instances/{name}/statusLightweight status and URL for an instance.
GET/instances/{name}/utilizationTime-in-phase utilization breakdown.
POST/instances/{name}/extendExtend an instance’s expiry (extra_hours, default +1h).
DELETE/instances/{name}Terminate an instance (deletes the CRD, marks the record terminated).
GET/instances/eventsServer-sent event stream of instance updates for the caller.
GET/instances/summaryAggregate launch counts (all-time and last 7 days). Admin.

These are unauthenticated and intended for probes and uptime checks.

MethodPathPurpose
GET/health/Basic health check.
GET/health/readyReadiness probe.
GET/health/liveLiveness probe.

This page is a curated map of the main routes. The live spec at /docs (and /openapi.json) is generated from the running code and always reflects the current schemas, parameters, and response codes — defer to it when the two disagree.