---
title: "Cancel an in-flight compose job"
method: POST
path: "/v1/projects/{id}/compose/jobs/{composeJobId}/cancel"
tags: ["compose"]
---

# Cancel an in-flight compose job

`POST /v1/projects/{id}/compose/jobs/{composeJobId}/cancel`

## Request

- Base URL: `https://api.cueframe.ai`
- URL: `https://api.cueframe.ai/v1/projects/{id}/compose/jobs/{composeJobId}/cancel`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.cueframe.ai/api/auth/mcp/authorize`, token URL `https://api.cueframe.ai/api/auth/mcp/token`, scopes: `projects:write`)
  - API key in header `PAYMENT-SIGNATURE`

Cancel a running compose so an agent (or a cost guard) can abort a mis-priced or runaway ensemble without waiting out its budget or TTL. Cancellation is confirmed before the job becomes terminal; the compose.cancelled event is then emitted and any linked charge is released. Already-terminal jobs are rejected (422 compose_not_cancellable).

## Path parameters

- `id` string, required
- `composeJobId` string, required

## Response `200`

Cancelled.

- ComposeJobDetailResponse
  - `composeJobId` string, required
  - `projectId` string, required
  - `status` 'queued' | 'running' | 'awaiting_input' | 'complete' | 'failed' | 'cancelled', required
  - `reconciliationRequired` boolean
  - `error` string, nullable, required
  - `request` object, required
    - `suggestionId` string
    - `fromComposition` boolean
    - `scope` unknown
    - `critique` string
    - `parentJobId` string
    - `maxCandidates` integer
    - `budgetUsd` number
    - `qualityThreshold` number
  - `candidates` unknown[], required
    - unknown
  - `winner` object, nullable, required
    - `candidateIndex` integer, required
    - `compositionRunId` string, required
  - `listUsd` number
  - `startedAt` number, required
  - `completedAt` number, nullable, required
  - `advisoryResult` ConsultResult: The advisory envelope returned by a completed consult job (on ComposeJobDetailResponse.advisoryResult).
    - `mode` 'advise' | 'amend' | 'explore', required
    - `assessment` object: Grounded critique of the CURRENT composition. Omitted for mode=advise.
      - `editorial` object, required
        - `score` number, required
        - `grounding` 'measured' | 'judged', required
        - `abstained` boolean, required
        - `reliability` number
      - `spatial` object, required
        - `score` number, required
        - `grounding` 'measured' | 'judged', required
        - `abstained` boolean, required
        - `reliability` number
      - `brand` object, required
        - `score` number, required
        - `grounding` 'measured' | 'judged', required
        - `abstained` boolean, required
        - `reliability` number
      - `caption` object, required
        - `score` number, required
        - `grounding` 'measured' | 'judged', required
        - `abstained` boolean, required
        - `reliability` number
    - `proposals` object[], required
      - `label` string, required
      - `candidateIndex` integer: Present for amend/explore — adopt via POST /compose/jobs/:jobId/select with this candidateIndex. Absent for advise.
      - `changeSummary` string[], required: Human-legible edit-pattern labels.
      - `boundToEtag` string: The composition etag this proposal was computed against.
      - `expectedDelta` object: Advisory per-criterion score lift; NOT authoritative pre-recalibration.
    - `principles` string[], required: Reusable, grounded lessons for the client's next authoring.
    - `plan` unknown
    - `checkpointId` string: The durable kind:'score' Checkpoint minted from this advisory (evidence convergence — get_checkpoint re-reads the envelope later). Stamped at the consult success terminal.
  - `checkpoint` object
    - `checkpointId` string, required
    - `stage` 'content' | 'layout' | 'motion', required
    - `version` integer, required

## Other responses

- `400`: Bad request — validation_error / invalid_cursor / invalid_query.
- `401`: Missing or invalid Authorization header.
- `402`: Payment required. Returned when the caller presents no API key on a priced operation: the body AND the `Payment-Required` header carry the x402 v2 challenge (accepted scheme, network, USDC asset, amount, payTo). Sign the EIP-3009 authorization and retry with a `PAYMENT-SIGNATURE` header. A KEYED caller sees this status instead when their plan lacks or has exhausted the feature (`billing_required`).
- `403`: Forbidden — permission insufficient.
- `404`: Resource not found.
- `422`: Unprocessable — invalid_composition / media_in_use / session_in_use / render_not_cancellable.
- `429`: Rate limited. Retry-After header present.
- `500`: Internal error.
- `503`: Service unavailable — billing_unavailable / honest-503 for runtime deps.

---

[API](https://skmtc.dev/cueframe/apis/cueframe-api.md) · [All operations](https://skmtc.dev/cueframe/apis/cueframe-api/llms.txt) · [OpenAPI document](https://skmtc.dev/cueframe/apis/cueframe-api/revisions/8f9bfe362b4a?raw)
