# Workflows

> List the workspace's workflows, read one with its steps, or delete one for good.

Web page: https://docs.lodol.com/docs/api/workflows

## The workflow object

```json
{
  "id": "665f1a2b3c4d5e6f7a8b9c0d",
  "name": "Monthly Client Report",
  "description": "Builds a client's monthly report and emails it to them",
  "created_by": "665f1a2b3c4d5e6f7a8b9c0e",
  "created_at": "2026-01-15T10:30:00+00:00",
  "updated_at": "2026-01-15T10:30:00+00:00",
  "last_run_at": "2026-03-17T08:00:00+00:00",
  "inputs": [
    { "name": "client", "type": "text", "required": true, "default": null, "description": "The client to report on" },
    { "name": "month", "type": "text", "required": false, "default": "last month", "description": "" }
  ],
  "outputs": [
    { "name": "total", "type": "number", "description": "The month's sales, in dollars" },
    { "name": "summary", "type": "text", "description": "" }
  ]
}
```

<Fields title="Fields">
<Field id="id" type="string" description="The workflow's ID. It stays the same when the workflow is edited, so it's safe to store." />
<Field id="name" type="string" description="The workflow's name." />
<Field id="description" type="string" description="What the workflow does." />
<Field id="created_by" type="string or null" description="The ID of the member who created it." />
<Field id="created_at" type="string or null" description="When it was created, in ISO 8601." />
<Field id="updated_at" type="string or null" description="When it was last changed, in ISO 8601." />
<Field id="last_run_at" type="string or null" description="When it last ran, in ISO 8601." />
<Field id="inputs" type="array" description="The inputs the workflow declares, which a run can give values for. Empty if it declares none, and for a workflow that starts from a trigger or a schedule, which takes no inputs." />
<Field id="outputs" type="array" description="The outputs the workflow declares: what a run that succeeds hands back, in the run's outputs. Empty if it declares none." />
</Fields>

Each entry in `inputs` describes one input:

<Fields title="Input fields">
<Field id="name" type="string" description="The name a run gives the value under." />
<Field id="type" type="string" description="One of text, number, boolean, list or object." />
<Field id="required" type="boolean" description="Whether every run must give it a value." />
<Field id="default" type="any or null" description="The value an optional input takes when a run leaves it out." />
<Field id="description" type="string" description="What the input is for, as written in the workflow." />
</Fields>

Each entry in `outputs` describes one output:

<Fields title="Output fields">
<Field id="name" type="string" description="The name the value is under in a run's outputs." />
<Field id="type" type="string" description="One of text, number, boolean, list or object." />
<Field id="description" type="string" description="What the output is, as written in the workflow." />
</Fields>

### Workflow IDs and versions

