AI Content Drop Drops API
A drop is one piece of work that runs from research through concepts, a plan, generation and assembly without the caller moving it between endpoints. Available to accounts enabled for drops; every path here answers `404 not_found` on an account that is not, so an unlisted caller cannot tell the surface apart from one that does not exist. **One verb.** POST /v1/engine/chat is the only endpoint that does work: research, concepts, a storyboard, a board, a render or a scheduled post are all asked for in words, and the engine picks the phase itself. The rest read a drop or a reference, answer a question, decide a spend, act on one thing a drop made, or stop it. **Nothing spends without a decision.** A step that would charge credits is priced with a signed quote and parked until POST /v1/engine/runs/{id}/approve answers it. The quote fixes the credit ceiling and lapses after a few minutes; a lapsed quote is refused and the engine prices the step again by itself, so read the drop for the current `quote_id` rather than asking for the step a second time. Credits are charged only when a step succeeds. A request that could release a charge needs an API key with the `generations:create` scope, and one without it is answered 403 `INSUFFICIENT_SCOPE`. Starting a drop needs the Professional plan or higher (402 `PLAN_REQUIRED`), and messages and new drops are counted per account per day (429 `DAILY_LIMIT`, with `reset_at`). `X-Sandbox: true` is refused on every path here with 400 `SANDBOX_UNSUPPORTED`: opening a drop costs nothing by itself, so there is nothing to rehearse. **From a reference.** POST /v1/engine/analyze reads an image or a clip the caller has the rights to into words: the shots, the cast, the look, any lines, and a reference class. It costs no credits, is capped per account per day, needs `canvas:write` on an API key, and never returns the media (the file is deleted once it is read); GET /v1/engine/references/{id} reads the words back. An image or a clip of up to 30 seconds is answered with the words; a longer clip is answered 202 and read in the background, and GET /v1/engine/references/{id} reaches `ready`, or `failed` with `error_message`, by itself. To make something from it, send the first message to POST /v1/engine/chat with `brief.reference` set to `{"kind": "upload", "url": }`: the drop takes the reading as its first step, at no charge. A drop started while a long clip is still being read waits for that reading, and reads the clip itself if the background reading was lost. Sending the `facts` back as `brief.reference_facts` skips that step; both `brief.reference_class` and `brief.reference_facts` are dropped while reference reading is off for the account. `features.reference_intake` on GET /v1/engine/lanes says whether this account may send references. **Reviewed pieces.** Where `features.judge` is on, each finished video, image and ad carries `review`: a 0-100 score, a verdict, the reasons and the notes. A retry the review proposes is an ordinary step in `tasks`, with `retry_of` naming the step it makes again; it waits for POST /v1/engine/runs/{id}/approve with its own quote like every other step, and `review.retry_task_id` names it. When there is no retry step, `review.offer` names another model by its product label, and the piece's `actions` list carries the matching `try-model-…` action for POST /v1/engine/runs/{id}/actions/{actionId}. **Live narration.** Two routes answer `text/event-stream` and are not listed as JSON operations, because a function-calling client built from this document would wait on them forever: POST /v1/engine/chat with any Accept other than `application/json`, and GET /v1/engine/runs/{id}/stream, which re-attaches to a drop already in flight and closes by itself after 30 minutes. Both emit the same events (`started`, `phase`, `thinking`, `status`, `tool_start`, `tool_progress`, `tool_complete`, `artifact_ready`, `answer_delta`, `answer_reset`, `questions`, `approval_required`, `followups`, `error`, `done`); a lost connection never cancels a drop. A browser can follow a drop live at GET /v1/engine/runs/{id}/stream (text/event-stream); agents send `Accept: application/json` to POST /v1/engine/chat and poll getDrop (GET /v1/engine/runs/{id}).