Docs · Workflows API
Workflows API
GraphQL stores the process. This API runs it.
A workflow is still a DataObject (schemaRef: "schema:workflow") — you can list it via GraphQL. Starting a run, collecting fields, invoking agents, pausing for humans, and sealing to a system of record happen here.
Ships today in Closure (session auth; public embed routes where enabled).
Lifecycle
POST /api/runs → collect / agent / human / gateway / wait …
→ POST /api/runs/{id}/advance (repeat)
→ end (+ Events audit)Hybrid graphs (parallel gateways, waits, orchestration teams) use the same advance loop — see Orchestration.
Try it here
This is the wf-lead-capture workflow from the sample DataObject below, running live — the same graph JSON rendered as an executable form. Submit it and you've driven the collect → advance loop this page documents.
Lead capture
live demo · wf-lead-capturePreview only — install the pack in Closure to run against your org.
Routes
| Route | Role |
|---|---|
GET/POST /api/workflows | List / register graphs |
GET /api/workflows/[id] | Fetch graph JSON |
POST /api/runs | Start a run |
POST /api/runs/submit | Start with collect fields |
POST /api/runs/[id]/advance | Advance one step |
GET /api/runs/[id] | Inspect run status + data |
GET /api/public/workflows/[id] | Published graph for embeds |
POST /api/public/runs/submit | Public collect (when enabled) |
Marketing demos may proxy under /api/closure/* — prefer Closure origin or your BFF in production.
Sample workflow DataObject
Same universe as GraphQL — process as data:
{
"@id": "urn:uuid:bbbbbbbb-bbbb-5bbb-8bbb-bbbbbbbbbbbb",
"schemaRef": "schema:workflow",
"name": "Lead capture",
"orgId": "org_demo",
"data": {
"workflowId": "wf-lead-capture",
"entryNodeId": "start",
"nodes": [
{ "id": "start", "kind": "start", "label": "Start" },
{
"id": "collect",
"kind": "collect",
"label": "Contact",
"meta": {
"fields": [
{ "name": "email", "type": "email", "required": true },
{ "name": "name", "type": "text", "required": true }
]
}
},
{
"id": "notify",
"kind": "integration",
"label": "Notify",
"meta": { "adapterId": "email.notify" }
},
{ "id": "end", "kind": "end", "label": "Done" }
],
"edges": [
{ "id": "e1", "from": "start", "to": "collect" },
{ "id": "e2", "from": "collect", "to": "notify" },
{ "id": "e3", "from": "notify", "to": "end" }
]
}
}Forms, chat, and agents are projections of this graph — not three products.
Start a run
curl -sS https://closureapps.com/console/api/runs/submit \
-H "Content-Type: application/json" \
-H "Cookie: <session>" \
-d '{
"workflowId": "wf-lead-capture",
"fields": { "email": "you@example.com", "name": "Ada" },
"policyPack": "open"
}'Typical response shape:
{
"runId": "run_…",
"status": "running",
"cursor": "notify",
"data": { "email": "you@example.com", "name": "Ada" }
}Advance
curl -sS https://closureapps.com/console/api/runs/run_…/advance \
-H "Content-Type: application/json" \
-H "Cookie: <session>" \
-d '{ "actor": "ops@acme.com" }'Useful body fields by node kind:
| Situation | Body |
|---|---|
| Collect | { "fields": { … } } |
| Decision / loop | { "branch": "pass" } or { "autoLoop": true } |
| Human / policy | { "actor": "user@org" } |
| Wait resume | { "resumeWait": true, "signal": "docs.received" } |
| Boundary timeout | { "fireBoundary": "timeout" } |
| Cancel + compensate | { "cancel": true } |
Public embeds
GET /api/public/workflows/wf-lead-capture
POST /api/public/runs/submitThin hosts and Experience Packs use these for collect → seal without console chrome. Package with @closure-platform/client — SDK.
Read vs run
| Need | API |
|---|---|
| List / edit workflow graphs as DataObjects | GraphQL objects(schemaRef: "schema:workflow") |
| Execute a journey | This page — /api/runs* |
| Author hybrid BPM × agents | Orchestration · Closure canvas |
Roadmap
- Scoped public API keys
- Webhook trigger catalog parity per connector