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

# Workflows and tasks

> Read and run workflows, follow their runs, and manage tasks and app records.

A workflow is a graph of steps that starts on a signal, on a schedule or on a person's request. A run is one
execution of a workflow. A task is a piece of work for a person or an agent. Every call uses the token of a member
and shows only what that member may see.

## Workflows

A member sees a workflow when it is shared with the workspace, when the member owns it, or when it is shared with the
member or a department. A member who may edit every agent sees all of them. A call that changes a workflow returns
`403` with `You cannot change this workflow.` when the role does not allow it.

| Task | Call |
| - | - |
| List workflows. Add `?active=1` for the switched-on ones. | `GET /api/v1/workflows` |
| Read a page of workflows. Filters: `show` (`agents` or `apps`), `state` (`on` or `off`), `q`. Sorts: `name`, `state`, `updated`. | `GET /api/v1/workflows/table` |
| Create a workflow. | `POST /api/v1/workflows` |
| Read one, with its `problems`. | `GET /api/v1/workflows/{workflow_id}` |
| Change one. | `PATCH /api/v1/workflows/{workflow_id}` |
| Archive one. It is switched off and kept with its runs. | `DELETE /api/v1/workflows/{workflow_id}` |
| Read its saved versions, newest first. | `GET /api/v1/workflows/{workflow_id}/versions` |
| Check the graph. | `POST /api/v1/workflows/{workflow_id}/validate` |
| Run it now. | `POST /api/v1/workflows/{workflow_id}/run` |
| Read or change who sees it. | `GET`, `POST /api/v1/workflows/{workflow_id}/sharing` |
| Read the step types, signals and tools a graph can use. Add `?q=` to narrow it. | `GET /api/v1/workflows/palette` |
| Read the library of templates, one template, and make your own workflow from it. | `GET /api/v1/workflows/templates`, `GET /api/v1/workflows/templates/{slug}`, `POST /api/v1/workflows/templates/{slug}/use` |

### Create a workflow

```bash theme={null}
curl -X POST https://api.impellabs.tech/api/v1/workflows \
  -H "Authorization: Bearer imp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Welcome a new lead",
    "description": "Starts when a form comes in.",
    "graph": {
      "nodes": [
        {"id": "start", "type": "trigger", "data": {"on": "signal", "signal": "lead.submitted"}},
        {"id": "finish", "type": "end", "data": {"resolution": "welcomed"}}
      ],
      "edges": [{"source": "start", "target": "finish"}]
    }
  }'
```

The reply is the workflow, with status `201`. It carries `id`, `name`, `slug`, `description`, `graph`, `is_active`,
`trigger_signal`, `version`, `summary`, `starts`, `steps`, `owner_id`, `can_edit`, `sharing`, `problems` and the
times. A new workflow is off.

* `name` is required, up to 255 characters. `graph` is required on create.
* A `graph` has `nodes` and `edges`. A node has `id`, `type`, `data` and an optional `position`. An edge has
  `source`, `target` and an optional `sourceHandle`.
