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

# Run a workflow from the API

> Every workflow is a typed API endpoint and an MCP tool. Declare its inputs on the API trigger, use them in any step, and call it sync or async.

Every workflow starts with an **API trigger**. The trigger lists the inputs the workflow takes. Once a workflow has steps, you can call it from your code, from a script, or from an AI assistant over MCP, the same way you call a skill.

## Before you start

* An API key from **Settings → API Keys** with the `workflows:read` and `workflows:invoke` scopes. See [API keys](/account/api-keys).
* Credits on your account. See [Credits and billing](/credits-and-billing).

The examples read the key from the `VALENDATA_API_KEY` environment variable and call `https://api.valendata.com`.

## 1. Declare the inputs

Open the workflow and click the **API trigger** node, the first node on the canvas. Add one entry per input:

| Field | What it means |
| - | - |
| `name` | Letters, digits and `_`. Steps refer to it as `{{inputs.name}}`. |
| `type` | `string`, `number`, `integer`, `boolean`, `array` or `object`. |
| `required` | The caller must send it, unless it has a `default`. |
| `default` | Used when the caller leaves it out. Scheduled runs always use the defaults. |
| `description`, `example` | Shown in the API tab, the API contract and the MCP tool. |

You can't delete the trigger. A workflow made before triggers existed gets one automatically, with one required string input for each `{{inputs.name}}` its steps already use.

## 2. Use the inputs in steps

Write `{{inputs.<name>}}` in any step setting: a skill step's inputs, its **Max results**, an HTTP URL or body, a condition value. Code steps also get every input in the `inputs` dictionary.

When a whole setting is one reference, the step gets the value with its type, so `{{inputs.limit}}` in **Max results** becomes the number `3`. Inside longer text, the value is pasted in as text.

## 3. Read the contract

```bash theme={null}
curl https://api.valendata.com/v1/workflows/test-workflow-api \
  -H "Authorization: Bearer $VALENDATA_API_KEY"
```

The answer lists `input_schema` (the trigger's inputs), `input_json_schema`, `output` (what `outputs` will hold), a `reliability` summary of the last 20 finished runs, the `api_endpoint`, the `runs_endpoint` and the `mcp_tool` name. The slug is shown on the workflow's API tab.

## 4. Run it and wait

```bash theme={null}
curl -X POST https://api.valendata.com/v1/workflows/test-workflow-api/run \
  -H "Authorization: Bearer $VALENDATA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"inputs": {"limit": 3}, "wait": 60}'
```

Valendata checks the inputs first. A missing required input, a wrong type or an unknown input name returns `422` with every problem listed, and nothing runs or costs credits. Values are converted when they can be: `"3"` becomes `3` for an `integer` input.

If the run finishes within `wait` seconds (default 60, max 120), you get `200`:

```json theme={null}
{
  "run_id": "0f533c1b-9134-466f-b6ba-38592ca5d21c",
  "status": "completed",
  "inputs": {"limit": 3},
  "outputs": {
    "rows": [{"author": "Albert Einstein", "text": "“The world as we have created it is a process of our thinking…”"}],
    "count": 3
  },
  "steps": [{"step_id": "quotes", "name": "Quotes", "type": "skill", "status": "success", "count": 3}],
  "credits_charged": 2.0,
  "cost_final": true,
  "status_url": "/v1/workflow-runs/0f533c1b-9134-466f-b6ba-38592ca5d21c"
}
```

`outputs` holds the rows of the workflow's final step. If several steps end the workflow, `outputs` has one `{rows, count}` per final step, keyed by step name.

If the run is still going after `wait` seconds, you get `202` with the run so far. Poll its `status_url`.

## 5. Or start it and come back

```bash theme={null}
curl -X POST https://api.valendata.com/v1/workflows/test-workflow-api/runs \
  -H "Authorization: Bearer $VALENDATA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1234" \
  -d '{"inputs": {"limit": 3}, "webhook_url": "https://example.com/hooks/valendata"}'
```

You get `202` with `run_id` and `status_url` at once. Then either poll:

```bash theme={null}
curl https://api.valendata.com/v1/workflow-runs/RUN_ID \
  -H "Authorization: Bearer $VALENDATA_API_KEY"
```

or wait for the webhook. The webhook body is the same run object, signed like skill webhooks. See [Webhooks](/guides/web-to-api#webhooks). Sending the same `Idempotency-Key` again returns the run it already started.

## From an AI assistant (MCP)

Each workflow you can run is also an MCP tool named `workflow_<slug>`, for example `workflow_test-workflow-api`. Its input schema is the trigger's inputs and its output schema is the run object above. Clients that support the MCP Tasks extension get a task they can poll instead of waiting. See [MCP](/integrations/mcp).

## Who can run it and who pays

* The workflow's owner and members of its workspace can read and run it. Anyone else gets `404`.
* The workflow's owner pays: a base fee per run, plus each step's own cost. The run is charged the higher of the two, never both. API and MCP runs don't use your monthly run allowance.
* If your account already has its maximum of runs in progress, `/run` answers `429` with `Retry-After`. `/runs` waits its turn instead.


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