Workflow API
The Workflow API manages Automation definitions, immutable published versions, and queued Runs. Use it when a service needs to provision or invoke repeatable evidence workflows wit
Base URL:
https://api.provon.dev/v1Public routes use a project API key. The key selects the project:
Authorization: Bearer <PROVON_API_KEY>
Content-Type: application/json| Capability | Access |
|---|---|
workflows:read |
List and read definitions, versions, Runs, and Step Runs |
workflows:write |
Create, update, delete, publish, invoke, and control Runs |
The default project key includes workflows:read, not workflows:write.
Route Forms#
Every route has two forms:
| Caller | Form |
|---|---|
| Project API key | /v1/workflows/... |
| Signed-in Workbench client | /v1/projects/:projectId/workflows/... |
The same rule applies to /workflow-runs. Public integrations should use the shorter API-key form
and must not mix a path project ID with a key from another project.
Endpoints#
Definitions#
| Method | Path | Purpose |
|---|---|---|
GET |
/workflows |
List workflow definitions |
POST |
/workflows |
Create an editable definition |
GET |
/workflows/:id |
Read a definition and published versions |
PATCH |
/workflows/:id |
Update the editable definition |
DELETE |
/workflows/:id |
Delete a definition |
POST |
/workflows/:id/publish |
Validate and publish a new version |
POST |
/workflows/:id/runs |
Queue a manual Run |
Runs#
| Method | Path | Purpose |
|---|---|---|
GET |
/workflow-runs |
List Runs |
GET |
/workflow-runs/:id |
Read a Run with its definition and steps |
POST |
/workflow-runs/:id/cancel |
Cancel queued or running work |
POST |
/workflow-runs/:id/retry |
Requeue failed, dead-letter, or cancelled work |
POST |
/workflow-runs/:id/resume |
Resume queued or failed work |
Paths in the tables are relative to https://api.provon.dev/v1.
Definition Model#
A workflow definition contains:
{
"id": "workflow_01J...",
"name": "Review a risky run",
"description": "Create a Finding from reviewed manual input.",
"status": "draft",
"graph": {
"nodes": [],
"edges": []
},
"owner": "Reliability",
"activeVersionId": null,
"createdAt": 1760000000000,
"updatedAt": 1760000000000,
"publishedAt": null
}Status is draft, active, paused, or archived. The editable graph is not executed directly.
Publishing snapshots it into an immutable version and sets activeVersionId.
Each graph node requires:
| Field | Purpose |
|---|---|
id |
Unique node ID inside the graph |
kind |
trigger, control, or operation |
op |
Implemented operation identifier |
label |
Human-readable label |
description |
Optional explanation |
params |
Operation-specific configuration |
Each edge requires id, source, and target. Branching edges also carry a typed branch such as
true, false, case, default, success, or failure.
See Automations for supported trigger and operation families. The Workbench builder is the recommended way to discover operation parameters; the API graph is the persisted contract, not a second user-facing workflow language.
Create A Workflow#
This minimal draft accepts manual input and creates a Finding:
POST /v1/workflows{
"name": "Manual risk review",
"description": "Create a Finding from an explicit invocation.",
"status": "draft",
"owner": "Reliability",
"graph": {
"nodes": [
{
"id": "manual",
"kind": "trigger",
"op": "trigger.manual",
"label": "Manual",
"params": {
"inputSchema": "{\"fields\":[{\"key\":\"summary\",\"label\":\"Summary\",\"type\":\"text\",\"required\":true}],\"allowExtraFields\":false}"
}
},
{
"id": "finding",
"kind": "operation",
"op": "diagnostics.finding.create",
"label": "Create a finding",
"params": {
"title": "Manual review: {{input.summary}}",
"severity": "medium",
"summary": "{{input.summary}}"
}
}
],
"edges": [
{
"id": "manual-to-finding",
"source": "manual",
"target": "finding"
}
]
}
}Successful creation returns 201:
{
"workflow": {
"id": "workflow_01J...",
"name": "Manual risk review",
"status": "draft"
}
}Client-supplied workflow IDs are ignored. Names must be unique inside the project.
Update And Publish#
PATCH /workflows/:id accepts any non-empty subset of:
{
"name": "Manual incident review",
"description": "Updated purpose",
"status": "paused",
"owner": "Agent platform",
"graph": {
"nodes": [],
"edges": []
}
}Publish after the draft graph is complete:
POST /v1/workflows/workflow_01J.../publishPublishing validates:
- graph structure and node IDs;
- trigger count and edge topology;
- required operation parameters;
- artifact compatibility between connected nodes;
- runtime support for every operation.
An invalid graph returns 400 with error: "invalid_workflow_graph" and an issues array. A
runtime that cannot report its workflow capabilities returns 503 with
error: "workflow_runtime_unavailable".
Queue A Manual Run#
POST /v1/workflows/workflow_01J.../runs
Idempotency-Key: incident-1842-review{
"input": {
"summary": "The agent claimed success after the refund tool returned HTTP 400."
}
}The API validates manual input against the trigger's input schema and enqueues execution. It does
not execute the graph inside the HTTP request. Successful enqueue returns 201 with the Run detail.
Use a stable Idempotency-Key for retried client requests. The key is scoped to the manual workflow
invocation and is stored as a stable trigger reference.
List Definitions#
GET /v1/workflows?status=active&limit=50Query parameters:
| Parameter | Values |
|---|---|
status |
draft, active, paused, or archived |
limit |
Positive integer page size |
cursor |
Opaque pagination.nextCursor |
List items omit the complete graph and add nodeCount, runCount, and triggerOp. Read one
definition when graph or version detail is required.
List And Inspect Runs#
GET /v1/workflow-runs?workflowId=workflow_01J...&status=failed&limit=50Run filters:
| Parameter | Values |
|---|---|
workflowId |
One workflow ID |
status |
queued, running, completed, failed, dead_letter, or cancelled |
limit |
Positive integer page size |
cursor |
Opaque pagination.nextCursor |
GET /workflow-runs/:id returns:
- the complete Run, including input and output;
- the current workflow definition when it still exists;
- the immutable version used by the Run;
- ordered Step Runs with node operation, attempts, input, output, and error.
Run Control#
| Action | Allowed source statuses | Result |
|---|---|---|
| Cancel | queued, running |
Run becomes cancelled |
| Retry | failed, dead_letter, cancelled |
Run is requeued with more attempts |
| Resume | queued, failed |
Existing Run is made runnable |
Invalid transitions return 409. Retry or resume only after correcting the dependency that caused
the failure; otherwise the same side effect can fail again.
Pagination#
Definition and Run lists return:
{
"pagination": {
"limit": 50,
"nextCursor": "1760000000000\tworkflow_01J..."
}
}Pass nextCursor unchanged. Do not parse it or derive a new cursor from timestamps.
Errors#
| Status | Meaning |
|---|---|
400 |
Invalid JSON, graph, field, cursor, or manual Run input |
401 |
Public route did not receive a valid project API key |
403 |
API key lacks workflows:read or workflows:write |
404 |
Workflow, version, or Run was not found in the project |
409 |
Name conflict, inactive workflow, or invalid transition |
503 |
Queue or workflow runtime capability service unavailable |
504 |
A workflow node timed out |
Workflow-domain errors generally return a short machine-readable error string and optional
message. Authentication errors use the shared structured API error body.