The HTTP API¶
Everything the browser does, the API does first. The dashboard is a generated client of this schema, not a privileged path into the engine — so anything you can click, you can script.
Base URL: https://api.${DOMAIN}/api/v1, or http://127.0.0.1:8000/api/v1 for
a fluksio serve installation.
Authenticating¶
export TOKEN=$(curl -s -X POST $FLUKSIO/login/access-token \
-d "username=admin@example.com&password=..." | jq -r .access_token)
curl -s $FLUKSIO/users/me -H "Authorization: Bearer $TOKEN"
A bearer token, valid for eight days. POST /login/test-token checks one.
Password recovery and reset are POST /password-recovery/{email} and
POST /reset-password/.
Agents authenticate differently — see Agents over MCP.
The interactive schema
When ENVIRONMENT is not production, the full OpenAPI schema is at
/docs (Swagger) and /redoc, and the raw document at
/api/v1/openapi.json. That is the authoritative reference; this page is
the tour.
It is closed in production on purpose: the schema enumerates every endpoint the installation serves, including the paths webhook nodes mounted at runtime.
Flows¶
| Method | Path | What |
|---|---|---|
GET |
/flows/ |
every flow, with node counts, draft and running state |
GET |
/flows/{name} |
one flow — the draft if there is one — with node status and issues |
PUT |
/flows/{name} |
save a draft (version must match, or 409) |
POST |
/flows/{name}/publish |
put the draft live |
POST |
/flows/{name}/discard-draft |
throw the draft away |
POST |
/flows/{name}/rename |
rename it |
DELETE |
/flows/{name} |
delete it |
GET |
/flows/node-types |
every node type and its parameter schema |
GET |
/flows/graph |
every flow as one graph — what Home draws |
Reading a flow returns the draft when one exists, along with a preview of how it would run: node statuses and validation issues for the version you are editing, not the one running underneath it.
Node source¶
curl -s $FLUKSIO/flows/house/nodes/decide/source -H "Authorization: Bearer $TOKEN"
curl -X PUT $FLUKSIO/flows/house/nodes/decide/source -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"code": "def process(x):\n return {\"y\": x * 2}\n"}'
POST .../share promotes a node's source to the shared library;
POST .../unshare gives it a private copy back. GET /flows/library lists the
shared sources and which flows use each.
Running and controlling¶
| Method | Path | What |
|---|---|---|
POST |
/flows/{name}/start · /stop |
activate or tear down its subscriptions and schedules |
POST |
/flows/{name}/pause · /resume |
hold messages instead of running them |
POST |
/flows/{name}/step |
release exactly one held message |
POST |
/flows/{name}/validate |
the issues, without saving |
POST |
/flows/{name}/run |
run every node once, from the values you pass |
POST |
/flows/{name}/nodes/{id}/trigger |
feed values into one node |
POST |
/flows/{name}/nodes/{id}/cancel |
kill the worker running it right now |
POST |
/flows/{name}/nodes/{id}/acknowledge |
clear the failure the canvas is marking |
POST /flows/{name}/run on a batch flow submits a run instead, because
that is what running one means — the parameters, the series and the result are
the point, and a call that quietly did something else would be a trap.
Messages¶
curl -s $FLUKSIO/messages/ -H "Authorization: Bearer $TOKEN"
curl -X POST $FLUKSIO/messages/house.setpoint -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"value": 22.5}'
curl -s $FLUKSIO/messages/house.temperature/history -H "Authorization: Bearer $TOKEN"
GET /messages/ is the catalogue: every message any published flow declares,
with its last value. Publishing puts a value into the graph exactly as a
dashboard control does — which means only a message some flow declares can be
published to. Flows own the namespace; everything else is a client of it.
Runs¶
| Method | Path | What |
|---|---|---|
POST |
/runs/flows/{name} |
queue one run — {"params": {...}, "seed": 7, "draft": false} |
POST |
/runs/flows/{name}/sweep |
queue many, sharing a group_id |
GET |
/runs |
the queryable history: ?flow=, ?status=, ?group=, ?digest=, ?limit= |
GET |
/runs/{id} |
one run in full: params, result, per-node record, artifacts |
POST |
/runs/{id}/cancel |
stop it |
GET |
/runs/{id}/metrics?name=&stride= |
one metric's series, in step order |
GET |
/runs/series/compare?ids=a,b,c&metric= |
that metric across several runs |
Submitting answers immediately with a queued run. Wrong parameters — an
undeclared name, a value of the wrong type — come back as a 422 naming the
problem, before anything executes.
?digest= filters by the hash of the parameters, which is how you find "every
run that used exactly this configuration".
compare answers in the same shape a chart widget draws, so three training
curves side by side is a widget binding rather than a screen of its own.
See Runs: pipelines that finish.
Artifacts¶
curl -X PUT $FLUKSIO/artifacts -H "Authorization: Bearer $TOKEN" \
--data-binary @model.pt
curl -s $FLUKSIO/artifacts/sha256:abc... -H "Authorization: Bearer $TOKEN" -o model.pt
Content-addressed, so uploading the same bytes twice stores them once. Node
code normally reaches these through fluksio.save_artifact /
fluksio.load_artifact rather than here.
Dashboards and panels¶
| Method | Path | What |
|---|---|---|
GET |
/dashboards/ |
every dashboard, without its contents |
GET |
/dashboards/{name}?draft=true |
the published document, or the editor's copy |
POST |
/dashboards/{name} |
create one |
PUT |
/dashboards/{name} |
save a draft |
POST |
/dashboards/{name}/publish · /discard · /rename |
|
GET PUT |
/panels/ |
which device shows which dashboards |
POST |
/panels/pair |
start a pairing |
GET |
/panels/pair/{code} |
what is holding a code |
Secrets, modules, alerts¶
curl -s $FLUKSIO/secrets/ -H "Authorization: Bearer $TOKEN" # names only
curl -X PUT $FLUKSIO/secrets/influx-token -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"value": "..."}'
curl -s $FLUKSIO/modules/ -H "Authorization: Bearer $TOKEN"
curl -X POST $FLUKSIO/modules/apply -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"requirements": "numpy>=2\n"}'
curl -s $FLUKSIO/alerts/config -H "Authorization: Bearer $TOKEN"
curl -X POST $FLUKSIO/alerts/test/my-phone -H "Authorization: Bearer $TOKEN"
Secrets are write-only over the API: you can list names and set values, never read one back.
Observability¶
| Path | What |
|---|---|
/observability/summary |
engine health — always 200, degraded or not |
/observability/timeseries |
executions and failures over a window |
/observability/flows |
per-flow rollups with a 60-slice trend |
/observability/runs |
recent cascades, with ?flow=, ?since=, ?until= |
/observability/events?kind=failure\|audit |
what went wrong, or who changed what |
/observability/dead-letter |
work the engine gave up on |
GET /utils/health/ is the deep health check the container probe uses: it
fails when the event loop is wedged or the state backend is gone, not just when
the process is dead.
Workers¶
| Method | Path | What |
|---|---|---|
GET |
/workers |
what is attached, its labels and how busy it is |
POST |
/workers/tokens |
mint a worker credential (superuser; shown once) |
GET |
/workers/runtime |
the node runner's source, for a host without pip |
WS |
/workers/attach |
where a worker dials in |
See Remote workers.
Live events¶
The websocket authenticates from its query string. It sends a snapshot on connect and then every engine event: node executions, values published, health changes, run started and finished. This is what the canvas and the dashboards draw from.
Errors¶
| Code | Means |
|---|---|
400 |
the request was malformed, or the node refused it with a message |
401 / 403 |
not signed in, or not allowed |
404 |
no such flow, dashboard, run or message |
409 |
someone else saved first — the body carries current_version |
422 |
a parameter, port or binding did not typecheck |
503 |
that subsystem is not available on this installation |
A 409 on a save or a publish is not an error to retry blindly: it means the stored version moved past the one you were editing. Re-read, merge, save again.
Generating a client¶
The frontend's TypeScript client is generated from the OpenAPI schema
(make generate-client). Any OpenAPI generator will do the same for your
language — point it at /api/v1/openapi.json on a non-production installation.