Overview
Conventions, authentication, and base URLs for the Flux REST API.
The Flux server exposes a FastAPI application. Every public route is documented in this section, organized by domain: workflows, executions, workers, schedules, secrets, and auth/admin.
Base URL
A locally-started server (flux start server) listens on http://localhost:8000 by default. In production the server typically sits behind a reverse proxy that terminates TLS and exposes the API at a public hostname. The REST API has no global version prefix in Flux 0.56.0 — paths begin at /workflows, /executions, /admin/..., and so on.
Authentication
Flux uses a bearer-token model. Authenticated callers send:
Authorization: Bearer <token>
Two production providers are always available when [flux.security.auth].enabled = true:
- API keys (
APIKeyProvider) — long-lived tokens minted per service-account principal viaPOST /admin/principals/{subject}/keys. Used by operators, CI, and worker processes. - OIDC (
OIDCProvider) — validates JWT bearer tokens against a configured issuer.
Two internal providers are always registered but not intended for direct use:
- Bootstrap token — single-purpose token used only by
POST /workers/registerto provision a worker’s service-account API key. - Execution token (
ExecutionTokenProvider) — short-lived JWT minted by the server when a workflow run starts; the worker presents it on subsequent callbacks scoped to that one execution.
For provider configuration and key lifecycle, see Security: Authentication.
When auth is disabled
If [flux.security.auth].enabled = false, every route accepts unauthenticated requests as an anonymous identity with no permissions resolved. Most routes still call require_permission(...), which returns success when auth is disabled. This mode is intended for local development only.
Permissions
Most routes are gated by require_permission("<permission>"). Permissions follow the shape resource:scope:scope:verb, with * as a wildcard. Common shapes:
workflow:{namespace}:{name}:read|run|registerexecution:*:readschedule:*:read|manageworker:*:*admin:secrets:read|manageadmin:principals:read|manageadmin:roles:read|manageadmin:metrics:read
A 403 response carries {"detail": "Permission denied: requires '<perm>'"} (or, for workflow run, a structured body with missing_permissions).
Request and response format
- Content type is
application/jsonunless explicitly noted (SSE endpoints usetext/event-stream; workflow upload usesmultipart/form-data). - Errors come back as FastAPI’s standard
{"detail": "<message>"}JSON, or{"detail": {...}}for structured cases. - Common status codes:
400bad request,401missing/invalid auth,403permission denied,404not found,409conflict (e.g. claim race, duplicate role),413payload too large,422validation,500server error. - Run endpoints (
POST /workflows/{ns}/{name}/run/{mode}) read an optionalX-Flux-Preferred-Workerheader — the sticky-routing hint workers relay for meshcall()s. The value is stripped of surrounding whitespace and discarded when empty or longer than 256 characters; the dispatcher honors it only when the named worker is eligible (see Dispatch modes). - Approval decisions (
POST /executions/{id}/approvals/{task_call_id}/approve) accept{"reason": ..., "always": false}—always: truecreates a standing grant. Approval rows in decision responses and listings include ascopefield (callorexecution); see Human approvals.
HTTP method conventions
Flux mostly follows REST conventions, with one deliberate exception:
- Cancel is
GET—GET /workflows/{namespace}/{name}/cancel/{execution_id}. The intent is to make cancellation easy to trigger from a browser or curl one-liner without a request body. There is no POST or DELETE form. - Run mode is a path segment —
POST /workflows/{namespace}/{name}/run/{mode}. Valid modes aresync,async, andstream. Anything else returns 400.streamreturns SSE. - PUT vs PATCH —
PUTreplaces (PUT /schedules/{id}accepts a full update body).PATCHpartially updates (PATCH /admin/roles/{name},PATCH /admin/principals/{subject}).
SSE endpoints
Three endpoints return Server-Sent Events with media_type: text/event-stream:
POST /workflows/{ns}/{name}/run/stream— streamstask_started,task_completed, andworkflow_completedevents for a single execution.POST /workflows/{ns}/{name}/resume/{execution_id}/stream— same shape, for a resumed execution.GET /workers/{name}/connect— long-lived dispatch channel; the server pushesexecution_scheduled,execution_cancelled,execution_resumed, and periodicpingevents to the worker.
Worker health and metrics
Workers answer the SSE ping with POST /workers/{name}/pong, whose optional JSON body is {"healthy": bool, "metrics": {str: float}} (legacy workers send no body). A worker reporting healthy: false stays connected — running work finishes — but is excluded from new dispatch until it reports healthy again. GET /workers reflects both signals: each worker carries its latest advertised metrics snapshot, and status can be unhealthy in addition to online/offline. The metrics feed dynamic routing policies.
Versioning
The API itself has no version prefix in Flux 0.56.0. Workflow versioning happens at the catalog level: registering a workflow with the same namespace/name allocates a new integer version. Run a specific version with ?version=<n> on POST .../run/{mode}.
Rate limits
Flux 0.56.0 bakes in two narrow application-level rate limits: POST /auth/test-token is limited to 10 requests per minute per client, and POST /workers/register defaults to 30 requests per minute per client IP (tunable via [flux.workers] register_rate_limit; an empty string disables it). For everything else, rely on your reverse proxy or API gateway.
Health and metrics
GET /health— unauthenticated. Returns 200 when healthy and 503 when the database is unreachable; the JSON body carriesstatus,database, andversion. Status-code-only probes can rely on it.GET /ready— unauthenticated readiness probe. Separate from/healthso orchestrators can distinguish “remove from the load balancer” (readiness, e.g. a database blip) from “restart the process” (liveness).GET /metrics— Prometheus exposition, gated byadmin:metrics:read. Only registered when[flux.observability].prometheus_enabled = true.
OpenAPI
The FastAPI app exposes OpenAPI documents and Swagger UI automatically:
GET /docs— interactive Swagger UI.GET /openapi.json— machine-readable spec.
See OpenAPI spec for code-generation tips.