#API reference
Generated from the live API’s OpenAPI spec — every field below is enforced by the route’s zod schema, so this reference cannot drift. All requests are authenticated with Authorization: Bearer <api-key>. Base URL: https://flowplane-api.do.demo.thebuildmill.com.
Try requests interactively in the API explorer, or grab the machine-readable /openapi.json for Postman / Insomnia / codegen — it carries the full nested schemas (e.g. the policy route / surface shapes) that the tables below summarize.
#Approvers
#POST /v1/approvers/
Register an approver
Admin-initiated registration. Creates a person with declared channels/methods; email/inbox are auto-verified, the rest land pending until the approver self-verifies. Idempotent per (org, email).
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | |
name | string | no | |
clerkUserId | string | no | |
channels | object[] | no | |
methods | object[] | no |
#GET /v1/approvers/
List approvers
All approver identities for the org, with channel + method verification state.
#GET /v1/approvers/{id}
Get an approver
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
#POST /v1/approvers/{id}/verify
Verify an approver capability
Self-serve completion: mark a declared channel or surface verified (or failed), persisting the proven endpoint/ref. Real per-channel proof (OTP, Slack lookup, DocuSign mapping) plugs in here.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
channel | email | slack | discord | phone | sms | webhook | no | |
surface | inbox | slack | discord | docusign | email | api | no | |
endpoint | string | no | |
resolvedRef | string | no | |
status | verified | failed | no |
#POST /v1/approvers/{id}/disable
Disable an approver
Soft-disable. The approver stops binding any surface and is never routed a decision. Policies naming them still resolve, but report as unsatisfiable — returned in warnings. Reversible via /enable. Idempotent.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
#POST /v1/approvers/{id}/enable
Re-enable a disabled approver
Clears the disable. Registration deliberately does not do this — bringing someone back is an explicit act. Idempotent.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
#Decisions
#GET /v1/decisions/
List decisions (reviewer inbox)
List decisions for the org, newest first. Filter by status and assignee email for the reviewer inbox.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
status | query | no | PENDING | APPROVED | REJECTED | EXPIRED | CANCELLED |
assignee | query | no | string |
limit | query | no | integer |
offset | query | no | integer |
#GET /v1/decisions/{id}
Get a decision with its quorum tally
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
#PUT /v1/decisions/{id}/output
Save the reviewer’s refined draft (conversational refinement)
Persist an edited version of a refinable decision’s proposed output. On approve, the engine resumes with the refined draft (refinedOutput ?? proposedOutput). Only allowed while the decision is PENDING and carries a proposedOutput.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
title | string | no | |
format | text | markdown | no | |
content | string | yes |
#POST /v1/decisions/{id}/refine
Refine the draft with the org’s own model (BYO)
Apply the reviewer’s feedback to the current draft using the org’s configured LLM (Settings → Refine with AI). Returns the revised draft and appends the turn to the refinement log. Does not commit — the reviewer saves via PUT /output, then approves.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
feedback | string | yes |
#POST /v1/decisions/{id}/decide
Approve or reject a decision
Record a vote. Under quorum the decision resolves only when the approval/rejection threshold is met; reject-wins by default. On resolution Flowplane fires the engine resume event.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
decision | approve | reject | yes | |
note | string | no | |
responseValue | one of | no |
#Directory
#GET /v1/directory/actor
Resolve an internal actor id to a display label
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
ref | query | yes | string |
#Notifications
#GET /v1/notification-rules/
Get my notification rules (ladder)
#PUT /v1/notification-rules/
Replace my notification rules
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
rules | object[] | yes |
#GET /v1/contact-methods/
Get my contact methods
#PUT /v1/contact-methods/
Update my contact methods
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
email | string | no | |
sms | string | no | |
slack | string | no | |
pushEnabled | boolean | no |
#POST /v1/push-devices/
Register this device for push
Idempotent on (user, token) — safe to call on every launch, which the client should do because push tokens rotate on reinstall and restore. Re-registering a revoked device reactivates it.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
token | string | yes | |
platform | ios | android | yes | |
deviceName | string | no |
#GET /v1/push-devices/
List my registered devices
#DELETE /v1/push-devices/{id}
Revoke one of my devices
Soft-revoke. Call on sign-out, otherwise the next person to sign in on that handset keeps receiving the previous user’s notifications.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
#Policies
#GET /v1/policies/
List approval policies
All named approval policies for the org.
#POST /v1/policies/
Create (or upsert) an approval policy
Create a named org-scoped approval policy: a mandatory floor plus defaults for surface, route, approver group, and quorum. Idempotent upsert keyed by (org, name). Rejects unsatisfiable policies with 422.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
floor | object[] | no | |
defaults | object | no |
#GET /v1/policies/{name}
Get an approval policy
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
name | path | yes | string |
#PUT /v1/policies/{name}
Update an approval policy
Replace an existing policy’s floor + defaults. 404 if it does not exist. Rejects unsatisfiable policies with 422.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
name | path | yes | string |
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
floor | object[] | no | |
defaults | object | no |
#DELETE /v1/policies/{name}
Delete an approval policy
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
name | path | yes | string |
#Runs
#POST /v1/runs/
Trigger a workflow run
Fire the external engine event for a registered workflow. Flowplane seeds no run/step rows — the engine owns execution; Flowplane tracks the decisions requested on the run.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
workflowId | string | yes | |
input | object | no | |
idempotencyKey | string | no | |
timeoutSec | integer | no |
#Worker
#POST /v1/worker/register
Register (upsert) a workflow definition
SDK/worker self-registration. Idempotent upsert keyed by workflow id for the API key’s org.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | |
name | string | no | |
version | integer | no | |
engine | bundled | inngest | temporal | trigger | no | |
steps | object[] | yes |
#POST /v1/worker/decisions
Open a HITL decision (decision-first model)
Called by an engine adapter (e.g. flowplane.awaitApproval) to request a human decision for an external-engine run. The policy gate may resolve "not required", in which case approvalNeeded=false and no decision is created.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
engine | bundled | inngest | temporal | trigger | mcp | no | |
externalRunId | string | yes | |
stepRef | string | yes | |
workflowRef | string | no | |
assigneeEmail | string | no | |
policy | string | no | |
required | boolean | no | |
context | object | no | |
proposedOutput | object | no | |
responseSpec | one of | no | |
timeoutSec | integer | no |
#GET /v1/worker/decisions
List decisions (API-key scope) — the agent's inbox
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
status | query | no | PENDING | APPROVED | REJECTED | EXPIRED | CANCELLED |
limit | query | no | integer |
#GET /v1/worker/decisions/{id}
Get a decision status (API-key scope) — poll a park-and-resume verdict
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
#POST /v1/worker/decisions/{id}/cancel
Cancel a pending decision (API-key scope)
Withdraw a decision the agent no longer needs. Only PENDING decisions cancel; an already-resolved one returns cancelled=false with its current status.
Parameters:
| Param | In | Required | Type |
|---|---|---|---|
id | path | yes | string |
#POST /v1/worker/policies
Upsert a named approval policy
Declare an org-scoped approval policy: a mandatory floor (when a human is required) plus defaults for assignee, approver group, and quorum. Idempotent upsert keyed by (org, name).
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
floor | object[] | no | |
defaults | object | no |