> ## Documentation Index
> Fetch the complete documentation index at: https://askeditor.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Jobs & polling

> Async by design: run returns a job id; the job resolves to the mp4 and the canvas.

Video work takes seconds to minutes, so the API is **queue-first**:

```
queued templates:  run → { jobId }, then GET /v1/jobs/{jobId} until done
sync templates:    POST /v1/run/{id} holds open and RETURNS the result
```

`remove-background` is synchronous: no polling at all. `tighten` and
`launch-cut` are queued and resolve through the jobs envelope.

## Job states

`queued → running → completed | refused | failed`

* `completed` carries the full envelope: `finalUrl`, `canvasUrl`,
  `recipeVersion`, timings.
* `refused` carries a [typed reason](/docs/setting-up/refusals): free.
* `failed` is on us: see
  [Infrastructure errors](/docs/setting-up/infrastructure-errors); failed jobs
  are not charged.

## Estimate first

`GET /v1/estimate?recipeId={id}` is free and returns
`{ credits, etaSeconds, creditsRemaining, blockers[] }` with typed blockers
(`INSUFFICIENT_CREDITS`, `IN_FLIGHT`, `SCOPE_DENIED`,
`RECIPE_NOT_ALLOWED`, `SPEND_CAP_REACHED`). Agents should estimate, ask consent, then run.

<Note>
  An estimate validates the PRICE and your ACCOUNT (credits, scopes, in-flight
  caps), not your material: material checks (duration, readability, subject
  presence) happen at run time, and when they fail you get a free typed
  refusal, never a charge.
</Note>

## Polling etiquette

Poll every 5-15s; each template page posts an `etaSeconds` to calibrate
expectations. Webhooks (`callback_url`) are on the roadmap for
fire-and-forget integrations.
