---
title: Cancel Run
api: POST /brands/{brand_id}/runs/{run_id}/cancel
description: "Mark a stuck or running pipeline run as failed. Use when a run has not made progress for more than 15 minutes."
---

> **For AI agents:** the complete documentation index is at [llms.txt](https://docs.boringmarketing.com/llms.txt). Append `.md` to any page URL for its markdown version.

Forces a `queued` or `running` pipeline run into the `failed` state. Use when a run appears stuck — for example, `meta.stage_started_at` has not advanced for more than 15 minutes — or when you need to free the active-run slot for a new trigger.

<Warning>
**The run-status cancellation is the only thing this endpoint guarantees.** Background work that was already in flight when you cancelled may continue to completion. The status row is locked into the cancelled state — a worker that finishes after the cancel cannot transition the row back to `running` or `done` (PR #112 added a terminal-state guard) — but its outputs (evidence, opportunities, brief drafts, etc.) may still land in the database under the cancelled `run_id`. Filter by `?run_id=` if you need to inspect what the worker produced before it was cancelled.
</Warning>

## Path parameters

<ParamField path="brand_id" type="string" required>
  The brand UUID.
</ParamField>

<ParamField path="run_id" type="string" required>
  The run UUID.
</ParamField>

## Response

```json
{
  "run_id": "run-uuid",
  "status": "failed",
  "cancelled": true
}
```

## Errors

| Status | Meaning |
|---|---|
| `400` | Run is not in a cancellable state (already `done`, `failed`, or `cancelled`). Body: `{"detail": "Run is <status>, not queued or running"}`. |
| `404` | Run does not exist or does not belong to this brand. |

## Example

```bash
curl -X POST \
  -H "X-API-Key: $BM_API_KEY" \
  https://api.boringmarketing.com/brands/$BRAND_ID/runs/$RUN_ID/cancel
```

<Tip>
After cancelling, you can immediately re-trigger the same pipeline endpoint. The new run will get a fresh `run_id`. Pipeline data is append-only — the cancelled run's partial work is preserved in the database and can still be queried via `?run_id=<cancelled-run-id>`.
</Tip>
