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

# Requests

> How a job moves from submission to result.

Every generation is a **job**. You create it with `POST /jobs`, read it with `GET /jobs/{id}`, and it ends in one of three terminal statuses.

## Job lifecycle

| `status` | Meaning |
| - | - |
| `queued` | Accepted and waiting to run. The only status that can be canceled. |
| `processing` | The provider is working on it. `provider_status` holds the provider's own status, verbatim. |
| `completed` | Finished. `artifacts` holds the files. |
| `failed` | Failed. `error` says why; the unused hold is released. |
| `canceled` | Canceled before it ran. Nothing is charged. |

`completed`, `failed` and `canceled` are terminal: the job does not change after that.

## Submit

```bash theme={null}
curl https://api.blon.ai/v1/jobs \
  -H "Authorization: Bearer $BLON_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"model":"gpt-image-2","input":{"prompt":"A ceramic teapot on a linen table, soft morning light"},"webhook_url":"https://example.com/hooks/blon","metadata":{"order":"A-17"}}'
```

| Field | Required | Meaning |
| - | - | - |
| `model` | Yes | Model id from [`GET /models`](https://docs.blon.ai/models) |
| `input` | Yes | The model's inputs, keyed by input id |
| `webhook_url` | No | Public `https` URL notified when the job ends. See [Webhooks](https://docs.blon.ai/how-to/webhooks.md) |
| `metadata` | No | Your own JSON object, up to 1 KB, returned on the job |

A media input is `{ "asset_id": "…" }` or `{ "url": "https://…" }`. See [File uploads](https://docs.blon.ai/concepts/file-uploads.md).

## Initial response

A new job returns `202 Accepted` with a `Location` header pointing at the job and a `Retry-After` header equal to `next_poll_after_seconds`.

```json theme={null}
{
  "id": "cmh2x0f6k0001qv8z9d4c1a7e",
  "object": "job",
  "model": "gpt-image-2",
  "status": "queued",
  "provider_status": null,
  "queue_position": null,
  "cancelable": true,
  "next_poll_after_seconds": 5,
  "urls": {
    "get": "https://api.blon.ai/v1/jobs/cmh2x0f6k0001qv8z9d4c1a7e",
    "cancel": "https://api.blon.ai/v1/jobs/cmh2x0f6k0001qv8z9d4c1a7e/cancel"
  },
  "input": {
    "prompt": "A ceramic teapot on a linen table, soft morning light"
  },
  "metadata": {
    "order": "A-17"
  },
  "cost": {
    "currency": "CREDITS",
    "estimated": "8",
    "charged": null,
    "refunded": "0"
  },
  "usage": null,
  "artifacts": null,
  "expires_at": null,
  "error": null,
  "webhook": {
    "url": "https://example.com/hooks/blon",
    "status": "pending",
    "attempts": 0
  },
  "idempotency_hit": false,
  "request_id": "cmh2x0f6k0001qv8z9d4c1a7e",
  "created_at": "2026-10-30T08:00:00.000Z",
  "started_at": null,
  "completed_at": null,
  "updated_at": "2026-10-30T08:00:00.000Z"
}
```

| Field | Meaning |
| - | - |
| `urls.get` | Where to read the job |
| `urls.cancel` | Where to cancel it; `null` once it can no longer be canceled |
| `cancelable` | Whether a cancel would succeed now |
| `next_poll_after_seconds` | Minimum wait before the next read; `null` once terminal |
| `cost` | `estimated` at submission, `charged` once terminal (`"0"` for failed or canceled), `refunded` |
| `idempotency_hit` | `true` when the response replays an earlier job with the same `Idempotency-Key` |
| `request_id` | The request id |

Always decide by the `status` in the body, not by the HTTP status code: a replayed job returns `200` whatever its status.

## Completed output

```bash theme={null}
curl https://api.blon.ai/v1/jobs/cmh2x0f6k0001qv8z9d4c1a7e \
  -H "Authorization: Bearer $BLON_API_KEY"
```

```json theme={null}
{
  "id": "cmh2x0f6k0001qv8z9d4c1a7e",
  "object": "job",
  "model": "gpt-image-2",
  "status": "completed",
  "provider_status": "succeeded",
  "queue_position": null,
  "cancelable": false,
  "next_poll_after_seconds": null,
  "urls": {
    "get": "https://api.blon.ai/v1/jobs/cmh2x0f6k0001qv8z9d4c1a7e",
    "cancel": null
  },
  "input": {
    "prompt": "A ceramic teapot on a linen table, soft morning light"
  },
  "metadata": {
    "order": "A-17"
  },
  "cost": {
    "currency": "CREDITS",
    "estimated": "8",
    "charged": "8",
    "refunded": "0"
  },
  "usage": null,
  "artifacts": [
    {
      "id": "cmh2x0g2p0002qv8zb3n5k8wd",
      "name": "default",
      "type": "image",
      "url": "https://blon.ai/api/assets/cmh2x0g2p0002qv8zb3n5k8wd?ticket=…",
      "url_expires_at": "2026-10-30T08:15:00.000Z",
      "content_type": "image/png",
      "size_bytes": 1482113,
      "width": 1024,
      "height": 1024,
      "duration_ms": null
    }
  ],
  "expires_at": "2026-11-06T08:00:00.000Z",
  "error": null,
  "webhook": {
    "url": "https://example.com/hooks/blon",
    "status": "delivered",
    "attempts": 1
  },
  "idempotency_hit": false,
  "request_id": "cmh2x0f6k0001qv8z9d4c1a7e",
  "created_at": "2026-10-30T08:00:00.000Z",
  "started_at": "2026-10-30T08:00:01.000Z",
  "completed_at": "2026-10-30T08:00:09.000Z",
  "updated_at": "2026-10-30T08:00:09.000Z"
}
```

Each artifact has an `id`, which is a Blon asset id you can pass as `{ "asset_id": "…" }` to the next job, and a `url` signed for 15 minutes (`url_expires_at`). Every read of the job signs fresh URLs, so when one expires, read the job again.

Files created through the API are kept for 7 days; the job's `expires_at` shows when. After that `artifacts` is an empty list.

## List jobs

```bash theme={null}
curl "https://api.blon.ai/v1/jobs?limit=20&status=completed" \
  -H "Authorization: Bearer $BLON_API_KEY"
```

Jobs come newest first. Page with `limit` (1–100, default 20) and `starting_after` set to the previous page's `next_cursor`, while `has_more` is `true`. You can also filter by `status`, `model`, `created_after` and `created_before`. Jobs in a list do not include `artifacts`; read the single job for its files.

## Cancel a job

```bash theme={null}
curl -X POST https://api.blon.ai/v1/jobs/cmh2x0f6k0001qv8z9d4c1a7e/cancel \
  -H "Authorization: Bearer $BLON_API_KEY"
```

Only a `queued` job can be canceled. Anything else returns `409 job_not_cancelable`. A job already sent to the provider is not canceled.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.