---
title: "Delete a drop"
method: DELETE
path: "/v1/engine/runs/{id}"
tags: ["Drops"]
---

# Delete a drop

`DELETE /v1/engine/runs/{id}`

## Request

- Base URL: `https://aicontentdrop.com`
- URL: `https://aicontentdrop.com/v1/engine/runs/{id}`
- Auth: HTTP bearer

Delete one drop and its transcript. Artifacts already delivered elsewhere — a board, a finished render — are not touched. Credits already charged are not affected either; there is nothing to give back, because a step only charges once it has succeeded.

## Path parameters

- `id` string, uuid, required

## Response `200`

The drop was deleted.

- DropDeleted
  - `success` boolean, required
  - `run` DropRun: One drop, as every caller sees it. `phase` is a property of the drop, never a place to navigate to; `revision` is bumped by every write and is what a conditional write is checked against.
    - `id` string, uuid, required
    - `title` string, required
    - `goal` string, required
    - `phase` 'intake' | 'research' | 'concept' | 'plan' | 'produce' | 'assemble' | 'distribute' | 'done', required
    - `status` 'idle' | 'running' | 'waiting_input' | 'waiting_approval' | 'failed' | 'done' | 'cancelled', required
    - `lane` 'cinematic' | 'ugc' | 'marketing' | 'null', nullable: Which recipe this drop follows. Null while the lane is still a question.
    - `approvalMode` 'confirm_each', required: confirm_each is the only mode served: the drop stops before every step that would charge credits.
    - `budgetCredits` integer, nullable, required: The credit ceiling for the whole drop, or null for none. Approving a step cannot lift it.
    - `creditsQuoted` number, required
    - `creditsSpent` number, required: Credits charged so far. Work that failed charges nothing.
    - `revision` integer, required
    - `canvasId` string, nullable, required: The board this drop builds its artifacts on, once it has one.
    - `error` string, nullable
    - `entities` DropEntities, required: Everything a drop has made, keyed by kind and then by id. An artifact enters once and is referenced afterwards, so ids stay stable for the life of the drop. Instructions sent to a producer, internal model ids and job references are not part of this projection and never appear.
      - `brief` object: The settled brief: what is being made, for what, how long, on which recipe.
      - `videos` object
      - `images` object
      - `ads` object
      - `research` object: Competitor rows read for this drop. Each carries `demo` and `analysed` so a sample row is never shown as an observed one.
      - `concepts` object: Angles, each bound to the research ids it rests on.
      - `storyboards` object
      - `boards` object: The board this drop builds on, with its link.
      - `quotes` object
    - `counters` DropCounter[], required
      - `word` 'retrieved' | 'analysed' | 'selected' | 'generated' | 'checked', required
      - `count` integer, required: The number of ids below.
      - `label` string, required: What was counted, in the words a person reads.
      - `coverage` string: How it was measured, when the word alone would overstate it.
      - `bucket` 'brief' | 'videos' | 'images' | 'ads' | 'research' | 'concepts' | 'storyboards' | 'boards' | 'quotes', required: Which bucket of this drop's artifacts the ids live in.
      - `ids` string[], required
    - `shared` boolean, required: Whether this drop currently has a share link. The address itself is returned only to the POST that minted it.
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required

## Other responses

- `401`: Missing, malformed, revoked, or budget-exhausted API key
- `404`: No drop with that id on this account — or the whole surface is absent, which is what an account that is not enabled for drops sees. Drops are available to accounts enabled for them; on those accounts every path below answers `{"error":{"code":"not_found"}}` and nothing else, so an unlisted caller cannot tell an enabled surface from an absent one. On an enabled account, this is a drop id that does not exist or is not yours.
- `409`: The drop is not in a state that allows this. `code` says which: `RUN_BUSY` (it is working on the last message), `RUN_FINISHED`, `REVISION_CONFLICT` (it changed while your request was in flight — read it again and repeat), `TASK_NOT_AWAITING_APPROVAL`, `QUOTE_UNKNOWN` (that step has no priced quote yet), or `QUOTE_EXPIRED` (the price lapsed, so nothing was released).
- `429`: Rate limited. Read Retry-After (header) or error.retry_after_seconds (body) — they carry the same number — and wait that long. Retrying sooner extends the window rather than shortening it.
- `500`: Unexpected failure on our side. Retry once; nothing was charged.

---

[API](https://skmtc.dev/aicontentdrop/apis/ai-content-drop-api.md) · [All operations](https://skmtc.dev/aicontentdrop/apis/ai-content-drop-api/llms.txt) · [OpenAPI document](https://skmtc.dev/aicontentdrop/apis/ai-content-drop-api/revisions/75a13a8043ae?raw)