Editing a workflow can save a new version of it, but its `id` stays the same, so you can store it and use it to run the workflow later. Every endpoint that takes a workflow ID also accepts the ID of any version of it, such as an ID this API returned before the workflow was edited, and acts on the workflow as it is now. A run records the version that ran as its [`version_id`](https://docs.lodol.com/docs/api/runs.md#the-run-object).

---

## List workflows

<Endpoint method="GET" path="/api/v1/workflows" />

Returns every workflow in the workspace the API key belongs to. Requires the `workflows:read` scope.

```bash tab="cURL" tab-group="lang"
curl https://api-prod.lodol.com/api/v1/workflows \
  -H "Authorization: Bearer $LODOL_API_KEY"
```

```js tab="JavaScript"
const response = await fetch('https://api-prod.lodol.com/api/v1/workflows', {
  headers: { Authorization: `Bearer ${process.env.LODOL_API_KEY}` },
});
const { workflows } = await response.json();
```

```python tab="Python"
response = requests.get(
    "https://api-prod.lodol.com/api/v1/workflows",
    headers={"Authorization": f"Bearer {os.environ['LODOL_API_KEY']}"},
)
workflows = response.json()["workflows"]
```

**Response `200`:** the workspace's [workflow objects](#the-workflow-object).

```json
{
  "workflows": [
    {
      "id": "665f1a2b3c4d5e6f7a8b9c0d",
      "name": "Monthly Client Report",
      "description": "Builds a client's monthly report and emails it to them",
      "created_by": "665f1a2b3c4d5e6f7a8b9c0e",
      "created_at": "2026-01-15T10:30:00+00:00",
      "updated_at": "2026-01-15T10:30:00+00:00",
      "last_run_at": "2026-03-17T08:00:00+00:00",
      "inputs": [
        { "name": "client", "type": "text", "required": true, "default": null, "description": "The client to report on" }
      ],
      "outputs": [
        { "name": "total", "type": "number", "description": "The month's sales, in dollars" }
      ]
    }
  ]
}
```

---

## Get a workflow

<Endpoint method="GET" path="/api/v1/workflows/:id" />

Returns one workflow, including its steps as a `program`. Requires the `workflows:read` scope. `:id` can be the workflow's `id` or the ID of any of its versions; the response always describes the workflow as it is now, under its `id`.

```bash tab="cURL" tab-group="lang"
curl https://api-prod.lodol.com/api/v1/workflows/665f1a2b3c4d5e6f7a8b9c0d \
  -H "Authorization: Bearer $LODOL_API_KEY"
```

```js tab="JavaScript"
const response = await fetch(
  'https://api-prod.lodol.com/api/v1/workflows/665f1a2b3c4d5e6f7a8b9c0d',
  { headers: { Authorization: `Bearer ${process.env.LODOL_API_KEY}` } },
);
const workflow = await response.json();
```

```python tab="Python"
response = requests.get(
    "https://api-prod.lodol.com/api/v1/workflows/665f1a2b3c4d5e6f7a8b9c0d",
    headers={"Authorization": f"Bearer {os.environ['LODOL_API_KEY']}"},
)
workflow = response.json()
```

**Response `200`:** a [workflow object](#the-workflow-object) with one more field, `program`: the workflow's trigger and steps, in the format described in [Workflow format](https://docs.lodol.com/docs/api/workflow-format.md).

```json
{
  "id": "665f1a2b3c4d5e6f7a8b9c0d",
  "name": "Monthly Client Report",
  "program": {
    "kind": "Program",
    "version": 1,
    "inputs": [...],
    "body": [...]
  },
  "...": "the other workflow fields"
}
```

---

## Delete a workflow

<Endpoint method="DELETE" path="/api/v1/workflows/:id" />

Deletes a workflow and every version of it, as deleting it in Lodol does. This can't be undone. Requires the `workflows:delete` scope, and the member who created the key must be allowed to delete workflows (the **Delete workflows** role permission); otherwise the request gets `403`.

Deleting a workflow:

- stops any run of it in progress
- stops its trigger or schedule from listening
- removes it from its folders
- detaches the secrets and values scoped to it, without deleting them
- keeps its past runs, which you can still read under [Runs](https://docs.lodol.com/docs/api/runs.md)

`:id` can be the workflow's `id` or the ID of any of its versions.

```bash tab="cURL" tab-group="lang"
curl -X DELETE https://api-prod.lodol.com/api/v1/workflows/665f1a2b3c4d5e6f7a8b9c0d \
  -H "Authorization: Bearer $LODOL_API_KEY"
```

```js tab="JavaScript"
await fetch('https://api-prod.lodol.com/api/v1/workflows/665f1a2b3c4d5e6f7a8b9c0d', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${process.env.LODOL_API_KEY}` },
});
```

```python tab="Python"
requests.delete(
    "https://api-prod.lodol.com/api/v1/workflows/665f1a2b3c4d5e6f7a8b9c0d",
    headers={"Authorization": f"Bearer {os.environ['LODOL_API_KEY']}"},
)
```

**Response `200`:**

```json
{
  "id": "665f1a2b3c4d5e6f7a8b9c0d",
  "name": "Monthly Client Report",
  "deleted": true
}
```

A workflow that doesn't exist, or is already deleted, returns `404`. A delete that fails returns `500` and leaves the workflow as it was. Deleting takes no `Idempotency-Key`, so if a delete times out, check with [Get a workflow](#get-a-workflow) before sending it again: it may have gone through.
