> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbitforms.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflows API

> Build, publish, run and inspect workflows from code or an AI agent: the node catalogue, graphs of nodes and edges, activation, runs and AI agent templates.

A workflow is a graph: one trigger node (a form submission, a contact added, a deal stage change, a meeting booked…) connected to action nodes (create a deal or task, add a note, update the contact, run an AI agent, send to an integration) through filters, routers and delays. The same engine, validators and plan rules as the editor apply, so a graph an agent builds is held to the same standard as one drawn by hand. The [MCP server](https://docs.orbitforms.ai/mcp/tools.md) exposes the same operations as tools.

> [!NOTE]
>
> **Start with the schema.** `GET /api/v1/workflows/schema` returns every trigger and node type with its provider, the config fields each needs, the outputs it exposes to later nodes, plan requirements and the graph rules.

## Scopes

| Scope | Allows |
| - | - |
| `workflows:read` | Read workflows, runs and AI agent templates |
| `workflows:write` | Create, update, activate, pause and run workflows; manage AI agent templates. Active and running workflows carry out their steps, which can email people, enroll contacts in sequences, change CRM records and send data to connected apps and webhooks |
| `workflows:delete` | Delete workflows and AI agent templates |

## Endpoints

| Method | Endpoint | Description |
| - | - | - |
| `GET` | `/api/v1/workflows/schema` | Node catalogue and graph rules |
| `GET` | `/api/v1/workflows` | List (`status`, `search`, `page`, `per_page`) with trigger, node and run counts |
| `POST` | `/api/v1/workflows` | Create a draft: `{ name, description?, trigger_config?, nodes?, edges? }` |
| `GET` | `/api/v1/workflows/:id` | The workflow with its nodes, edges and `has_unpublished_changes` |
| `PATCH` | `/api/v1/workflows/:id` | Change name, description, trigger config, nodes and edges (saved as a draft), or `status` |
| `DELETE` | `/api/v1/workflows/:id` | Delete the workflow and its runs |
| `POST` | `/api/v1/workflows/:id/run` | Run now: `{ contact_ids, idempotency_key? }` or `{ trigger_data }`; both run in the background (202) |
| `GET` | `/api/v1/workflows/:id/runs` | Runs, newest first (`status`) |
| `GET` | `/api/v1/workflows/runs/:runId` | One run with every node step, input, output and timing |
| `GET` / `POST` | `/api/v1/agent-templates` | AI agent templates (instructions, criteria, model) the team owns plus shared ones / create |
| `PATCH` / `DELETE` | `/api/v1/agent-templates/:id` | Change or delete a template the team owns |

## Building a graph

Nodes may carry a `key` of your choosing so edges can reference them before they have ids; ids are assigned on save. `trigger_config` mirrors the trigger node (`{ provider, form_id }` for form triggers) and is derived from it when omitted.

```bash theme={null}
curl -X POST https://orbitforms.ai/api/v1/workflows \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Demo requests → pipeline",
    "nodes": [
      { "key": "trigger", "type": "trigger", "provider": "form", "config": { "form_id": "FORM_ID" } },
      { "key": "deal", "type": "automation", "provider": "create_deal", "config": { "pipeline_id": "PIPELINE_ID", "stage_id": "STAGE_ID", "name_template": "{{company}} demo" } },
      { "key": "task", "type": "automation", "provider": "create_task", "config": { "title_template": "Call {{first_name}}", "due_in_days": 1, "assignee_mode": "contact_owner" } }
    ],
    "edges": [
      { "source_node_id": "trigger", "target_node_id": "deal" },
      { "source_node_id": "deal", "target_node_id": "task" }
    ]
  }'
```

## Publishing, pausing, resuming

A workflow is created as a **draft**. `PATCH` with `{ "status": "active" }` validates the graph (missing config, unconnected nodes, plan limits), publishes it and starts running it on its trigger; the response carries the validation problems when it is not ready. Edits to an active workflow are saved as a draft (`has_unpublished_changes: true`) until `status: "active"` is sent again. `{ "status": "paused" }` stops new runs; sending `"active"` again resumes it, and `process_queue` (`all`, `skip`, `none`) says what happens to submissions queued while it was paused.

Pass `expected_updated_at` (the `updated_at` you last read) with a `PATCH` to have the save refused with `409 conflict` when someone changed the workflow meanwhile.

## Running

`POST /api/v1/workflows/:id/run` with `contact_ids` starts one run per contact (the trigger must be Contact Added or Form Submission); the same `contact_ids` with the same `idempotency_key` never run twice. With `trigger_data` the workflow runs once with that data; the response carries a `trigger_key`, and `GET /api/v1/workflows/:id/runs?trigger_key=...` finds that run. Both respond `202`: runs execute in the background, so poll the run for its status and per-node steps. Runs can send email, call integrations and change CRM data.

> **[CRM API](https://docs.orbitforms.ai/developers/api/crm.md)**
>
> The objects workflows create and update

> **[MCP tools](https://docs.orbitforms.ai/mcp/tools.md)**
>
> The same operations as MCP tools


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.