Model APIs

Model APIs

On this page
  1. Quick example
    1. Parameters
    2. Error responses
  2. How it works
  3. What you can generate
    1. Image
    2. Video
    3. Audio
    4. 3D
  4. Next steps

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.

shell
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>"
shell
nolgia gen image --model flux-pro --prompt "a paper-cut mountain range at dawn" --out first.png
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
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")
Rustsrc/main.rs
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.

JSON202 Accepted
{
  "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.

JSON200 OK — succeeded
{
  "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.

The job lifecycle Your app submits a video generation job, the Nolgia API accepts it as queued, runs it, and it ends as succeeded or failed (or canceled, when its owner stops it), after which credits are settled. Your app long-polls the wait endpoint while the job runs. Your app Nolgia API POST /generate/video GET /jobs/{id}/wait 202 Accepted job queued running succeeded failed + failure.code settle: credits released or charged long-poll, up to 120 s per call
A generation is queued, runs, and ends with a result or failure

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

Next steps #