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

# Workflows API

> Invoke a named workflow and poll its run state.

<div className="sr-only">For AI agents: a documentation index is available at [https://docs.coverbase.com/llms.txt](https://docs.coverbase.com/llms.txt) — this page is also available in markdown by appending .md to the URL.</div>

The Workflows API lets external systems start a workflow by name with an arbitrary input payload, and read the state of a run.

All endpoints are org-scoped to the API key. See [API conventions](/conventions) for authentication, IDs, timestamps, idempotency, and the error envelope.

## Run a workflow

<ParamField path="method" type="POST">
  `POST /v1/workflows/{workflow_name}/run`
</ParamField>

Starts a new run of the named workflow. Returns `201 Created`. The `workflow_name` path segment is matched against the workflow definition's `name` for your org.

The run row is created and committed, then a `Workflow.RunRequested` event is dispatched to the workflow engine, which executes the definition's entrypoint components. The response returns as soon as the run is created and the event is enqueued — poll [Get a workflow run](#get-a-workflow-run) for progress.

### Path parameters

<ParamField path="workflow_name" type="string" required>
  The name of the workflow as configured for your org.
</ParamField>

### Request body

<ParamField body="input" type="object">
  Workflow input parameters. Optional — defaults to `{}`. The value is stored and echoed back on the response; its schema is workflow-specific and is not validated by this endpoint.
</ParamField>

### Headers

<ParamField header="Authorization" type="string" required>
  `Bearer ak_...`
</ParamField>

<ParamField header="Idempotency-Key" type="string">
  Optional. If the same key is sent again within 24 hours for this endpoint, the original response is returned and no new run is started. See [Idempotency](/conventions#idempotency).
</ParamField>

### Example request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.coverbase.app/v1/workflows/quarterly-privacy-sweep/run" \
    -H "Authorization: Bearer ak_live_xxx" \
    -H "Idempotency-Key: privacy-sweep-2026-q2" \
    -H "Content-Type: application/json" \
    -d '{
      "input": {
        "vendor_filter": { "tags": ["processes_pii"] },
        "due_date": "2026-06-30"
      }
    }'
  ```

  ```python Python theme={null}
  import os
  import requests

  API_KEY = os.environ["COVERBASE_API_KEY"]
  BASE_URL = "https://api.coverbase.app"

  resp = requests.post(
      f"{BASE_URL}/v1/workflows/quarterly-privacy-sweep/run",
      headers={
          "Authorization": f"Bearer {API_KEY}",
          "Idempotency-Key": "privacy-sweep-2026-q2",
          "Content-Type": "application/json",
      },
      json={"input": {"vendor_filter": {"tags": ["processes_pii"]}, "due_date": "2026-06-30"}},
      timeout=30,
  )
  resp.raise_for_status()
  print(resp.json())
  ```
</CodeGroup>

### Example response

`201 Created`:

```json theme={null}
{
  "workflow_run_id": "cbwr_a8f2c19e3d4b5e6f7a8b9c0d1e2f3a4b",
  "workflow_name": "quarterly-privacy-sweep",
  "status": "started",
  "started_at": 1746576000,
  "input": {
    "vendor_filter": { "tags": ["processes_pii"] },
    "due_date": "2026-06-30"
  }
}
```

### Response fields

<ResponseField name="workflow_run_id" type="string">
  Identifier for this run (`cbwr_...`). Use it with the get-run endpoint.
</ResponseField>

<ResponseField name="workflow_name" type="string">
  The resolved workflow definition name.
</ResponseField>

<ResponseField name="status" type="string">
  Run status. One of: `started`, `completed`, `canceled`, `failed`. A new run is `started`.
</ResponseField>

<ResponseField name="started_at" type="integer">
  Unix timestamp (seconds) when the run was created.
</ResponseField>

<ResponseField name="input" type="object">
  Echoes the input sent in the request.
</ResponseField>

### Error responses

| Status | Body                                                                                                                                                              | When                                                                                                |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| 404    | `{"detail": {"code": "workflow_not_found", "message": "Workflow '...' not found."}}`                                                                              | No workflow with that name exists for the org.                                                      |
| 409    | `{"detail": {"code": "workflow_disabled", "message": "Workflow '...' is disabled."}}`                                                                             | The workflow exists but is not enabled.                                                             |
| 502    | `{"detail": {"code": "workflow_dispatch_failed", "message": "Workflow run was created but could not be dispatched. Retry with the same workflow run id (...)."}}` | The run row was created but the dispatch event failed. The run ID is in the message; safe to retry. |
| 422    | Standard validation error                                                                                                                                         | The request body failed schema validation. See [API conventions](/conventions#validation-errors).   |

## Get a workflow run

<ParamField path="method" type="GET">
  `GET /v1/workflows/runs/{workflow_run_id}`
</ParamField>

Returns the current state of a workflow run.

### Path parameters

<ParamField path="workflow_run_id" type="string" required>
  The run ID (`cbwr_...`).
</ParamField>

### Example request

```bash cURL theme={null}
curl -X GET "https://api.coverbase.app/v1/workflows/runs/cbwr_a8f2c19e3d4b5e6f7a8b9c0d1e2f3a4b" \
  -H "Authorization: Bearer ak_live_xxx"
```

### Example response

```json theme={null}
{
  "workflow_run_id": "cbwr_a8f2c19e3d4b5e6f7a8b9c0d1e2f3a4b",
  "workflow_name": "quarterly-privacy-sweep",
  "workflow_definition_id": "cbwd_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
  "status": "completed",
  "started_at": 1746576000,
  "completed_at": 1746579600,
  "steps": [
    {
      "step_id": "cbwrs_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
      "component_id": "cbwc_9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d",
      "component_name": "Send questionnaire",
      "action_type": "send_questionnaire",
      "status": "success",
      "message": null,
      "artifacts": [
        { "artifact_type": "vendor", "id": "cbvndr_e448ba62882143f3ba0c140bb2e30162", "role": "trigger" },
        { "artifact_type": "questionnaire_response", "id": "cbqsrw_2d5e8f1a4b7c0d3e6f9a2b5c8d1e4f7a", "role": "result" }
      ],
      "created_at": 1746576540,
      "updated_at": 1746576600
    }
  ]
}
```

### Response fields

<ResponseField name="workflow_run_id" type="string">
  The run ID (`cbwr_...`).
</ResponseField>

<ResponseField name="workflow_name" type="string | null">
  The workflow definition name, or `null` if the definition could not be resolved.
</ResponseField>

<ResponseField name="workflow_definition_id" type="string | null">
  The workflow definition ID (`cbwd_...`).
</ResponseField>

<ResponseField name="status" type="string">
  Run status. One of: `started`, `completed`, `canceled`, `failed`.
</ResponseField>

<ResponseField name="started_at" type="integer">
  Unix timestamp (seconds) when the run was created.
</ResponseField>

<ResponseField name="completed_at" type="integer | null">
  Unix timestamp (seconds) when the run finished. Populated only when `status` is `completed`, `failed`, or `canceled`; otherwise `null`.
</ResponseField>

<ResponseField name="steps" type="object[]">
  Executed steps for this run (empty array if none yet). Each step records both the component that ran and the outcome of that component's action. Each step has:

  <Expandable title="step fields">
    <ResponseField name="step_id" type="string">The run-step ID (`cbwrs_...`).</ResponseField>
    <ResponseField name="component_id" type="string | null">The workflow component this step ran.</ResponseField>
    <ResponseField name="component_name" type="string | null">The component's display name.</ResponseField>
    <ResponseField name="action_type" type="string | null">The component's action type (e.g. `send_questionnaire`), when available.</ResponseField>
    <ResponseField name="status" type="string | null">Action outcome. One of `success`, `failed`, `skipped`, or `null` if the engine has not yet recorded a result for this step.</ResponseField>
    <ResponseField name="message" type="string | null">Optional human-readable explanation. Set on failure to surface the error; set on `skipped` to explain why; usually `null` on success.</ResponseField>

    <ResponseField name="artifacts" type="object[]">
      Entities the step consumed or produced. Each entry has `artifact_type` (the canonical target type, e.g. `vendor`, `assessment`, `questionnaire_response`), `id` (the entity ID), and `role` (`trigger` for entities that fed into the step; `result` for entities the step created or modified).
    </ResponseField>

    <ResponseField name="created_at" type="integer | null">Unix timestamp (seconds) when the step was recorded.</ResponseField>
    <ResponseField name="updated_at" type="integer | null">Unix timestamp (seconds) of the step's last update.</ResponseField>
  </Expandable>
</ResponseField>

Poll this endpoint until `status` is terminal (`completed`, `canceled`, or `failed`); `steps[]` grows as the engine progresses, and each step's `status` and `artifacts` reflect what that stage actually did.

### Error responses

| Status | Body                                                                                   | When                                                                 |
| ------ | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| 404    | `{"detail": {"code": "workflow_run_not_found", "message": "Workflow run not found."}}` | The `workflow_run_id` does not exist or is not in the API key's org. |

## List workflow runs

<ParamField path="method" type="GET">
  `GET /v1/workflows/runs`
</ParamField>

Returns workflow runs for the org, newest first. Use this when you don't already know the run ID — for example, to discover runs created by other systems or by Coverbase's internal automations, or to reconcile run history against an external scheduler.

### Query parameters

<ParamField query="workflow_name" type="string">
  Filter to runs of a specific workflow definition by name. Returns `404 workflow_not_found` if no workflow with that name exists for the org.
</ParamField>

<ParamField query="status" type="string">
  Filter by run status. Repeat to include multiple statuses, e.g. `?status=started&status=failed`. Valid values: `started`, `completed`, `canceled`, `failed`.
</ParamField>

<ParamField query="created_at_after" type="integer">
  Unix timestamp (seconds). Include only runs created at or after this time.
</ParamField>

<ParamField query="created_at_before" type="integer">
  Unix timestamp (seconds). Include only runs created at or before this time.
</ParamField>

<ParamField query="limit" type="integer" default="100">
  Page size. Min `1`, max `500`.
</ParamField>

<ParamField query="offset" type="integer" default="0">
  Pagination offset.
</ParamField>

### Example request

```bash cURL theme={null}
curl -X GET "https://api.coverbase.app/v1/workflows/runs?workflow_name=quarterly-privacy-sweep&status=failed&limit=20" \
  -H "Authorization: Bearer ak_live_xxx"
```

### Example response

```json theme={null}
{
  "data": [
    {
      "workflow_run_id": "cbwr_a8f2c19e3d4b5e6f7a8b9c0d1e2f3a4b",
      "workflow_name": "quarterly-privacy-sweep",
      "workflow_definition_id": "cbwd_1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d",
      "status": "failed",
      "started_at": 1746576000,
      "completed_at": 1746576720,
      "step_count": 3
    }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}
```

### Response fields

<ResponseField name="data" type="object[]">
  Paginated list of run summaries. Each entry mirrors the keys of [Get a workflow run](#get-a-workflow-run), minus `steps[]` and plus `step_count`. Fetch the full run via `GET /v1/workflows/runs/{workflow_run_id}` when you need per-stage outcomes.
</ResponseField>

<ResponseField name="total" type="integer">
  Total number of runs matching the filters (across all pages).
</ResponseField>

<ResponseField name="limit" type="integer">
  Echoes the requested page size.
</ResponseField>

<ResponseField name="offset" type="integer">
  Echoes the requested offset.
</ResponseField>

### Error responses

| Status | Body                                                                                 | When                                                                                 |
| ------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
| 404    | `{"detail": {"code": "workflow_not_found", "message": "Workflow '...' not found."}}` | `workflow_name` was supplied but no workflow with that name exists for the org.      |
| 422    | Standard validation error                                                            | A query parameter failed validation (e.g. `limit` out of range, malformed `status`). |
