---
title: run
description: Run an endpoint, a job by id, or a workflow, spending prepaid credit with idempotent retries and optional fallback across providers.
---

<WorksIn />

Runs spend prepaid credit. Needs the `runs.execute` scope. On a new workspace, call
[`balance`](/mcp-tools/balance) first and [`top_up`](/mcp-tools/top-up) if needed. `run`
validates the input, checks the workspace budget, reserves the estimated max cost, then runs or
queues the endpoint. Some endpoints act on your connected accounts and can send or change things
there.

`endpointId` can be a concrete endpoint id, `"job:<job id>"` to let looot pick the first provider
in `fallback.prefer` order that this workspace can run now and whose schema accepts your input,
or `"workflow:<id>"` to start that workflow (follow its `workflowRunId` with [`runs_get`](/mcp-tools/runs-get)).

## Inputs

| Argument | Type | Required | Default | Limits | Meaning |
| --- | --- | --- | --- | --- | --- |
| `endpointId` | string | Yes | - | - | An endpoint id, `job:<job id>`, or `workflow:<id>`. |
| `input` | object | Yes | - | - | The endpoint's own input fields, per its `inputSchema` from [`inspect`](/mcp-tools/inspect). |
| [`idempotencyKey`](/concepts/idempotency) | string | Yes | - | - | Unique per logical call. Same key and identical body replay the original run; same key with a different body returns `409`. |
| `output.mode` | string | No | - | `raw` \| `custom` | `raw` returns the provider's own shape; `custom` needs `mappingId` (and optional `version`) for a stored output mapping. |
| [`fallback`](/concepts/fallback) | boolean or object | No | - | see below | `true` takes every default. Object: `{enabled, maxAttempts (1-10, default 3), maxCostUsd (0-100), prefer, exclude (max 50 ids), stopAtFirstMiss (default false)}`. |
| `wait` | number | No | 20 | 0-60 | Seconds to block for the settled result inline before returning the queued/running run instead. `wait: 0` returns at once. |

`error` on a failed run: `{code, providerStatus, message, requestId, whoseError, retryable, retryHint}`,
never secrets or raw provider headers. Every run carries [`outcome`](/concepts/outcomes)
(`hit`\|`weak`\|`miss`\|`error`\|`rejected`\|`skipped`\|`pending`). With `fallback`, the result
also carries `route`: `{servedBy, attempts, skipped, summary}`. A completed run of a normalized
job can carry [`normalized`](/concepts/normalized-output) next to `result`.

## Example call

```json
{
  "endpointId": "linkup-search",
  "input": {
    "q": "What is Microsoft's 2024 revenue?",
    "depth": "standard",
    "outputType": "searchResults"
  },
  "idempotencyKey": "9e2f7c1a-4b3d-4e5f-8a6b-1c2d3e4f5a6b",
  "wait": 20
}
```

## Example answer

Abridged: `result` is the provider's own payload and varies by endpoint.

```json
{
  "runId": "run_807967cc4b7f468fa5d7dbcaefdee859",
  "endpointId": "linkup-search",
  "status": "completed",
  "providerResponseStatus": "ok",
  "createdAt": "2026-09-24T21:14:36.435Z",
  "completedAt": "2026-09-24T21:14:37.377607+00:00",
  "input": {
    "q": "What is Microsoft's 2024 revenue?",
    "depth": "standard",
    "outputType": "searchResults"
  },
  "outcome": "hit",
  "actualCost": 0.005,
  "error": null
}
```

## Errors

Out of credit is a tool error with `code: "insufficient_balance"` and `status: "blocked"`: show
the customer `error.message` and `topUp.checkoutUrl` (or `topUp.dashboardUrl`), wait for payment,
then retry with a **new** `idempotencyKey`. A successful call can still carry `status: "failed"`,
for an unknown `endpointId` or input failing the endpoint's schema: check `status` and `error`,
not the tool call's own success. Reusing an `idempotencyKey` with a different `endpointId` or
`input` fails as [`idempotency_conflict`](/errors/rest-errors#idempotency_conflict), never silently applying the new body to the old run.
Missing `idempotencyKey`, `input` or `endpointId` returns [`validation_error`](/errors/rest-errors#validation_error) naming the field.
This workspace already at its in-flight run limit returns [`too_many_inflight_runs`](/errors/rest-errors#too_many_inflight_runs).

## REST and CLI

- REST: [`POST /v1/runs`](/reference/runs/post-v1-runs)
- CLI: `looot run <endpoint-id> --input '{"..."}' [--wait] [--fallback]`

<Related />
