HTTP API
All routes are tenant-scoped via the four CPET headers (X-Customer, X-Product, X-Env, X-Tenant) and require a Bearer token. A CPET that resolves to no configured tenant returns 400.
Running workflows
Section titled “Running workflows”| Method | Path | Purpose |
|---|---|---|
| POST | /workflow/start | Start a run |
| POST | /workflow/signal | Deliver a named signal to a waiting instance |
| POST | /workflow/resume | Resume a specific node — {instanceid, node, data} |
| POST | /workflow/event | Resume by event id — {instanceid, event, data} |
| POST | /workflow/cancel | Cancel a run — {instanceid} |
| GET | /workflow/status?instanceid= | Current instance status |
| GET | /workflow/logs?instanceid= | Merged, time-sorted instance + node event log |
| GET | /workflow/config?id=|name=|path= | A definition’s type and declared variables. Accepts an API key or a Bearer token |
Starting a run
Section titled “Starting a run”curl -X POST https://<host>/workflow/start \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -H "X-Customer: acme" -H "X-Product: shop" -H "X-Env: prod" -H "X-Tenant: eu" \ -d '{"workflowname":"order-approval","context":{"order_id":"1234"}}'Identify the definition with exactly one of:
| Field | Meaning |
|---|---|
workflowid | Definition id |
workflowname | Definition name |
workflowpath | Definition path — fetched from meta if not already loaded |
workflow | A full inline definition, registered on the fly |
Other fields:
| Field | Type | Purpose |
|---|---|---|
context | object | Run variables, available to tasks as {{var}} |
starttask | string | Override the first node |
tasklist | string[] | Restrict execution to a subset of tasks |
selectors | object | Per-task agent requirements, e.g. {"train": {"tag": "gpu"}} |
workertag / tag, model | string | Agent routing shorthands |
workerid | string[] | Pin to specific agents |
workerids | object | Per-task agent map |
workerdomain | string | Resolve an agent by infrastructure address |
affinity | string | none / single-agent / instance / definition / payload |
affinity-key | string[] | Payload fields for payload-scoped affinity |
pin-agent | bool | Shorthand for affinity: single-agent |
restart-on-failure | bool | Restart rather than resume when an agent dies |
Query ?user=true injects the caller’s identity into task context.
Responses:
// 200 — dispatched{ "message": "...", "instanceid": "01K…", "status": "executing", "workflowid": "…" }
// 202 — accepted but queued (no agent free); same shape, status "queued"{ "message": "...", "instanceid": "01K…", "status": "queued", "workflowid": "…" }Failure responses:
| Status | Meaning | Header |
|---|---|---|
503 | No agent is currently free | Retry-After: 5 |
429 | The overflow queue is full | Retry-After: 10 |
400 | No agent matches the requested selectors, or the definition/tenant is invalid | — |
503 and 429 are both retryable — the run was not started. 400 on selectors means no agent in the fleet can ever satisfy them, so retrying won’t help.
Signalling a waiting instance
Section titled “Signalling a waiting instance”curl -X POST https://<host>/workflow/signal \ -H "Authorization: Bearer $TOKEN" $H \ -d '{"instanceid":"01K…","signal_name":"approved","data":{"approver_name":"Dana"}}'The signal name must match an event declared on the Wait node, and any fields that event lists under required must be present. Response: {"success": true}.
Inspecting
Section titled “Inspecting”| Method | Path | Returns |
|---|---|---|
| GET | /agents | Agents serving this tenant: {agents:[{id, version, status, type, domain, grpcaddress, httpaddress, healthy, tags?, capabilities?}]} |
| GET | /workflow/queue | This tenant’s queued work: {total_pending, items[]} |
| DELETE | /workflow/queue/:id | Cancel one queued item. 403 if it belongs to another tenant, 404 if unknown |
Superadmin plane
Section titled “Superadmin plane”Requires a control-plane token. These are cross-tenant.
| Method | Path | Returns |
|---|---|---|
| GET | /admin/agents?tenant= | All agents, with tenants[], exclusive, max_concurrent_tasks |
| GET | /admin/agents/:id | One agent including full metadata |
| GET | /admin/queue?tenant=&status= | Queue across tenants, plus pending_by_tenant |
| DELETE | /admin/queue/:id | Cancel any queued item, bypassing the tenant check |
| GET | /admin/instances?tenant= | Instances grouped by tenant |
Data surfaces
Section titled “Data surfaces”Mounted at clean paths: /rest/* (entity CRUD), /schema/* (including openapi.json, jsonschema, graphql, cue, zod), /admin/data/* (migration plans, seeds, retention, locks), and /superadmin/tenant/*. Applying a plan, retention, and lock force-release all require superadmin.
Health
Section titled “Health”GET /health and GET /ready — unauthenticated, no CPET headers required.