* The graph has one `trigger` step. Its `on` is `signal`, `schedule` or `manual`. The step types, the settings of
  each one and the signals you can start on come from `GET /api/v1/workflows/palette`. The signal names are the
  [event types](https://docs.impellabs.tech/api/events.md).
* A changed graph is saved as the next numbered version. `is_active` must be `true` or `false`. A workflow with problems cannot be
  switched on. The call returns `400` with `detail` and a list of `problems`, each `{node_id, message}`.

### Run a workflow

```bash theme={null}
curl -X POST https://api.impellabs.tech/api/v1/workflows/WORKFLOW_ID/run \
  -H "Authorization: Bearer imp_..." \
  -H "Content-Type: application/json" \
  -d '{"input": {"note": "Started from my system"}, "test": false}'
```

The body takes `input` (an object), `agent_id` and `test`. A live run needs the workflow on: otherwise the call
returns `409` with `This workflow is switched off.` A workflow with problems returns `400`. The reply is the run, with
status `201`.

## Runs

| Task | Call |
| - | - |
| List runs. Filters: `workflow`, `status`, `agent`. | `GET /api/v1/workflows/executions` |
| Read one run, with its steps, context and transcript. | `GET /api/v1/workflows/executions/{execution_id}` |
| Stop a run. | `POST /api/v1/workflows/executions/{execution_id}/cancel` |
| Start the same run again on the workflow as it is now. The old run stops and stays. | `POST /api/v1/workflows/executions/{execution_id}/rerun` |
| Answer the approval card a run waits on. Body: `{"approved": true, "note": "..."}`. | `POST /api/v1/workflows/executions/{execution_id}/decide` |

A run has `id`, `workflow`, `workflow_name`, `version`, `agent_id`, `test`, `status`, `current_node_id`,
`step_count`, `wake_at`, `wait_kind`, `resolution` and `last_error`. A test run belongs to the person who started it.
Stopping a run that already ended returns `409`. `decide` returns `409` when the run does not wait for an approval,
and only the person the card names can answer it.

## Tasks

A task has a title, notes, an assignee (a person or an agent), a due time, a reminder, a priority, a status, a
board stage, a list, labels, a checklist and links to a conversation, a contact or an app record.

```bash theme={null}
curl -X POST https://api.impellabs.tech/api/v1/tasks \
  -H "Authorization: Bearer imp_..." \
  -H "Content-Type: application/json" \
  -d '{"title": "Call Sam about the offer", "due_at": "2026-11-03T17:00:00+04:00", "priority": "high"}'
```

```json theme={null}
{
  "id": "…",
  "title": "Call Sam about the offer",
  "notes": "",
  "kind": "",
  "assignee": {"type": "member", "id": "…", "name": "Alex"},
  "due_at": "2026-11-03T13:00:00+00:00",
  "remind_at": null,
  "priority": "high",
  "status": "open",
  "overdue": false,
  "stage": null,
  "position": 0,
  "list": null,
  "labels": [],
  "checklist": [],
  "repeat": "",
  "refs": {"case_id": null, "contact_id": null, "app": null, "entity": null, "record_id": null},
  "comment_count": 0,
  "can_edit": true
}
```

The reply has more keys: `repeated_from`, `source`, `created_by`, `completed_at`, `created_at` and `updated_at`.

The request takes `title`, `notes`, `assignee`, `due_at`, `remind_at`, `priority` (`low`, `normal` or `high`),
`status`, `stage_id`, `list_id`, `labels`, `checklist`, `repeat` (empty, `daily`, `weekdays`, `weekly` or `monthly`), `case_id`, `contact_id` and `record`
(`{app, entity, record_id}`). `assignee` is `me`, a member id or `agent:<id>`. Without it, the task is yours. Times
need an offset. A task `status` is `open`, `in_progress`, `done` or `cancelled`.

| Task | Call |
| - | - |
| List tasks. | `GET /api/v1/tasks` |
| Read, change or archive one. | `GET`, `PATCH`, `DELETE /api/v1/tasks/{task_id}` |
| Complete or reopen one. | `POST /api/v1/tasks/{task_id}/complete`, `/reopen` |
| Move the reminder. Body: `{"until": "..."}` or `{"minutes": 30}`. | `POST /api/v1/tasks/{task_id}/snooze` |
| Read or add comments. | `GET`, `POST /api/v1/tasks/{task_id}/comments` |
| Archive a comment. Its writer, an owner or an admin can. | `DELETE /api/v1/tasks/{task_id}/comments/{comment_id}` |
| Change many tasks. | `POST /api/v1/tasks/bulk` |
| Read the labels in use, and counts of overdue and due tasks. | `GET /api/v1/tasks/labels`, `GET /api/v1/tasks/summary` |
| Read or change the board stages and the lists. | `/api/v1/tasks/stages`, `/api/v1/tasks/lists` |
| Read whether Tasks is on. An owner or an admin turns it on with `POST`. | `GET`, `POST /api/v1/tasks/area` |

The task list takes these filters: `assignee` (`me`, `none`, `all`, a member id or `agent:<id>`), `status` (also
`active` and `all`), `due` (`today`, `overdue` or `week`), `case`, `contact`, `list`, `stage`, `label`, `priority`,
`source` (`agents` or `people`), `record` (`app:entity:id`), `q` and `offset`. The reply is
`{"results": [...], "enabled": true, "next_offset": 50}`. Send `next_offset` as `offset` for the next page. A page holds
50 tasks.

`POST /api/v1/tasks/bulk` takes `{"ids": [...], "action": "...", "value": ...}` with up to 200 ids. The `action` is
`complete`, `reopen`, `cancel`, `archive`, `assign`, `due`, `priority`, `stage`, `list`, `label_add` or
`label_remove`. The reply is `{"updated": n, "results": [...]}`.

Stages and lists can be created, ordered and removed by owners and admins. A stage has a `kind` of `todo`, `doing` or
`done`.

## App records

An app keeps its own records in entities. These calls read and write them for any installed app.

| Task | Call |
| - | - |
| Read a page of records. Keys: `q`, `filter`, `sort`, `order`, `page`, `page_size`, `archived`. | `GET /api/v1/apps/{slug}/{entity}/records` |
| Create a record. Body: `{"values": {...}, "draft"?: true, "key"?: "...", "test"?: true}`. | `POST /api/v1/apps/{slug}/{entity}/records` |
| Read one record and its history. | `GET /api/v1/apps/{slug}/{entity}/records/{record_id}` |
| Change values. Body: `values`. | `PATCH /api/v1/apps/{slug}/{entity}/records/{record_id}` |
| Archive a record. It is kept and can be restored. | `DELETE /api/v1/apps/{slug}/{entity}/records/{record_id}` |
| Set a status of the entity. | `POST /api/v1/apps/{slug}/{entity}/records/{record_id}/status` |
| Bring back an archived record. It must be archived less than 30 days ago. | `POST /api/v1/apps/{slug}/{entity}/records/{record_id}/restore` |

The page reply is `{results, count, page, page_size, pages}`. The page size is 20 unless you ask for another from 1 to
100\. Read the entities and fields of an app from `GET /api/v1/apps/{slug}`. A record that does not exist returns
`404` with `There is no such record.`

ImpelLabs raises `record.created`, `record.updated` and `record.status_changed` when records change. A workflow or a
webhook can start on them. See [event types](https://docs.impellabs.tech/api/events.md).


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