Getting started
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.
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 for the catalog and calling methods. The TypeScript and Python programs ran against production with the published packages on 2026-09-20, and the Rust one uses the nolgia crate's subscribe helper; the Quickstart adds the video step.
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>"
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");
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")
use nolgia::tokio;
#[tokio::main]
async fn main() -> nolgia::Result<()> {
let nolgia = nolgia::Client::from_env()?;
let image = nolgia
.subscribe(nolgia::image("flux-pro", "a paper-cut mountain range at dawn"))
.await?;
nolgia.download(image.url().expect("an image"), "first.png").await?;
println!("image job {} -> first.png", image.job.id);
Ok(())
}
How a generation runs #
A generation returns a job that moves from queued to running, then reaches succeeded, failed or canceled. Read Jobs to follow its status and retrieve the finished asset.
Clients #
| Client | Package | Version |
|---|---|---|
| TypeScript | @nolgia/sdk |
0.1.4 |
| Python | nolgia on PyPI |
0.1.4 |
| Rust | nolgia on crates.io |
0.1.0 |

