Model APIs
Model APIs
On this page
Generate images, video, audio and 3D through the same API used by nolgia.ai. Choose a model from the catalog, send its inputs, and follow the returned job to a downloadable asset.
Quick example #
With a client installed and NOLGIA_TOKEN set, these Quick Start programs generate an image and download it as first.png.
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>"
nolgia gen image --model flux-pro --prompt "a paper-cut mountain range at dawn" --out first.png
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, generate_video
from nolgia.api.jobs import wait_for_job
from nolgia.models import GenerateImageRequest, GenerateVideoRequest, ImageModel, Job, VideoModel
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 std::num::NonZeroU64;
use nolgia_client::{types, ApiError, ClientBuilder};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = ClientBuilder::new("https://api.nolgia.ai/v1")
.bearer_token(std::env::var("NOLGIA_TOKEN")?)
.build()?;
let prompt: types::GenerateImageRequestPrompt = "a paper-cut mountain range at dawn".parse()?;
let job = client.generate_image()
.body_map(|b| b.model("flux-pro").prompt(Some(prompt)).num_images(1u64))
.send().await?.into_inner();
let asset = finish(&client, &job.id.to_string(), 120).await?;
std::fs::write("first.png", reqwest::get(&asset.signed_url).await?.bytes().await?)?;
println!("image job {} -> first.png", job.id);
Ok(())
}
/// Long-poll until the job settles. A 408 means the wait window closed while
/// the job was still running: wait again.
async fn finish(client: &nolgia_client::Client, id: &str, timeout: u64)
-> Result<nolgia_client::types::Asset, Box<dyn std::error::Error>> {
loop {
match client.wait_for_job().id(id.parse::<uuid::Uuid>()?).timeout_seconds(timeout).send().await {
Ok(response) => {
let job = response.into_inner();
return match (job.status.as_str(), job.asset) {
("succeeded", Some(asset)) => Ok(asset),
(status, _) => Err(format!("job {id} ended {status}").into()),
};
}
Err(ApiError::ErrorResponse(response)) if response.status() == 408 => continue,
Err(error) => return Err(error.into()),
}
}
}
The submit call answers 202 Accepted. This production response was captured on 2026-09-21; only the identifying fields are shown.
{
"id": "4a9b2242-f732-4a83-ba41-17448f5aa15f",
"status": "queued",
"model": "flux-pro",
"modality": "image",
"created_at": "2026-09-21T03:33:14.622149Z"
}
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | |
modality |
Modality |
Yes | |
model |
string | Yes | |
status |
JobStatus |
Yes | |
created_at |
string | Yes |
When that job finishes, reading it returns the asset. This is the matching production response, with download URLs shortened for readability; its lighthouse prompt belongs to the captured run, not the mountain prompt in the example.
{
"asset": {
"created_at": "2026-09-21T03:33:21.706691Z",
"display_name": "Lighthouse on a cliff",
"expires_at": "2026-09-21T05:00:00Z",
"favorite": false,
"has_audio": false,
"id": "f7bc037c-d7d7-434a-8843-26675574de0d",
"mime_type": "image/png",
"modality": "image",
"model": "flux-pro",
"prompt": "a lighthouse on a cliff, paper-cut style",
"signed_url": "https://storage.googleapis.com/nolgia-generations-prod/dad27b53-a85b-4e…",
"size_bytes": 418584,
"status": "ready",
"tags": [
],
"thumbnail_url": "https://storage.googleapis.com/nolgia-generations-prod/dad27b53-a85b-4e…",
"user_id": "dad27b53-a85b-4e3d-8fd6-b152c803a27c"
},
"completed_at": "2026-09-21T03:33:21.805937Z",
"created_at": "2026-09-21T03:33:14.622149Z",
"id": "4a9b2242-f732-4a83-ba41-17448f5aa15f",
"modality": "image",
"model": "flux-pro",
"status": "succeeded",
"updated_at": "2026-09-21T03:33:21.805937Z",
"user_id": "dad27b53-a85b-4e3d-8fd6-b152c803a27c"
}
| Field | Type | Required | Description |
|---|---|---|---|
status |
JobStatus |
Yes | |
asset |
Asset |
No | |
updated_at |
string | Yes | |
completed_at |
string, nullable | No |
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | |
prompt |
string, nullable | No | The prompt as the customer submitted it.… |
enhanced_prompt |
string, nullable | No | Image generations only: the server-composed prompt that was actually rendered, present only when it differs from prompt (the Aura layer enhanced the prompt, or a character's or element's canonical description was folded in).… |
signed_url |
string | Yes | Time-limited GCS signed URL for download.… |
expires_at |
string | Yes | Expiry of signed_url. |
mime_type |
string | No | |
width |
integer, nullable | No | |
height |
integer, nullable | No | |
duration_seconds |
number, nullable | No | Media duration in seconds for video/audio assets.… |
has_audio |
boolean, nullable | No | Whether the asset's media carries an audio stream.… |
Parameters #
The example supplies the image model and prompt, with one output requested by the TypeScript and Rust programs. Model-specific optional arguments and capability checks are covered in Common model arguments.
| Field | Type | Required | Description |
|---|---|---|---|
model |
ImageModel |
Yes | |
prompt |
string | No | What to generate.… |
num_images |
integer | No | How many images to render from this one request. Each one is billed, so four images cost four times one. The ceiling is per-model (image.num_images_max); most models allow four. |
Error responses #
| Response | What to do |
|---|---|
400 validation |
Correct an unsupported model or argument before retrying. |
401 |
Replace the invalid or expired token. |
402 out_of_credits |
Add credits or choose a generation your wallet can pay for. |
409 with job_id |
Follow the earlier job; this duplicate refusal is not billed. |
422 confirmation_rejected |
Re-quote if you supplied an expired or mismatched confirmation token. |
429 rate_limit |
Wait for capacity or the quota reset before resubmitting. |
408 timeout from wait |
Wait again; the generation may still be running. |
Read failure.code on an accepted job that later fails; Errors describes those outcomes separately from submit refusals.
How it works #
Every model generation returns a job. Your application chooses how to follow it; the job and its credit settlement are the same whichever method you use.
| Method | What happens | Guide |
|---|---|---|
subscribe() (TypeScript and Python 0.1.2; the Rust crate keeps its own) |
One helper submits, polls, and returns the completed result. | Synchronous: subscribe |
| Submit and poll | Submit once, retain the id, and read GET /jobs/{id} from any process. |
Asynchronous: submit and poll |
| Long-poll | GET /jobs/{id}/wait holds a request until completion or the wait window closes. |
Long-poll with wait |
| Status stream | GET /jobs/{id}/sse delivers status changes and a final event using a single-use ticket. |
Streaming |
| Provider callbacks | A signed provider callback wakes the poller; this is not a customer webhook. | Callbacks and webhooks |
| Agent | Create a conversation with POST /agent/sessions, then ask the agent to generate media. |
Agent Sessions API |
The blocking helper suits a script that needs one finished file before moving on. It ships in 0.1.2; the Quick Start implements the same submit-and-wait behavior with the published clients today.
Submit and poll fits a production worker that must release its HTTP connection immediately. Save the id before doing other work, then resume from that id after a process restart instead of submitting the generation again.
Long-polling reduces repeated status requests when your program can keep a connection open. A 408 closes only that wait window; call it again while the job is still running.
Status streaming is useful for displaying progress as it changes. The stream reports job state rather than progressive image, video or audio output; the result remains a finished file.
Provider callbacks improve how quickly the server notices completion without requiring a listener in your application. The server verifies the callback and reads the provider's authoritative result before settling the job.
The agent is useful when a conversation needs to choose inputs, plan work or make several assets. Its session transcript and generated assets remain available through the Agent Sessions API.
What you can generate #
The catalog below is generated from the model registry and published pricing. Use POST /jobs/cost for the exact quote for your request settings; a model's headline price is not a quote for every duration, resolution or output count.
| Image | Video | Audio | 3D |
|---|---|---|---|
| 48 | 74 | 17 | 2 |
Image #
Image models take a prompt, supported reference images and model-specific size or quality settings. They return an image asset, such as the PNG above, with width and height when known; read each model's capabilities before choosing optional arguments.
| Model id | Modality | Plan | Credits |
|---|---|---|---|
flux-2-flex |
image | starter | 6 per image |
flux-2-klein |
image | starter | 2 per image |
flux-2-max |
image | starter | 7 per image |
flux-2-pro |
image | starter | 2 per image |
flux-expand |
image | starter | 5 per image |
flux-kontext-max |
image | starter | 8 per image |
flux-kontext-pro |
image | starter | 4 per image |
flux-pro |
image | starter | 4 per image |
flux-schnell |
image | starter | 2 per image |
flux-ultra |
image | starter | 6 per image |
gpt-image-1 |
image | starter | 14 per image |
gpt-image-1.5 |
image | starter | 12 per image |
gpt-image-2 |
image | starter | 22 per image |
gpt-image-2.5-flare |
image | starter | 8 per image |
gpt-image-2.5-sunburst |
image | starter | 8 per image |
grok-imagine-image |
image | starter | 2 per image |
grok-imagine-image-2.0 |
image | starter | 4 per image |
grok-imagine-image-quality |
image | starter | 5 per image |
ideogram-v3 |
image | starter | 6 per image |
ideogram-v4 |
image | starter | 1 per image |
mai-image-2.5 |
image | starter | 6 per image |
mai-image-2.5-pro |
image | starter | 10 per image |
mai-image-2.6 |
image | starter | 6 per image |
mai-image-2.6-flash |
image | starter | 3 per image |
minimax-image-01 |
image | starter | 1 per image |
nano-banana-2 |
image | starter | 4 per image |
nano-banana-2-lite |
image | starter | 2 per image |
nano-banana-pro |
image | starter | 8 per image |
qwen-image-3 |
image | starter | 3 per image |
recraft-v2 |
image | starter | 3 per image |
recraft-v3 |
image | starter | 4 per image |
recraft-v4 |
image | starter | 4 per image |
recraft-v4-pro |
image | starter | 25 per image |
recraft-v4.1 |
image | starter | 4 per image |
recraft-v4.1-pro |
image | starter | 21 per image |
recraft-v4.1-utility |
image | starter | 4 per image |
recraft-v4.1-utility-pro |
image | starter | 21 per image |
remove-background |
image | starter | 1 per image |
riverflow-v2.5-fast |
image | starter | 2 per image |
riverflow-v2.5-pro |
image | starter | 14 per image |
seedream-4.5 |
image | starter | 3 per image |
seedream-v5-pro |
image | starter | 5 per image |
stable-diffusion-3.5 |
image | starter | 4 per image |
topaz-image-cgi |
image | starter | 7 per image |
topaz-image-high-fidelity |
image | starter | 7 per image |
topaz-image-low-resolution |
image | starter | 7 per image |
topaz-image-standard |
image | starter | 7 per image |
topaz-image-text |
image | starter | 7 per image |
Video #
Video models take a prompt and, where supported, images, video or audio references plus duration and quality settings. They return an MP4 asset with duration_seconds and has_audio metadata when known.
| Model id | Modality | Plan | Credits |
|---|---|---|---|
flux-3-video |
video | pro | 48 per clip (5 s) |
grok-imagine-video |
video | pro | 20 per clip (5 s) |
grok-imagine-video-1.5 |
video | pro | 41 per clip (5 s) |
happyhorse-1.0 |
video | pro | 28 per clip (5 s) |
happyhorse-1.0-video-edit |
video | pro | 36 per clip (5 s) |
happyhorse-1.1 |
video | pro | 28 per clip (5 s) |
happyhorse-1.1-r2v |
video | pro | 36 per clip (5 s) |
heygen-avatar-iv |
video | pro | 14 per clip (5 s) |
kling-avatar |
video | pro | 16 per clip (5 s) |
kling-o1 |
video | pro | 24 per clip (5 s) |
kling-v2-5-turbo |
video | pro | 12 per clip (5 s) |
kling-v2-6 |
video | pro | 12 per clip (5 s) |
kling-v3-i2v |
video | pro | 35 per clip (5 s) |
kling-v3-motion-control |
video | pro | 35 per clip (5 s) |
kling-v3-omni |
video | pro | 24 per clip (5 s) |
kling-v3-omni-audio |
video | pro | 32 per clip (5 s) |
kling-v3-pro-i2v |
video | pro | 47 per clip (5 s) |
kling-v3-pro-t2v |
video | pro | 47 per clip (5 s) |
kling-v3-t2v |
video | pro | 35 per clip (5 s) |
kling-v3-turbo |
video | pro | 32 per clip (5 s) |
minimax-h3 |
video | pro | 65 per clip (5 s) |
minimax-h3-max-i2v |
video | pro | 23 per clip (5 s) |
minimax-h3-max-t2v |
video | pro | 23 per clip (5 s) |
minimax-hailuo-2.3 |
video | pro | 28 per clip (5 s) |
minimax-hailuo-2.3-fast |
video | pro | 16 per clip (5 s) |
omni-1.1-flash |
video | pro | 50 per clip (5 s) |
omni-1.1-flash-edit |
video | pro | 50 per clip (5 s) |
remove-background-video |
video | starter | 14 per clip (5 s) |
runway-aleph-2 |
video | pro | 78 per clip (5 s) |
runway-gen-4.5 |
video | pro | 34 per clip (5 s) |
seedance-1-5-pro |
video | pro | 15 per clip (5 s) |
seedance-2.0-fast |
video | pro | 34 per clip (5 s) |
seedance-2.0-mini |
video | pro | 28 per clip (5 s) |
seedance-2.0-pro-i2v |
video | pro | 43 per clip (5 s) |
seedance-2.0-pro-r2v |
video | pro | 85 per clip (5 s) |
seedance-2.0-pro-t2v |
video | pro | 43 per clip (5 s) |
seedance-2.5 |
video | pro | 56 per clip (5 s) |
seedvr2-restore |
video | starter | 32 per clip (5 s) |
topaz-artemis |
video | starter | 18 per clip (5 s) |
topaz-artemis-dehalo-low |
video | starter | 18 per clip (5 s) |
topaz-artemis-dehalo-medium |
video | starter | 18 per clip (5 s) |
topaz-artemis-low |
video | starter | 18 per clip (5 s) |
topaz-artemis-medium |
video | starter | 18 per clip (5 s) |
topaz-artemis-moire |
video | starter | 18 per clip (5 s) |
topaz-dione |
video | starter | 18 per clip (5 s) |
topaz-dione-dehalo |
video | starter | 18 per clip (5 s) |
topaz-dione-dv |
video | starter | 18 per clip (5 s) |
topaz-dione-robust-dehalo |
video | starter | 18 per clip (5 s) |
topaz-dione-tv |
video | starter | 18 per clip (5 s) |
topaz-gaia |
video | starter | 18 per clip (5 s) |
topaz-gaia-cg |
video | starter | 18 per clip (5 s) |
topaz-hdr |
video | starter | 18 per clip (5 s) |
topaz-hyperion |
video | starter | 80 per clip (5 s) |
topaz-iris |
video | starter | 18 per clip (5 s) |
topaz-iris-medium |
video | starter | 18 per clip (5 s) |
topaz-motion-deblur |
video | starter | 18 per clip (5 s) |
topaz-nyx |
video | starter | 18 per clip (5 s) |
topaz-nyx-fast |
video | starter | 10 per clip (5 s) |
topaz-nyx-xl |
video | starter | 18 per clip (5 s) |
topaz-proteus |
video | starter | 18 per clip (5 s) |
topaz-proteus-natural |
video | starter | 18 per clip (5 s) |
topaz-rhea |
video | starter | 18 per clip (5 s) |
topaz-starlight |
video | starter | 40 per clip (5 s) |
topaz-starlight-fast |
video | starter | 20 per clip (5 s) |
topaz-theia |
video | starter | 18 per clip (5 s) |
topaz-theia-fidelity |
video | starter | 18 per clip (5 s) |
topaz-wonder |
video | starter | 40 per clip (5 s) |
veo-3.1 |
video | pro | 112 per clip (5 s) |
veo-3.1-fast |
video | pro | 28 per clip (5 s) |
veo-3.1-lite |
video | pro | 14 per clip (5 s) |
wan-2.6 |
video | pro | 28 per clip (5 s) |
wan-2.7 |
video | pro | 28 per clip (5 s) |
wan-3.0 |
video | pro | 28 per clip (5 s) |
wan-3.0-prime |
video | pro | 39 per clip (5 s) |
Audio #
Audio models take speech text or a description of music or sound effects, with model-specific voice and speed options. They return an audio asset in the format you asked for; the model catalog says which options it accepts.
| Model id | Modality | Plan | Credits |
|---|---|---|---|
dia-tts |
audio | starter | 3 per 1,000 characters |
elevenlabs-music |
audio | starter | 67 per generation |
elevenlabs-sound-effects-v2 |
audio | starter | 4 per generation |
elevenlabs-tts-multilingual-v2 |
audio | starter | 6 per 1,000 characters |
elevenlabs-tts-turbo-v2.5 |
audio | starter | 3 per 1,000 characters |
elevenlabs-tts-v3 |
audio | starter | 6 per 1,000 characters |
elevenlabs-tts-v3-conversational |
audio | starter | 3 per 1,000 characters |
inworld-tts |
audio | starter | 1 per 1,000 characters |
kokoro-us-english |
audio | starter | 2 per 1,000 characters |
lyria-3.5 |
audio | starter | 5 per generation |
minimax-music-v2.6 |
audio | starter | 15 per generation |
minimax-speech-2.8-hd |
audio | starter | 6 per 1,000 characters |
minimax-speech-2.8-turbo |
audio | starter | 4 per 1,000 characters |
mmaudio-v2 |
audio | starter | 2 per generation |
orpheus-tts |
audio | starter | 3 per 1,000 characters |
stable-audio-2.5 |
audio | starter | 20 per generation |
stable-audio-3-medium |
audio | starter | 3 per generation |
3D #
3D models take an HTTPS image or your uploaded image asset ids, with texture and material options where supported. They return a GLB asset that you can download through the same job and asset flow.
| Model id | Modality | Plan | Credits |
|---|---|---|---|
hunyuan3d-v3 |
3d | starter | 21 per generation |
trellis |
3d | starter | 2 per generation |

