> ## 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.

# SDKs

> Call the ZeroGen API from TypeScript, JavaScript, or Python with the official libraries.

ZeroGen publishes official libraries for TypeScript and JavaScript,
[`@zerogen/sdk`](https://www.npmjs.com/package/@zerogen/sdk), and for Python,
[`zerogen`](https://pypi.org/project/zerogen/). Their types come from the
API's [OpenAPI document](https://api.zerogen.com/v1/openapi.json), and they
follow the conventions in these docs for you:

* They send an `Idempotency-Key` with every `POST`, and reuse it when they
  retry.
* They retry connection failures and errors whose `retryable` is `true`, and
  wait for `Retry-After` on a `429`.
* They wait for a run to end with `Prefer: wait`.
* They page through lists, and upload a file in one call.

Both libraries run on servers:

| Library | Runs on | Source |
| - | - | - |
| `@zerogen/sdk` | Node.js 20.3 or later, Deno, Bun, and edge runtimes such as Cloudflare Workers. It has no dependencies. | [zerogen-typescript](https://github.com/zerogeneration/zerogen-typescript) |
| `zerogen` | Python 3.10 or later, with a synchronous and an asynchronous client. It's built on httpx and pydantic. | [zerogen-python](https://github.com/zerogeneration/zerogen-python) |

In other languages, call the REST API directly. The
[API reference](https://docs.zerogen.com/api-reference/overview.md) and the OpenAPI document describe
every endpoint.

## Install

```bash npm theme={null}
npm install @zerogen/sdk
```

```bash pip theme={null}
pip install zerogen
```

## Create a run

Set your API key as `ZEROGEN_API_KEY`, then create a run and wait for it to
end:

```ts TypeScript theme={null}
import ZeroGen from "@zerogen/sdk";

const zerogen = new ZeroGen(); // Reads ZEROGEN_API_KEY.

const run = await zerogen.runs.createAndWait({
  model: "openai/gpt-image-2/generate",
  prompt: "A lighthouse at dawn, in watercolor",
});

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

```python Python theme={null}
from zerogen import ZeroGen

zerogen = ZeroGen()  # Reads ZEROGEN_API_KEY.

run = zerogen.runs.create_and_wait(
    {"model": "openai/gpt-image-2/generate", "prompt": "A lighthouse at dawn, in watercolor"}
)

print(run.status, run.outputs)
```

`createAndWait`, or `create_and_wait` in Python, creates the run with
`Prefer: wait=60`, then reads it with the same wait until it ends. It returns
for every final status, including `failed`, so check `status` and each
output's `status`. To return without waiting, call `runs.create`, then
`runs.get` or `runs.waitFor` (`wait_for` in Python) with the run's ID. To stop
waiting, pass an `AbortSignal` as `signal` in TypeScript, or cancel the task in
async Python; the run keeps going.

In Python, a request body is a dict with the API's own field names, such as
`projectId`, as the API reference shows them. Each response is a pydantic
model with snake\_case attributes, such as `run.project_id`. The
asynchronous client, `AsyncZeroGen`, has the same methods to `await`.

Each model takes its own inputs and parameters. Read a model's request schema
with `zerogen.models.get("openai/gpt-image-2/generate")`. For details, see
[Models in the API](https://docs.zerogen.com/developers/models.md).

## Upload an input

`uploads.upload` runs the three requests in
[Upload a file](https://docs.zerogen.com/developers/uploads.md#upload-a-file) and returns the ready asset's ID:

```ts TypeScript theme={null}
import { openAsBlob } from "node:fs";

const upload = await zerogen.uploads.upload(await openAsBlob("storyboard.png"), {
  filename: "storyboard.png",
});

const edit = await zerogen.runs.createAndWait({
  model: "openai/gpt-image-2/edit",
  prompt: "Turn the sky into a sunset",
  inputs: [{ role: "source", asset: upload.assetId }],
});
```

```python Python theme={null}
upload = zerogen.uploads.upload("storyboard.png")

edit = zerogen.runs.create_and_wait(
    {
        "model": "openai/gpt-image-2/edit",
        "prompt": "Turn the sky into a sunset",
        "inputs": [{"role": "source", "asset": upload.asset_id}],
    }
)
```

In TypeScript, it takes a `Blob`, `File`, `ArrayBuffer`, or `Uint8Array`, and
reads the media type from the file or from the filename's extension. For files
up to 64 MiB, it sends the file's SHA-256 digest. In Python, it takes a path,
`bytes`, or a binary file object that can seek, reads the media type from the
filename's extension, and always sends the digest. With the digest, a file the
project already has is reused instead of uploaded again.

## Download outputs

The libraries cover models, runs, and uploads. To download an output's file, or
to browse your Library, call the REST API: read
`GET /v1/assets/{assetId}/download` with the output's `asset.id`, using a key
with the `library:read` scope. For details, see
[Download your outputs](https://docs.zerogen.com/developers/quickstart.md#download-your-outputs).

## List

Iterate a list to read every item on every page:

```ts TypeScript theme={null}
for await (const model of zerogen.models.list({ capability: "video" })) {
  console.log(model.id);
}
```

```python Python theme={null}
for model in zerogen.models.list(capability="video"):
    print(model.id)
```

In TypeScript, awaiting a list instead returns one page, with `data` and
`nextCursor`. In Python, a list method returns the first page, with `data` and
`next_cursor`. With `AsyncZeroGen`, iterate a list with `async for`, or await
it for one page.

## Handle errors

A request that ZeroGen refuses fails with a `ZeroGenError`, which carries the
[error envelope](https://docs.zerogen.com/developers/errors.md): `status`, `code`, `param`, `retryable`, `details`,
and the response's request ID, as `requestId` in TypeScript and `request_id`
in Python. Branch on `code`:

```ts TypeScript theme={null}
import ZeroGen, { ZeroGenError } from "@zerogen/sdk";

try {
  await zerogen.runs.create({
    model: "openai/gpt-image-2/generate",
    prompt: "A lighthouse at dawn, in watercolor",
  });
} catch (error) {
  if (error instanceof ZeroGenError && error.code === "insufficient_balance") {
    // Ask an Owner or Admin to add funds.
  }
  throw error;
}
```

```python Python theme={null}
from zerogen import ZeroGenError

try:
    zerogen.runs.create(
        {"model": "openai/gpt-image-2/generate", "prompt": "A lighthouse at dawn, in watercolor"}
    )
except ZeroGenError as error:
    if error.code == "insufficient_balance":
        ...  # Ask an Owner or Admin to add funds.
    raise
```

A request that gets no response, because the connection failed or timed out,
fails with a `ZeroGenConnectionError`.

## Retries and idempotency

The libraries retry a request twice by default. They retry only connection
failures and errors whose `retryable` is `true`, and they don't wait for a
`Retry-After` longer than one minute. Each `POST` call gets a new
`Idempotency-Key`, which that call's retries reuse.

To retry safely across calls or processes, such as from a job queue, pass your
own key:

```ts TypeScript theme={null}
await zerogen.runs.create(job.request, { idempotencyKey: job.id });
```

```python Python theme={null}
zerogen.runs.create(job.request, idempotency_key=job.id)
```

For details, see [Idempotency](https://docs.zerogen.com/developers/idempotency.md).

## Configure the client

| TypeScript | Python | Default | Description |
| - | - | - | - |
| `apiKey` | `api_key` | `ZEROGEN_API_KEY` | The API key. |
| `baseURL` | `base_url` | `ZEROGEN_BASE_URL`, then `https://api.zerogen.com/v1` | The API's base URL. |
| `maxRetries` | `max_retries` | `2` | Retries for each request. |
| `timeout` | `timeout` | `120000` milliseconds in TypeScript, `120` seconds in Python | How long an attempt can take before it's abandoned. In Python, it's httpx's timeout for each step of the attempt. A request that waits for a run gets its wait added. |
| `fetch` | `http_client` | The global `fetch`, or a new httpx client | The HTTP client to send requests with. |
| `defaultHeaders` | `default_headers` | None | Headers to send with every request. |

Every method also takes request options. In TypeScript, they're its last
argument: `signal`, `timeout`, `maxRetries`, `idempotencyKey` for a `POST`,
and `headers`. In Python, they're keyword arguments: `timeout`, `max_retries`,
`idempotency_key` for a `POST`, and `headers`.


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