---
title: Documentation
eyebrow: Getting started
description: "One REST API for image, video, audio and 3D generation: the same API behind nolgia.ai, the nolgia CLI, the MCP server and the NOLGIA Agent."
---

# Build with Nolgia

One API for image, video, audio and 3D generation. Authenticate with a Personal Access Token, then submit a generation as a job you can poll, long-poll or stream. Quote the price before you spend. The base URL is `https://api.nolgia.ai/v1`.

:::cards
- [Model APIs](guides/models.html) icon=spot-library: Find a model, quote its price and run it through the API.
- [Agent Sessions API](guides/agent-api.html) icon=spot-agent: Build persistent conversations that generate media.
- [The CLI](guides/cli.html) icon=spot-terminal: Generate and manage media from your terminal.
- [API reference](api/) icon=spot-keys: Every endpoint and schema, rendered from the OpenAPI spec.
:::

## Start with a model API call

Set `NOLGIA_TOKEN` to your Personal Access Token, submit an image, wait for the job, and download the file. Start with [Model APIs](guides/models.html) for the catalog and calling methods. These are the programs that ran against production with the published packages on 2026-09-20; the [Quickstart](guides/getting-started.html) adds the video step.

```bash tab="curl"
$ curl -sS https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"flux-pro","prompt":"a paper-cut mountain range at dawn"}'
$ curl -sS "https://api.nolgia.ai/v1/jobs/<id from the response>/wait?timeout_seconds=120" \
  -H "Authorization: Bearer $NOLGIA_TOKEN"
$ curl -sS -o first.png "<asset.signed_url from the finished job>"
```

```ts tab="TypeScript"
import { writeFile } from "node:fs/promises";
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);

async function finish(id: string, timeout: number) {
  for (;;) {
    const { data, response } = await nolgia.GET("/jobs/{id}/wait", {
      params: { path: { id }, query: { timeout_seconds: timeout } },
    });
    if (response.status === 408) continue; // the wait window closed; the job is still running
    if (data?.status === "succeeded" && data.asset) return data.asset;
    throw new Error(`job ${id} ended ${data?.status ?? response.status}`);
  }
}

async function download(url: string, file: string) {
  await writeFile(file, Buffer.from(await (await fetch(url)).arrayBuffer()));
}

const { data: image, error } = await nolgia.POST("/generate/image", {
  body: { model: "flux-pro", prompt: "a paper-cut mountain range at dawn", num_images: 1 },
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
await download((await finish(image.id, 120)).signed_url, "first.png");
console.log("image job", image.id, "-> first.png");
```

```python tab="Python"
import os
import httpx
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.api.jobs import wait_for_job
from nolgia.models import GenerateImageRequest, ImageModel, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])


def finish(job_id, timeout):
    while True:
        response = wait_for_job.sync_detailed(job_id, client=client, timeout_seconds=timeout)
        if response.status_code == 408:  # the wait window closed while the job was still running
            continue
        done = response.parsed
        if isinstance(done, Job) and done.status == "succeeded":
            return done.asset
        raise SystemExit(f"job {job_id} {getattr(done, 'status', done)}")


def download(url, path):
    with open(path, "wb") as f:
        f.write(httpx.get(url).content)


job = generate_image.sync(client=client, body=GenerateImageRequest(model=ImageModel("flux-pro"), prompt="a paper-cut mountain range at dawn"))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
download(finish(job.id, 120).signed_url, "first.png")
print("image job", job.id, "-> first.png")
```

## How a generation runs

![Submit a generation, wait while it runs, then read the result](assets/diagrams/job-lifecycle.svg)

A generation returns a job that moves from `queued` to `running`, then reaches `succeeded`, `failed` or `canceled`. Read [Jobs](guides/jobs.html) to follow its status and retrieve the finished asset.

## Clients

<!-- gen:sdk-versions -->
| Client | Package | Version |
| --- | --- | --- |
| TypeScript | `@nolgia/sdk` | 0.1.4 |
| Python | `nolgia` on PyPI | 0.1.4 |
| Rust | `nolgia-client` | published with the CLI release; see crates.io |
<!-- /gen -->

## Where next

:::cards
- [Quick Start](guides/getting-started.html) icon=spot-library: Get a token and generate your first image and video.
- [Why Nolgia](guides/why-nolgia.html) icon=spot-jobs: Read the API's job, pricing and refund model.
- [Run MCP](guides/mcp.html) icon=spot-terminal: Generate from inside your coding agent's conversation.
- [Agent Sessions API](guides/agent-api.html) icon=spot-agent: Create persistent conversations and collect their assets.
- [API reference](api/) icon=spot-keys: Read every endpoint and schema.
:::
