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

# Quickstart

> Create a generation, wait for it to finish, and read its result.

This quickstart creates an image generation, holds the request open until the
image is ready, and then reads the generation again by its ID.

> [!TIP]
>
> In TypeScript or JavaScript, the [SDK](https://docs.zerogen.com/sdks.md) runs this whole flow with one
> call to `generations.createAndWait`.

## Before you begin

* Your organization must be in the API private beta.
* Create an API key in ZeroGen under **Settings → API keys**. The key needs the
  `generations:create` and `generations:read` scopes. A
  [test key](https://docs.zerogen.com/test-keys.md) runs the same requests on placeholder media at no
  charge, so start with one.
* Store the key in an environment variable on your server:

  ```bash theme={null}
  export ZEROGEN_API_KEY="zg_test_..."
  ```

## Create and read a generation

**1. Check your key**

Read the calling key's own access. This request needs no scope.

```bash theme={null}
curl https://api.zerogen.com/v1/me \
  -H "Authorization: Bearer $ZEROGEN_API_KEY"
```

The response names the key's mode (`live` or `test`), the scopes it can use
now, and its organization. For details, see
[Authentication](https://docs.zerogen.com/authentication.md).

**2. Create a generation and wait for it**

Send the model ID and a prompt to `POST /v1/generations`. The
`Prefer: wait=60` header holds the response for up to 60 seconds while the
generation runs. The `Idempotency-Key` header makes the request safe to
retry; use a new key for each new generation.

```bash theme={null}
curl https://api.zerogen.com/v1/generations \
  -H "Authorization: Bearer $ZEROGEN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f0e8b52-1c4d-4f7a-9b2e-6d5c4a3b2f10" \
  -H "Prefer: wait=60" \
  -d '{
    "model": "openai/gpt-image-2/generate",
    "prompt": "A lighthouse at dawn, in watercolor"
  }'
```

ZeroGen validates the request against the model's schema, prices it, holds
the quoted amount, and starts the work, all in this one call. Nothing is
charged unless every check passes.

* If the generation ends within the wait, the response is `200`.
* Otherwise, the response is `202` with the generation's current state.

Either way, the `Location` header gives the generation's path, such as
`/v1/generations/0b7f2c1e-5d4a-4c3b-9a8f-7e6d5c4b3a21`.

**3. Read the generation until it ends**

Read the generation by its ID. Add `Prefer: wait=N`, up to 60 seconds, to
hold the response until the generation ends or the wait runs out.

```bash theme={null}
curl https://api.zerogen.com/v1/generations/0b7f2c1e-5d4a-4c3b-9a8f-7e6d5c4b3a21 \
  -H "Authorization: Bearer $ZEROGEN_API_KEY" \
  -H "Prefer: wait=60"
```

A read only reads the generation's stored state, so reading more often
doesn't add work or cost. Each read still counts toward your
[rate limits](https://docs.zerogen.com/rate-limits.md).

The following example shows an ended generation. The IDs and amounts are
examples.

```json theme={null}
{
  "id": "0b7f2c1e-5d4a-4c3b-9a8f-7e6d5c4b3a21",
  "projectId": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
  "model": "openai/gpt-image-2/generate",
  "modelVersion": null,
  "status": "succeeded",
  "outputs": [
    {
      "index": 0,
      "status": "succeeded",
      "asset": {
        "id": "9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b",
        "mimeType": "image/png",
        "width": 1024,
        "height": 1024,
        "durationMs": null
      },
      "error": null
    }
  ],
  "error": null,
  "billing": {
    "mode": "platform",
    "state": "charged",
    "quotedMicroUsd": 42000,
    "heldMicroUsd": null,
    "chargedMicroUsd": 42000
  },
  "createdAt": "2026-10-21T17:04:05.000Z",
  "startedAt": "2026-10-21T17:04:05.000Z",
  "finishedAt": "2026-10-21T17:04:19.000Z"
}
```

## Generation statuses

A generation has one of the following statuses. The last four are final.

| Status | Meaning |
| - | - |
| `queued` | Accepted, and work hasn't started on any output. |
| `running` | Work has started, and at least one output hasn't ended. |
| `succeeded` | Every output succeeded. |
| `partial` | Some outputs succeeded and the others failed. |
| `failed` | Every output failed. |
| `cancelled` | The generation was cancelled. Outputs that finished first stay `succeeded`. |

Each output in `outputs` has its own `status`: `queued`, `running`,
`succeeded`, `failed`, or `cancelled`. A failed output carries an `error` in
the [error envelope](https://docs.zerogen.com/errors.md)'s shape.

## Poll from your code

The following Node.js example creates a generation and reads it until it ends,
without a library. It runs on Node.js 18 or later as an ES module. The
[SDK](https://docs.zerogen.com/sdks.md) does the same, with retries, in one call.

```javascript theme={null}
const API = "https://api.zerogen.com/v1";
const auth = { Authorization: `Bearer ${process.env.ZEROGEN_API_KEY}` };
const FINAL = new Set(["succeeded", "partial", "failed", "cancelled"]);

async function call(path, init = {}) {
  const response = await fetch(`${API}${path}`, init);
  const body = await response.json();
  if (!response.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
  return body;
}

let generation = await call("/generations", {
  method: "POST",
  headers: {
    ...auth,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
    Prefer: "wait=60",
  },
  body: JSON.stringify({
    model: "openai/gpt-image-2/generate",
    prompt: "A lighthouse at dawn, in watercolor",
  }),
});

while (!FINAL.has(generation.status)) {
  generation = await call(`/generations/${generation.id}`, {
    headers: { ...auth, Prefer: "wait=60" },
  });
}

console.log(generation.status, generation.outputs);
```

## Find your outputs

Each succeeded output's `asset.id` is an asset in your organization's Library,
in the generation's project. Your team can open and download it in ZeroGen,
and you can send the asset ID as an input to a later generation. For details,
see [Uploads and URL inputs](https://docs.zerogen.com/uploads.md).

## Next steps

* Read [Models](https://docs.zerogen.com/models.md) to find a model and the request schema it accepts.
* Read [Billing](https://docs.zerogen.com/billing.md) to understand `quotedMicroUsd`, holds, and charges.
* Read [Idempotency](https://docs.zerogen.com/idempotency.md) before you retry requests in production.


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