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

# Start and resume via API

> Start workflow executions and resume waiting ones with the Platform API

Two endpoints cover the whole lifecycle from an external system:

* `POST /platform/v1/workflows/{workflow_id}/executions` — start an execution
* `POST /platform/v1/workflow_executions/{execution_id}/resume` — resume an execution that is waiting for input

Both are asynchronous: they queue the work and return immediately.

## Before you start

* The workflow status must be `active`
* The workflow needs an active [API trigger](/docs/flows/triggers#api-trigger)
* Every request needs an `X-API-Key` header

## Start an execution

```bash theme={null}
curl -X POST "https://api.kapso.ai/platform/v1/workflows/$WORKFLOW_ID/executions" \
  -H "X-API-Key: $KAPSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow_execution": {
      "phone_number": "+14155552671",
      "phone_number_id": "123456789012345",
      "variables": {
        "customer_name": "Alice Smith",
        "order_total": 149.99
      },
      "context": {
        "source": "checkout_flow"
      }
    }
  }'
```

| Field                | Description                                                                                |
| -------------------- | ------------------------------------------------------------------------------------------ |
| `phone_number`       | E.164 number of the participant. Required unless you send `recipient`.                     |
| `recipient`          | BSUID or parent BSUID of the participant. Required unless you send `phone_number`.         |
| `phone_number_id`    | WhatsApp number that handles the conversation. Defaults to the project's WhatsApp config.  |
| `whatsapp_config_id` | Deprecated. Use `phone_number_id`.                                                         |
| `variables`          | Initial workflow variables, available as `{{var_name}}` or `{{vars.var_name}}`.            |
| `context`            | Extra contextual data merged into the `context` namespace, outside the variable namespace. |
| `initial_data`       | Custom payload passed to the workflow's first step.                                        |

Response is `202 Accepted`:

```json theme={null}
{
  "data": {
    "message": "Workflow execution initiated",
    "workflow_id": "workflow_uuid",
    "id": "execution_uuid",
    "tracking_id": "tracking_uuid"
  }
}
```

Keep `id` to fetch or resume the execution, and `tracking_id` to correlate it with your own systems.

### Start by BSUID

When you only have a [business-scoped user ID](/docs/whatsapp/business-scoped-user-ids), send `recipient` instead of `phone_number`:

```bash theme={null}
curl -X POST "https://api.kapso.ai/platform/v1/workflows/$WORKFLOW_ID/executions" \
  -H "X-API-Key: $KAPSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow_execution": {
      "recipient": "US.13491208655302741918",
      "phone_number_id": "123456789012345"
    }
  }'
```

If you send both identifiers, the phone number routes the conversation and the BSUID is kept as the participant identity. BSUID recipients are not supported on sandbox numbers.

### Execution context

An API-triggered execution starts with:

```
{{system.trigger_type}}                            # "api_call"
{{system.tracking_id}}                             # tracking_id from the response
{{system.api_key_id}}                              # API key used
{{system.trigger_whatsapp_config_id}}              # WhatsApp config handling the conversation

{{context.channel}}                                # "api"
{{context.phone_number}}                           # normalized phone number, when sent
{{context.whatsapp_business_scoped_user_id}}       # when recipient is a BSUID
{{context.whatsapp_parent_business_scoped_user_id}} # when recipient is a parent BSUID (US.ENT.…)

{{vars.your_variable}}                             # from the variables object
```

See [Triggers](/docs/flows/triggers#workflow-context) for the full context reference.

## Check execution status

```bash theme={null}
curl "https://api.kapso.ai/platform/v1/workflow_executions/$EXECUTION_ID" \
  -H "X-API-Key: $KAPSO_API_KEY"
```

The execution row is created when the queued job picks up the request, so a lookup fired immediately after the `202` can return `404`. Retry after a moment.

To find executions that need input, filter the workflow's execution list:

```bash theme={null}
curl "https://api.kapso.ai/platform/v1/workflows/$WORKFLOW_ID/executions?status=waiting" \
  -H "X-API-Key: $KAPSO_API_KEY"
```

## Resume a waiting execution

An execution enters `waiting` when it reaches a [wait for response](/docs/flows/step-types/wait-for-response-node) step. Resume it with the input the workflow was waiting for:

```bash theme={null}
curl -X POST "https://api.kapso.ai/platform/v1/workflow_executions/$EXECUTION_ID/resume" \
  -H "X-API-Key: $KAPSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": {
      "kind": "payload",
      "data": "yes, proceed"
    },
    "variables": {
      "confirmed_at": "2026-08-11T18:00:00Z"
    }
  }'
```

| Field          | Description                                                                  |
| -------------- | ---------------------------------------------------------------------------- |
| `message.data` | Required. String, object, or array passed to the waiting step.               |
| `message.kind` | Optional. Defaults to `payload`.                                             |
| `variables`    | Optional. Merged into the execution's `vars`; existing keys are overwritten. |

Note that `message` and `variables` sit at the top level, not under `workflow_execution`.

The response is `200 OK` with the execution's `id`, `status`, `tracking_id`, `current_step`, and timestamps. Resume work runs in the background, so the returned status can still be `waiting` — poll `GET /platform/v1/workflow_executions/{id}` to see it advance.

Only one resume can be pending at a time. A second request while the first is still pending returns `409 Conflict`.

## Errors

| Status | When                                                                                                                                                                                                                                                                   |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Resume request without a `message` object or without `message.data`.                                                                                                                                                                                                   |
| `404`  | Workflow or execution not found in this project.                                                                                                                                                                                                                       |
| `409`  | A resume is already pending, or the execution is being processed by another request. Retry after a short delay.                                                                                                                                                        |
| `422`  | Workflow not active, no active API trigger, neither `phone_number` nor `recipient` sent, `recipient` is not a valid BSUID or parent BSUID, `recipient` used with a sandbox number, `phone_number_id` not in this project, or the execution is not in `waiting` status. |
| `429`  | Burst rate limit exceeded. Retry after the seconds in `Retry-After`.                                                                                                                                                                                                   |

The start endpoint has a burst limiter on top of the general [rate limits](/api/rate-limits), scoped by API key and workflow, resetting every second:

* `legacy` / `free`: 5 requests per second
* `pro`: 15 requests per second
* `enterprise` / `platform`: 30 requests per second

Successful responses carry `X-Burst-RateLimit-Limit` and `X-Burst-RateLimit-Remaining`.
