---
title: "Cancel an analysis (best-effort once analyzing)"
method: POST
path: "/v1/analyses/{id}/cancel"
tags: ["analyses"]
---

# Cancel an analysis (best-effort once analyzing)

`POST /v1/analyses/{id}/cancel`

## Request

- Base URL: `https://api.primateintelligence.ai`
- URL: `https://api.primateintelligence.ai/v1/analyses/{id}/cancel`
- Auth: HTTP bearer

## Path parameters

- `id` string, required

## Response `200`

Canceled (or best-effort race documented in §14.2).

- Analysis: A video analysis (§13.2).
  - `id` string, required: Analysis resource id (prefixed ULID).
  - `object` 'analysis', required
  - `livemode` boolean, required: true when the request used a live key; false for test keys and sandbox. Stripe-style.
  - `origin` 'api' | 'console' | 'system', required: `api` — submitted via the public API; `console` — uploaded via the dashboard; `system` — generated internally (e.g. auto-probe, fixture seeding, run_prompt). System analyses are never billed. Agents should normally only process api/console-origin analyses. (Renamed 2026-07-27: former value `user` is now `api`.)
  - `status` 'queued' | 'preparing' | 'analyzing' | 'rendering' | 'completed' | 'failed' | 'canceled', required: Analysis lifecycle state (§14.2). Clients MUST tolerate unknown future non-terminal values.
  - `video_id` string, required: Video resource id (prefixed ULID). Immutable.
  - `prompt` string, nullable, required
  - `query` object, required: CompiledQuery (schema at /v1/schemas/compiled-query.json). Always populated in responses.
  - `parse_mode` 'llm' | 'heuristic' | 'client', nullable, required
  - `model` string, required
  - `options` object, required
    - `narrative` boolean
  - `progress` Progress, nullable, required: Non-terminal only. percent is monotonic non-decreasing per analysis.
    - `stage` string, required
    - `percent` number, required
  - `queue_position` integer, nullable, required
  - `result` Result, nullable, required: Analysis result — the product (§13.3). Reserved (always absent in v1): masks, bounding_boxes, events.
    - `answer` 'yes' | 'no' | 'indeterminate', required
    - `confidence` number, required
    - `clips` Clip[], required
      - `start_s` number, required
      - `end_s` number, required
      - `confidence` number, required
      - `terms` object, required
    - `term_confidences` object, required
    - `query_type` 'object' | 'action' | 'compound' | 'attribute' | 'open_ended', required
    - `video_duration_s` number, nullable, required
    - `detected_count` integer, nullable
    - `indeterminate_reason` 'low_confidence' | 'nothing_detected' | 'unsupported_query_form' | 'duration_mismatch' | 'unsupported_action_term', nullable
    - `unsupported_action` object: PRI-516: present only when the prompt requested something the model cannot detect/score. Absent otherwise — never null.
      - `reason` string, required: Why the request could not be scored.
      - `docs_url` string, required: The supported-actions capability list — what the model can and cannot detect.
  - `narrative` Narrative, nullable, required
    - `status` 'generating' | 'ready' | 'failed', required
    - `entries` object[], required
      - `t_s` number, required
      - `text` string, required
  - `artifacts` Artifacts, nullable, required: Signed URL TTL 1h; re-fetch GET analysis for a fresh URL.
    - `annotated_video_url` string, uri, required
    - `expires_at` string, date-time, required
  - `error` ErrorObject, nullable, required
    - `code` string, required
    - `message` string, required
  - `metering_rule` 'per_second' | 'per_frame': PRI-552: settlement rule pinned at admission. Resources created before the cutover report per_second.
  - `usage` AnalysisUsage, nullable, required: Terminal only. credit_balance_after is the balance immediately after THIS analysis settled — an immutable point-in-time snapshot; it does not change as later analyses run. Null when the account row is unavailable (e.g. free-grant exhausted before settlement). billed_seconds is the settled ledger amount, derived from the processed-frame count for per_frame rows (PRI-552); historical per_second rows carry their original clock-derived amount.
    - `billed_seconds` integer, required
    - `credit_balance_after` integer, nullable, required
    - `metering_rule` 'per_second' | 'per_frame': PRI-552: the rule this analysis settled under. Mirrors the top-level metering_rule for a self-contained terminal summary.
    - `frames` integer, nullable: PRI-552: processed-frame count reported by the inference callback (cost telemetry). Present for both metering rules when available; null when the callback did not carry it.
  - `rerun_eligible` boolean: PRI-493: present on failed analyses — true when this analysis qualifies for ONE free re-run (it failed during a platform incident, or was flagged by ops). POST /v1/analyses/{id}/rerun creates a fresh analysis at no charge. Absent on non-failed analyses.
  - `metadata` object: Free-form key/value metadata. ≤16 keys, key ≤40 chars [a-zA-Z0-9_.-], value ≤500 chars.
  - `created_at` string, date-time, required
  - `started_at` string, date-time, nullable, required
  - `completed_at` string, date-time, nullable, required

## Other responses

- `400`: validation_failed / url_forbidden / prompt errors (§15)
- `401`: invalid_api_key / key_revoked / key_expired
- `404`: resource_not_found (account-scoped; no existence oracle)
- `409`: resource_conflict / idempotency_key_reused / idempotency_unavailable
- `429`: rate_limit_exceeded / concurrency_limit_exceeded / quota_exceeded (always with Retry-After)

---

[API](https://skmtc.dev/primateintelligence/apis/primate-vision-api.md) · [All operations](https://skmtc.dev/primateintelligence/apis/primate-vision-api/llms.txt) · [OpenAPI document](https://skmtc.dev/primateintelligence/apis/primate-vision-api/revisions/aa51b01dc8ad?raw)
