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

# Polling & wait

> How to wait for a job to finish, efficiently.

Generation is asynchronous. A create call returns `202` with a job in `status: "pending"`; you then
wait for it to reach a terminal status (`completed` or `failed`).

## Long-poll with `?wait=true` (recommended)

Add `?wait=true` to `GET /jobs/{id}` to hold the connection until the job is terminal, up to \~55s:

```bash theme={null}
curl "https://app.dafty.ai/api/v1/jobs/$JOB_ID?wait=true" -H "x-api-key: $DAFTY_API_KEY"
```

* If the job finishes within the window, you get the terminal job immediately.
* **On timeout you still get `200`** with the job in its current (possibly `processing`) state -
  just re-issue the same request to keep waiting. Image jobs usually finish in one wait; longer jobs
  may take a couple.

A simple loop:

```bash theme={null}
while :; do
  JOB=$(curl -s "https://app.dafty.ai/api/v1/jobs/$JOB_ID?wait=true" -H "x-api-key: $DAFTY_API_KEY")
  STATUS=$(echo "$JOB" | jq -r .data.status)
  [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ] && break
done
```

## Plain polling

Omit `wait` to get the job's current state immediately - `status` is `pending` (queued) or
`processing` (running) until it reaches a terminal `completed` / `failed`:

```json theme={null}
{ "data": { "id": "3f9a4c2e-...", "type": "image.generate", "status": "processing", "createdAt": "..." } }
```

If you poll without `wait`, space requests a few seconds apart and honor `Retry-After` on `429`
(see [Rate limits](/rate-limits)).

## Cancelling a job

`POST /jobs/{id}/cancel` aborts a pending or in-flight job and returns its (now `failed`) state.

<Note>
  If the job had **already started generating** when you cancel, a partial cancellation charge of **1
  CU** applies - the provider was already doing work. Cancelling a job that is still `pending` (not yet
  started) is free.
</Note>

## Firing many at once

Start N generations, collect their job ids, then poll each - there's no batch endpoint, and that's
fine: creates are cheap and return immediately. Use [Idempotency keys](/idempotency) so a retried
create doesn't double-charge, and `GET /jobs` to re-list your jobs if you lose an id.

<Note>
  There are no webhooks in v1 - completion is via polling / `?wait=true`.
</Note>
