# Cancel a Playground Run

```http
POST /api/public/v1/competitions/mathematics-distillation-challenge-equational-theories-stage1/playground/runs/{runId}/cancel
```

**Scope**: `playground.write`.

Cancels a Run owned by the calling account if the evaluator has not claimed it. Cancellation remains available if the Playground becomes read-only or the competition closes. It does not delete the Run; it preserves a terminal record that remains available through [Get a Playground Run](./get-playground-run.md).

Cancellation depends on whether execution has started:

- If cancellation wins, the Run moves from `pending` to `cancelled`, no execution starts, and the full credit reservation is released.
- If the evaluator wins, the request returns `409 RUN_ALREADY_STARTED`. A running Run cannot be cancelled through this endpoint.

## Path parameters

| Parameter | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| `runId` | string | Yes | Run ID returned by create, list, or detail. |

## Request

The request has no body. Do not send `Content-Type` for an empty request.

```bash
curl -X POST "https://api.sair.foundation/api/public/v1/competitions/mathematics-distillation-challenge-equational-theories-stage1/playground/runs/run_01JSTAGE100000000000000001/cancel" \
  -H "Authorization: Bearer $SAIR_API_KEY"
```

## Response fields

| Field | Type | Description |
| :--- | :--- | :--- |
| `runId` | string | Cancelled Run ID. |
| `status` | string | Always `cancelled` after a successful request. |
| `creditsReleased` | number | Full credit reservation returned to the account. |
| `finishedAt` | string | ISO 8601 UTC cancellation time. |

```json
{
  "ok": true,
  "data": {
    "runId": "run_01JSTAGE100000000000000001",
    "status": "cancelled",
    "creditsReleased": 0.7,
    "finishedAt": "2026-08-30T08:21:31Z"
  }
}
```

Repeating the request after a successful cancellation is idempotent: it returns the same `200` response and does not release credits again. This operation therefore does not use an `idempotencyKey`.

## Errors

| HTTP | Code | When |
| :---: | :--- | :--- |
| `404` | `NOT_FOUND` | The Run does not exist, belongs to another account, or belongs to another competition. |
| `409` | `RUN_ALREADY_STARTED` | The evaluator claimed the Run before cancellation. Refresh the Run. |
| `409` | `RUN_NOT_CANCELLABLE` | The Run is already `done` or `failed`. Refresh the Run. |

See [Errors](../../../errors.md) for authentication, scope, and rate-limit errors.
