---
title: Common model arguments
description: The request fields that appear across models, one section each, and how to read a model's catalog entry before you send them.
---

# Common model arguments

The request schemas describe the shared vocabulary; the model catalog tells you which parts a particular model accepts. Read the catalog before choosing a duration, quality tier or reference input, then quote the exact body with `POST /jobs/cost` before you generate.

## Read the catalog first

`GET /models` publishes each model's capabilities and credit prices. A field being in the request schema does not mean every model supports it. The examples below read the catalog with the published clients.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/models \
  -H "Authorization: Bearer $NOLGIA_TOKEN"
```
```bash tab="CLI"
$ nolgia models get flux-pro
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data, error } = await nolgia.GET("/models");
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(data);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.models import list_models
from nolgia.models import ModelList

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
catalog = list_models.sync(client=client)
if not isinstance(catalog, ModelList):
    raise SystemExit(f"refused: {catalog}")
print(catalog.to_dict())
```
```rust tab="Rust"
use nolgia_client::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 catalog = client.list_models().send().await?.into_inner();
    println!("{catalog:?}");
    Ok(())
}
```

These are complete model entries from the production catalog captured on 2026-09-21, rather than the entire catalog response.

```json title="model-flux-pro.json"
{
  "cost": {
    "credits": 4,
    "unit": "per_image"
  },
  "id": "flux-pro",
  "image": {
    "aspect_ratios": [
      "3:1",
      "21:9",
      "16:9",
      "3:2",
      "4:3",
      "1:1",
      "3:4",
      "2:3",
      "9:16",
      "9:21",
      "1:3"
    ],
    "aura_compatible": true,
    "inpaint_mask": false,
    "num_images_max": 4,
    "reference_images_max": 0
  },
  "min_tier": "starter",
  "modality": "image",
  "quality": {
    "default": "native",
    "options": [
      {
        "credits": 4,
        "id": "native",
        "premium": false
      },
      {
        "credits": 17,
        "id": "2k",
        "premium": true
      },
      {
        "credits": 54,
        "id": "4k",
        "premium": true
      }
    ]
  },
  "recommended": false
}
```

```json title="model-veo-3.1-lite.json"
{
  "cost": {
    "baseline_seconds": 5,
    "credits": 14,
    "unit": "per_clip"
  },
  "id": "veo-3.1-lite",
  "min_tier": "pro",
  "modality": "video",
  "quality": {
    "default": "720p",
    "options": [
      {
        "credits": 14,
        "id": "720p",
        "premium": false
      },
      {
        "credits": 23,
        "id": "1080p",
        "premium": true
      }
    ]
  },
  "recommended": true,
  "references": {
    "audio_refs_max": 0,
    "element_refs_duration_seconds": 8,
    "element_refs_max": 3,
    "end_frame": false,
    "start_frame": true,
    "start_frame_required": false,
    "video_refs_max": 0
  },
  "video": {
    "aspect_ratios": [
      "16:9",
      "9:16"
    ],
    "audio": "always",
    "durations": [
      4,
      6,
      8
    ],
    "image_input": true,
    "speech": "native"
  }
}
```

| Capability block | What to read before submitting |
| --- | --- |
| `image.*` | `aspect_ratios`, `num_images_max`, `reference_images_max`, `inpaint_mask`, `aura_compatible`, and any `render_quality` ladder |
| `video.*` | Allowed `durations` or duration range, `aspect_ratios`, `audio`, `seed`, and any `bitrate_modes` |
| `references.*` | Start/end-frame support; image, video, audio and voice budgets; reference duration constraints; `video_tasks` |
| `quality.*` | The model's `default`, allowed tier ids, and credits for each option |
| `cost` | Base credits and billing unit; `baseline_seconds` when the price is for a baseline clip |

### Using the examples

Each argument example is an independent submission and can spend credits. Install the clients and set `NOLGIA_TOKEN` as in the [Quick Start](./getting-started.html); the examples preserve its client construction and submit-error handling. They print the new job id: use the Quick Start's `finish()` loop or [Asynchronous: submit and poll](./jobs.html) to wait for the asset.

Replace illustrative asset, character, project and other UUIDs with ids from your own account. For URL examples, set `REFERENCE_URL` to your own HTTPS media URL. Python's generated request `from_dict` constructs the schema's enum and UUID fields from the same JSON body shown in curl.

## model

| Property | Value |
| --- | --- |
| Type | string |
| Default | Required for image, video and audio; 3D selects `hunyuan3d-v3` when both model and quality are omitted |
| Values or range | A model id published for the requested modality |
| Applies to | All four generation request schemas |
| CLI flag | `--model`; `gen 3d --draft` selects `trellis` |

Send the catalog `id` verbatim. Model ids belong to a modality: an image model is not a video model even when the names describe the same family. CLI defaults are separate from the HTTP request contract; an explicit model makes a script easier to reproduce.

```bash tab="curl"
$ curl -s 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"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## prompt

| Property | Value |
| --- | --- |
| Type | string |
| Default | Required for ordinary image generation, video and audio; absent from 3D |
| Values or range | Up to 4,000 characters; video and audio require at least one |
| Applies to | `GenerateImageRequest`, `GenerateVideoRequest`, `GenerateAudioRequest` |
| CLI flag | `--prompt` |

Describe the result for images, video, music and sound effects; for text to speech, this is the text spoken and the input used for character-based billing. Image background removal and enhancement refuse a prompt because they operate on the reference pixels; image expansion accepts an optional prompt for the new margins. On reference video routes, name inputs with the provider slots published in the schema, such as `@Image1` or `@Video1`.

```bash tab="curl"
$ curl -s 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"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## negative_prompt

| Property | Value |
| --- | --- |
| Type | string or null |
| Default | Omitted |
| Values or range | Up to 4,000 characters; an image model can publish a lower `image.negative_prompt_max_length` |
| Applies to | Image and video requests; refused for image background removal |
| CLI flag | `--negative-prompt` on `gen video`; no image flag |

Use negative text only within the selected model's accepted limit. The server checks a model-specific image limit before reserving credits, so the shared schema maximum is not permission to exceed the catalog value.

```bash tab="curl"
$ curl -s 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","negative_prompt":"blurred, illegible text"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","negative_prompt":"blurred, illegible text"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "negative_prompt": "blurred, illegible text"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## seed

| Property | Value |
| --- | --- |
| Type | integer or null |
| Default | Omitted; no universal deterministic default |
| Values or range | Zero or greater |
| Applies to | Image and video requests; video support is `video.seed` |
| CLI flag | `--seed` on `gen video`; no image flag |

A seed is only meaningful on a model whose provider takes one. For video, `video.seed: false` means sending a seed is refused with `400`; an absent capability is unverified. A common field name is not a promise that all providers reproduce identical output.

```bash tab="curl"
$ curl -s 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","seed":42}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","seed":42},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "seed": 42
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## num_images

| Property | Value |
| --- | --- |
| Type | integer |
| Default | `1` |
| Values or range | `1` through `4`, further limited by `image.num_images_max` |
| Applies to | `GenerateImageRequest` |
| CLI flag | No dedicated flag; `gen image` submits one image |

The `flux-pro` fixture publishes a maximum of four images. Read the cap for the chosen model instead of copying that number across the catalog. Face-reference identity requests require one image, including when a character supplies the face reference.

```bash tab="curl"
$ curl -s 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","num_images":2}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":2,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "num_images": 2
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## image_size

| Property | Value |
| --- | --- |
| Type | `ImageSize` string |
| Default | Omitted; no schema default |
| Values or range | The six presets below |
| Applies to | `GenerateImageRequest` |
| CLI flag | No `--image-size` flag; use `--aspect-ratio` with a ratio instead |

These are the six size aliases accepted by the image schema. Prefer `aspect_ratio` when a model publishes a native ratio outside the square, 4:3 and 16:9 families. The CLI takes ratio strings, not these aliases.

### ImageSize values

| Value |
| --- |
| `square` |
| `square_hd` |
| `portrait_4_3` |
| `portrait_16_9` |
| `landscape_4_3` |
| `landscape_16_9` |

```bash tab="curl"
$ curl -s 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","image_size":"landscape_16_9"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","image_size":"landscape_16_9"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "image_size": "landscape_16_9"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## aspect_ratio

| Property | Value |
| --- | --- |
| Type | `ImageAspectRatio` for image; `AspectRatio` for video |
| Default | Omitted; let the model choose its default |
| Values or range | Schema values below, intersected with the selected model's published ratios |
| Applies to | Image and video requests; `image.aspect_ratios` or `video.aspect_ratios` |
| CLI flag | `--aspect-ratio` on `gen image` and `gen video` |

Choose a ratio from the selected model's catalog entry. The image and video enums differ, and a value in either enum can still be refused by a particular model. For example, the video fixture above accepts `16:9` and `9:16`.

### ImageAspectRatio values

| Value |
| --- |
| `16:9` |
| `9:16` |
| `1:1` |
| `4:3` |
| `3:4` |
| `3:2` |
| `2:3` |
| `21:9` |
| `9:21` |
| `2:1` |
| `1:2` |
| `5:4` |
| `4:5` |
| `3:1` |
| `1:3` |
| `4:1` |
| `1:4` |

### AspectRatio values

| Value |
| --- |
| `16:9` |
| `9:16` |
| `1:1` |
| `4:3` |
| `3:4` |
| `3:2` |
| `2:3` |
| `21:9` |

```bash tab="curl"
$ curl -s 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","aspect_ratio":"16:9"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","aspect_ratio":"16:9"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "aspect_ratio": "16:9"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## quality

| Property | Value |
| --- | --- |
| Type | string or null for image/video; enum string for 3D |
| Default | The model's `quality.default`; 3D defaults to `hunyuan3d-v3` when model is also absent |
| Values or range | `quality.options[].id`; 3D accepts `draft` or `standard` |
| Applies to | Image, video and 3D requests |
| CLI flag | `--quality` for image/video; `--draft` for 3D |

The ladder and price are model-specific: the fixtures show `native`, `2k`, `4k` for `flux-pro`, and `720p`, `1080p` for `veo-3.1-lite`. Omitting the field uses the base tier. An unsupported tier is a `400`, before a credit hold. For 3D, `draft` selects `trellis` and `standard` selects `hunyuan3d-v3`; a conflicting explicit model is refused.

```bash tab="curl"
$ curl -s 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","quality":"2k"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","quality":"2k"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "quality": "2k"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## render_quality

| Property | Value |
| --- | --- |
| Type | string |
| Default | `auto` |
| Values or range | `auto`, `low`, `medium`, `high`, `xhigh`, `max`, restricted to the model's own ladder |
| Applies to | Image only; GPT Image models publishing `image.render_quality` |
| CLI flag | `--render-quality` |

This controls the effort spent drawing the image. `quality` separately controls its output resolution, and the two can be combined. `low`, `medium` and `high` cost the base rate; `xhigh` and `max` add the credits published in the model's render-quality options and exist only on the GPT Image 2.5 models. A value the selected model does not publish is refused, never silently downgraded.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","render_quality":"high"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","render_quality":"high"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "render_quality": "high"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## duration_seconds

| Property | Value |
| --- | --- |
| Type | integer |
| Default | Model-dependent; omit to select a supported duration |
| Values or range | Schema `1` through `60`, restricted by `video.durations`, duration ranges and reference constraints |
| Applies to | `GenerateVideoRequest`; the audio field is deprecated and ignored |
| CLI flag | `--duration-seconds` on `gen video` |

For a discrete duration list, the server chooses the supported value nearest the five-second baseline, resolving ties upward; the Veo fixture therefore defaults to six seconds. Reference images can pin a different duration through `references.element_refs_duration_seconds`. An explicit duration must be supported: four seconds works in the fixture, five does not. Do not use the deprecated audio field to trim a narration.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"veo-3.1-lite","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","duration_seconds":4}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"veo-3.1-lite","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","duration_seconds":4},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "veo-3.1-lite",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "duration_seconds": 4
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## generate_audio

| Property | Value |
| --- | --- |
| Type | boolean or null |
| Default | `true` on models with optional audio |
| Values or range | `true` or `false`, interpreted through `video.audio` |
| Applies to | `GenerateVideoRequest` |
| CLI flag | `--generate-audio true` or `--generate-audio false` |

Read `video.audio`: `none` returns a silent clip regardless of the flag; `optional` honors it; `always` supplies native audio and refuses `false` with `400`. The asset's generation metadata records `generate_audio_effective` so the delivered behavior remains inspectable.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"veo-3.1-lite","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","duration_seconds":4,"generate_audio":true}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"veo-3.1-lite","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","duration_seconds":4,"generate_audio":true},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "veo-3.1-lite",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "duration_seconds": 4,
  "generate_audio": True
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## image_url

| Property | Value |
| --- | --- |
| Type | HTTPS URL string |
| Default | Omitted |
| Values or range | One start/reference image; image requests cap URL length at 2,048 characters |
| Applies to | Image reference input; video start-frame input; 3D front image |
| CLI flag | `--input` for image/video uses a local file or asset id; 3D also has `--image-url` |

An image reference needs spare `image.reference_images_max` capacity. For video, check `references.start_frame` and `start_frame_required`; text-only routes do not consume an image. For 3D, send exactly one of `image_url` and `image_asset_ids`. Prefer owned asset ids where the request offers them, so queued work receives a fresh signed URL at execution.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","image_url":"https://example.com/reference.png"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","image_url":process.env.REFERENCE_URL!},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "image_url": os.environ["REFERENCE_URL"]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## image_urls

| Property | Value |
| --- | --- |
| Type | array of HTTPS URL strings or null |
| Default | Omitted |
| Values or range | Image: at most 4 combined references; video: at most 9 combined element images; each model can allow fewer |
| Applies to | Image `image.reference_images_max`; video `references.element_refs_max` |
| CLI flag | No direct URL-array flag; use API clients |

On image requests, `image_url` is the first reference and `image_urls` adds more. On video requests, these URLs fill element-reference slots, sharing their budget with `element_asset_ids`. These fields do not create an independent budget for every way you attach media.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","image_urls":["https://example.com/reference.png"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","image_urls":[process.env.REFERENCE_URL!]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "image_urls": [
    os.environ["REFERENCE_URL"]
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## reference_asset_ids

| Property | Value |
| --- | --- |
| Type | array of image-asset UUIDs or null |
| Default | Omitted |
| Values or range | At most 4; shared with `image_url` and `image_urls` and limited by `image.reference_images_max` |
| Applies to | `GenerateImageRequest` |
| CLI flag | `--input PATH_OR_UUID` supplies one owned reference |

Use ids for images already in your Library. The server resolves and re-signs them when the job runs. A model with no reference input, including `flux-pro` in the fixture above, refuses any reference with `400`; it does not ignore the image.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","reference_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","reference_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "reference_asset_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## mask_asset_id

| Property | Value |
| --- | --- |
| Type | image-asset UUID or null |
| Default | Omitted |
| Values or range | One PNG mask; exactly one reference image; matching dimensions and an alpha channel |
| Applies to | Image models with `image.inpaint_mask: true` |
| CLI flag | `--mask PATH_OR_UUID` with exactly one `--input` |

Transparent mask pixels mark the region the model may repaint; opaque pixels describe the region to preserve. Describe the whole desired picture, including the new content. The mask is model guidance, so preserved areas are re-rendered rather than copied byte for byte. Unsupported input is refused before a hold; missing alpha or wrong dimensions discovered during execution fails the job with a full refund.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a desk with a red mug on the left and a potted fern in the centre","reference_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"],"mask_asset_id":"b2fbb51e-3c33-4a54-b87b-9c2b1e4f9a11"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a desk with a red mug on the left and a potted fern in the centre","reference_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"],"mask_asset_id":"b2fbb51e-3c33-4a54-b87b-9c2b1e4f9a11"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a desk with a red mug on the left and a potted fern in the centre",
  "reference_asset_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ],
  "mask_asset_id": "b2fbb51e-3c33-4a54-b87b-9c2b1e4f9a11"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## end_image_url

| Property | Value |
| --- | --- |
| Type | HTTPS URL string or null |
| Default | Omitted |
| Values or range | One final frame; mutually exclusive with `end_image_asset_id` |
| Applies to | Video with `references.end_frame: true`; requires the start `image_url` |
| CLI flag | `--end-frame PATH_OR_UUID` resolves a file or asset; no raw end-URL flag |

A final frame pins the destination of a start-to-end clip. Supply the start frame as well and check the capability: the Veo fixture above publishes `end_frame: false`. Choose a model that explicitly supports both frames.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","image_url":"https://example.com/start.png","end_image_url":"https://example.com/end.png"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","image_url":process.env.START_IMAGE_URL!,"end_image_url":process.env.END_IMAGE_URL!},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "seedance-2.5",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "image_url": os.environ["START_IMAGE_URL"],
  "end_image_url": os.environ["END_IMAGE_URL"]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## end_image_asset_id

| Property | Value |
| --- | --- |
| Type | image-asset UUID or null |
| Default | Omitted |
| Values or range | One owned final frame; mutually exclusive with `end_image_url` |
| Applies to | Same video capability and start-frame requirement as `end_image_url` |
| CLI flag | `--end-frame PATH_OR_UUID` with `--input` |

This is the owned-asset form of the final-frame input. The server resolves its URL for you; use at most one of the two end-frame fields.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","image_url":"https://example.com/start.png","end_image_asset_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","image_url":process.env.START_IMAGE_URL!,"end_image_asset_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "seedance-2.5",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "image_url": os.environ["START_IMAGE_URL"],
  "end_image_asset_id": "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## video_asset_ids

| Property | Value |
| --- | --- |
| Type | array of video-asset UUIDs or null |
| Default | Omitted |
| Values or range | At most 10 combined with `video_urls`, further limited by `references.video_refs_max` |
| Applies to | `GenerateVideoRequest` on a model accepting video references |
| CLI flag | Repeat `--video-ref ASSET_ID` |

Prefer owned video assets so the server can read duration and other stored metadata. Prompt references use `@Video1`, `@Video2` and so on. Duration and input-format constraints are model-specific; editing with `video_task: edit` requires a stored duration and cannot use raw URLs.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","video_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","video_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "seedance-2.5",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "video_asset_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## video_urls

| Property | Value |
| --- | --- |
| Type | array of HTTPS video URLs or null |
| Default | Omitted |
| Values or range | The same combined cap as `video_asset_ids` |
| Applies to | Video models with `references.video_refs_max` greater than zero |
| CLI flag | No raw video-URL flag; use `--video-ref` for owned assets |

Use raw URLs only for externally hosted footage. They share the asset-id budget, and the server cannot validate their duration, resolution or size from stored asset metadata; provider violations still fail. Use `video_asset_ids` when the footage is already in Nolgia.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","video_urls":["https://example.com/reference.png"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","video_urls":[process.env.REFERENCE_URL!]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "seedance-2.5",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "video_urls": [
    os.environ["REFERENCE_URL"]
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## audio_asset_ids

| Property | Value |
| --- | --- |
| Type | array of audio-asset UUIDs or null |
| Default | Omitted |
| Values or range | At most 10 combined with `audio_urls`; `references.audio_refs_max` and any `audio_refs_max_seconds` further restrict input |
| Applies to | `GenerateVideoRequest` on models accepting reference audio |
| CLI flag | Repeat `--audio-ref PATH_OR_UUID` |

These are your recorded audio tracks, resolved to signed URLs by the server. They are different from choosing a preset roster voice. Models that derive clip length and billing from the reference audio require an owned asset with duration metadata.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","audio_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","audio_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "seedance-2.5",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "audio_asset_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## audio_urls

| Property | Value |
| --- | --- |
| Type | array of HTTPS audio URLs or null |
| Default | Omitted |
| Values or range | The same combined cap as `audio_asset_ids` |
| Applies to | Video models with `references.audio_refs_max` greater than zero |
| CLI flag | No raw audio-URL flag; `--audio-ref` accepts a file or owned asset |

Pass externally hosted reference audio through this field when the selected model accepts it. Prefer `audio_asset_ids`; a model that requires stored input duration can refuse raw URLs.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","audio_urls":["https://example.com/reference.png"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","audio_urls":[process.env.REFERENCE_URL!]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "seedance-2.5",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "audio_urls": [
    os.environ["REFERENCE_URL"]
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## element_asset_ids

| Property | Value |
| --- | --- |
| Type | array of image-asset UUIDs or null |
| Default | Omitted |
| Values or range | At most 9 combined with `image_urls`, further limited by `references.element_refs_max` |
| Applies to | `GenerateVideoRequest` |
| CLI flag | Repeat `--element ASSET_ID` |

These are image references for a video, not registry element ids. Address the attached images as `@Image1` and onward in the prompt. An images-only reference request is allowed where the model supports it; attaching a video is not inherently required.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","element_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","element_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "seedance-2.5",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "element_asset_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## reference_voice_ids

| Property | Value |
| --- | --- |
| Type | array of strings or null |
| Default | Omitted |
| Values or range | At most 3; limited by `references.voice_refs_max` |
| Applies to | Grok Imagine 1.5 reference voices on models publishing voice-reference capability |
| CLI flag | No dedicated flag |

These select voices from the provider's roster rather than uploading audio. Address them as `<AUDIO_0>` through `<AUDIO_2>` in the prompt. The schema notes provider availability restrictions and a 720p output cap; pairing these voices with a 1080p tier is refused.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"grok-imagine-video-1.5","prompt":"A guide says <AUDIO_0> Welcome to the mountains.","reference_voice_ids":["eve"],"quality":"720p"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"grok-imagine-video-1.5","prompt":"A guide says <AUDIO_0> Welcome to the mountains.","reference_voice_ids":["eve"],"quality":"720p"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "grok-imagine-video-1.5",
  "prompt": "A guide says <AUDIO_0> Welcome to the mountains.",
  "reference_voice_ids": [
    "eve"
  ],
  "quality": "720p"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## character_id

| Property | Value |
| --- | --- |
| Type | character UUID or null |
| Default | Omitted |
| Values or range | One character belonging to the caller |
| Applies to | Image, video and audio requests; visual references must fit the chosen model |
| CLI flag | `--character-id` for image/video; no audio flag |

On image and video requests, the character supplies its canonical description and primary reference. Image identity constraints include one output and no competing `face_reference_asset_id`. For audio, the character can supply a catalog voice for this model; an explicit `voice` wins, and clip-voice cloning is not available.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","character_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","character_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "character_id": "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## character_ids

| Property | Value |
| --- | --- |
| Type | ordered array of character UUIDs or null |
| Default | Omitted |
| Values or range | Up to 4 unique characters, limited by the model's reference capacity |
| Applies to | Image and video requests |
| CLI flag | No cast-array flag; use API clients |

Order defines the cast, with the first character as lead. Every reference counts toward the model's budget; a cast that will not fit is refused. If you also send `character_id`, it must be one of the members. A character name mentioned as `@Name` is mapped to its cast/reference slot.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","character_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42","b2fbb51e-3c33-4a54-b87b-9c2b1e4f9a11"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","character_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42","b2fbb51e-3c33-4a54-b87b-9c2b1e4f9a11"]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "character_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42",
    "b2fbb51e-3c33-4a54-b87b-9c2b1e4f9a11"
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## location_id

| Property | Value |
| --- | --- |
| Type | location UUID or null |
| Default | Omitted |
| Values or range | One location belonging to the caller |
| Applies to | Image and video; spare image/element-reference capacity is required when the location has an image |
| CLI flag | No dedicated flag |

A location contributes its canonical description and, when present, its primary reference. It has its own field beside the character so a shot can place a person in a consistent room. An unknown location or insufficient capacity is a `400`, not a silently dropped reference.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","location_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","location_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "location_id": "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## product_id

| Property | Value |
| --- | --- |
| Type | product UUID or null |
| Default | Omitted |
| Values or range | One owned product; its primary and additional images use the remaining reference budget |
| Applies to | Image and video requests; not video regeneration with `source_video_asset_id` |
| CLI flag | No dedicated flag |

A product contributes its description and up to three images, primary first, within the remaining model budget. If the primary image cannot fit the request is refused; extra gallery images beyond the budget do not ride. A product with no image contributes only its description.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","product_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","product_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "product_id": "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## brand_kit_id

| Property | Value |
| --- | --- |
| Type | brand-kit UUID or null |
| Default | Omitted: the generation's project can supply its linked brand kit |
| Values or range | One owned brand kit |
| Applies to | Image and video requests; logo attachment depends on lane and spare capacity |
| CLI flag | No dedicated flag |

The brand block is appended after your prompt. A logo never displaces a reference you already supplied; it rides only when the lane and available slots permit it. Image enhancement, expansion and masked requests do not attach a logo. The asset records whether it rode as `brand_logo_attached`.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","brand_kit_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","brand_kit_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "brand_kit_id": "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## brand_kit_mode

| Property | Value |
| --- | --- |
| Type | `BrandKitMode` string |
| Default | `full` |
| Values or range | `full`, `prompt_only`, `off` |
| Applies to | Image and video requests |
| CLI flag | No dedicated flag |

Omitting the mode applies the full kit. `prompt_only` adds the brand block without the logo. `off` disables both explicit and project branding and cannot be combined with `brand_kit_id`.

### BrandKitMode values

| Value |
| --- |
| `full` |
| `prompt_only` |
| `off` |

```bash tab="curl"
$ curl -s 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","brand_kit_mode":"off"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","brand_kit_mode":"off"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "brand_kit_mode": "off"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## style_id

| Property | Value |
| --- | --- |
| Type | style UUID or null |
| Default | Omitted: the generation's project can contribute its pinned style |
| Values or range | One saved style visible to the caller |
| Applies to | Image and video requests; not video regeneration with `source_video_asset_id` |
| CLI flag | No dedicated flag |

A style appends its prompt fragment after your words. Reference images ride only within remaining capacity; a swatch that does not fit is omitted while the fragment remains. Video adds a swatch only when the clip already has other visual input, so a standalone swatch does not become the subject.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","style_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","style_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "style_id": "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## element_ids

| Property | Value |
| --- | --- |
| Type | array of registry-element UUIDs or null |
| Default | Omitted |
| Values or range | Image: up to 4; video: up to 9; all attached images still share the model's reference budget |
| Applies to | Image and video requests |
| CLI flag | No registry-element flag; video `--element` maps to `element_asset_ids`, a different field |

Registry elements carry a canonical description and reference images. They must be visible in your personal or active organization library. A character id can also be used here, but naming the same character here and in `character_id` is refused. Excess references are rejected before credits are held.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","element_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"gpt-image-2","prompt":"a paper-cut mountain range at dawn","element_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "gpt-image-2",
  "prompt": "a paper-cut mountain range at dawn",
  "element_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## motion_id

| Property | Value |
| --- | --- |
| Type | string or null |
| Default | Omitted |
| Values or range | A move id from `GET /motions`, up to 64 characters |
| Applies to | `GenerateVideoRequest`; works on every video model |
| CLI flag | `--motion` |

The server appends the selected camera move's prompt fragment as its own sentence; it does not replace or shorten your prompt. Use it for text-to-video, image-to-video or a multi-shot request. An unknown id is a `400` naming the motion library.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"veo-3.1-lite","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","duration_seconds":4,"motion_id":"push-in"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"veo-3.1-lite","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","duration_seconds":4,"motion_id":"push-in"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "veo-3.1-lite",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "duration_seconds": 4,
  "motion_id": "push-in"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## motion_strength

| Property | Value |
| --- | --- |
| Type | `CameraMoveStrength` string |
| Default | The move's `default_strength`, currently `medium` |
| Values or range | `subtle`, `medium`, `strong` |
| Applies to | Video requests with `motion_id`; refused without a move |
| CLI flag | `--motion-strength`, requires `--motion` |

Strength selects how far and how fast the camera move travels over the clip. The motion catalog provides the exact prompt fragment at each strength.

### CameraMoveStrength values

| Value |
| --- |
| `subtle` |
| `medium` |
| `strong` |

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"veo-3.1-lite","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","duration_seconds":4,"motion_id":"push-in","motion_strength":"subtle"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"veo-3.1-lite","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","duration_seconds":4,"motion_id":"push-in","motion_strength":"subtle"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "veo-3.1-lite",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "duration_seconds": 4,
  "motion_id": "push-in",
  "motion_strength": "subtle"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## aura

| Property | Value |
| --- | --- |
| Type | boolean or null |
| Default | On for person prompts on `image.aura_compatible` models; off otherwise |
| Values or range | `true` or `false` |
| Applies to | `GenerateImageRequest` |
| CLI flag | `--aura true` or `--aura false` |

Aura composes people as photographs with real skin and lighting. An explicit `false` overrides the person-prompt default. On a model without the capability, `true` is a no-op; a face reference is an identity request and cannot be combined with `aura: false`.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/image \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"flux-pro","prompt":"a portrait of a mountain guide in natural morning light","aura":true}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a portrait of a mountain guide in natural morning light","aura":true},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a portrait of a mountain guide in natural morning light",
  "aura": True
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## voice

| Property | Value |
| --- | --- |
| Type | string or null |
| Default | Model-specific; an eligible character can supply its catalog voice |
| Values or range | A model-specific voice id, at most 128 characters; read `audio.voices` |
| Applies to | `GenerateAudioRequest` for text to speech |
| CLI flag | `--voice`; discover with `nolgia voices list --model` |

Select a voice published for the TTS model. A voice id from another provider is not interchangeable, and an explicit voice overrides the character's saved voice.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/audio \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"kokoro-us-english","prompt":"The sun rises over the mountains.","voice":"af_bella"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/audio", {
  body: {"model":"kokoro-us-english","prompt":"The sun rises over the mountains.","voice":"af_bella"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_audio
from nolgia.models import GenerateAudioRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_audio.sync(client=client, body=GenerateAudioRequest.from_dict({
  "model": "kokoro-us-english",
  "prompt": "The sun rises over the mountains.",
  "voice": "af_bella"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## speed

| Property | Value |
| --- | --- |
| Type | number or null |
| Default | Omitted; `1` represents the voice's natural pace |
| Values or range | Shared schema `0.7` through `1.3`; use the model's `audio.speed` range |
| Applies to | Text-to-speech models publishing `audio.speed` |
| CLI flag | No dedicated flag |

Speed changes speaking rate without changing character-based pricing. The allowed range is per model; the schema documents an upper bound of `1.2` for ElevenLabs and `1.3` for MiniMax and Kokoro. Unsupported models or values outside their range return `400`.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/audio \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"kokoro-us-english","prompt":"The sun rises over the mountains.","speed":1.1}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/audio", {
  body: {"model":"kokoro-us-english","prompt":"The sun rises over the mountains.","speed":1.1},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_audio
from nolgia.models import GenerateAudioRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_audio.sync(client=client, body=GenerateAudioRequest.from_dict({
  "model": "kokoro-us-english",
  "prompt": "The sun rises over the mountains.",
  "speed": 1.1
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## format

| Property | Value |
| --- | --- |
| Type | `AudioFormat` string |
| Default | `mp3` |
| Values or range | `mp3`, `wav`, `ogg`, `flac` |
| Applies to | `GenerateAudioRequest` |
| CLI flag | `--format` |

Request the audio format you want to download. The response is still a job; read the finished asset's MIME type and signed URL when it succeeds.

### AudioFormat values

| Value |
| --- |
| `mp3` |
| `wav` |
| `ogg` |
| `flac` |

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/audio \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"kokoro-us-english","prompt":"The sun rises over the mountains.","format":"wav"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/audio", {
  body: {"model":"kokoro-us-english","prompt":"The sun rises over the mountains.","format":"wav"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_audio
from nolgia.models import GenerateAudioRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_audio.sync(client=client, body=GenerateAudioRequest.from_dict({
  "model": "kokoro-us-english",
  "prompt": "The sun rises over the mountains.",
  "format": "wav"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## texture

| Property | Value |
| --- | --- |
| Type | boolean |
| Default | `true` |
| Values or range | `true` or `false`; disabling texture requires `hunyuan3d-v3` |
| Applies to | `Generate3DRequest` |
| CLI flag | `--no-texture` sends `false` |

Disable texture to produce an untextured white model. The draft model does not offer the untextured option, and PBR requires texture to remain enabled.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/3d \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"hunyuan3d-v3","image_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"],"texture":false}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/3d", {
  body: {"model":"hunyuan3d-v3","image_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"],"texture":false},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_3d
from nolgia.models import Generate3DRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_3d.sync(client=client, body=Generate3DRequest.from_dict({
  "model": "hunyuan3d-v3",
  "image_asset_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ],
  "texture": False
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## pbr

| Property | Value |
| --- | --- |
| Type | boolean |
| Default | `false` |
| Values or range | `true` or `false`; requires `hunyuan3d-v3` and textures |
| Applies to | `Generate3DRequest` |
| CLI flag | `--pbr` |

Request PBR materials when you need that output from the textured 3D route. Quote the exact settings first because this option changes the request's price.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/3d \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"hunyuan3d-v3","image_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"],"texture":true,"pbr":true}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/3d", {
  body: {"model":"hunyuan3d-v3","image_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"],"texture":true,"pbr":true},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_3d
from nolgia.models import Generate3DRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_3d.sync(client=client, body=Generate3DRequest.from_dict({
  "model": "hunyuan3d-v3",
  "image_asset_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ],
  "texture": True,
  "pbr": True
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## image_asset_ids

| Property | Value |
| --- | --- |
| Type | ordered array of image-asset UUIDs |
| Default | No default: supply exactly this field or `image_url` |
| Values or range | One through four images in front, back, left, right order; `trellis` takes exactly one |
| Applies to | `Generate3DRequest` |
| CLI flag | Repeat `gen 3d --input PATH_OR_UUID` in view order |

The order of views matters. Use your own stored assets, and do not combine the array with a hosted `image_url`. Multiple views are available only on the model that supports them.

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/3d \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"hunyuan3d-v3","image_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/3d", {
  body: {"model":"hunyuan3d-v3","image_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_3d
from nolgia.models import Generate3DRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_3d.sync(client=client, body=Generate3DRequest.from_dict({
  "model": "hunyuan3d-v3",
  "image_asset_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## tags

| Property | Value |
| --- | --- |
| Type | array of strings |
| Default | Omitted |
| Values or range | At most 10 tags; each 1–40 characters |
| Applies to | All four generation requests |
| CLI flag | Repeat `gen 3d --tag`; no image/video/audio generation flag |

Tags are applied to the resulting assets and normalized to lowercase. They label the output; they are not provider prompt text.

```bash tab="curl"
$ curl -s 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","tags":["hero","draft"]}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","tags":["hero","draft"]},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "tags": [
    "hero",
    "draft"
  ]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## project_id

| Property | Value |
| --- | --- |
| Type | project UUID |
| Default | Omitted; agent-session context can provide filing |
| Values or range | A project belonging to the caller |
| Applies to | All four generation requests |
| CLI flag | `--project-id` |

File the generated assets in a project. An explicit project takes precedence over automatic agent-session attribution. The async video and 3D outputs are filed when the job completes; an unknown or foreign project is refused.

```bash tab="curl"
$ curl -s 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","project_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","project_id":"5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "project_id": "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## preset_slug

| Property | Value |
| --- | --- |
| Type | string or null |
| Default | Omitted on direct API, CLI, MCP and pipeline calls |
| Values or range | At most 128 characters |
| Applies to | All four generation requests |
| CLI flag | No dedicated generation flag |

The web app supplies this when a generation originates from a preset. It is attribution, stored verbatim without checking whether that preset still exists. Setting the slug does not load a preset or fill in missing model arguments; the example remains a complete generation body.

```bash tab="curl"
$ curl -s 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","preset_slug":"cinematic-portrait"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","preset_slug":"cinematic-portrait"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "preset_slug": "cinematic-portrait"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## confirmation_token

| Property | Value |
| --- | --- |
| Type | string |
| Default | Omitted; the confirmation gate is optional |
| Values or range | The token returned by `POST /jobs/cost` for this exact request and price, before `expires_at` |
| Applies to | All four generation requests |
| CLI flag | No dedicated flag |

Quote the request, show that price to the customer, then return the quote's token with the unchanged generation body. An expired, malformed, foreign or mismatched token is refused with `422` and `code: confirmation_rejected`. Omitting the token does not activate the gate. Set `CONFIRMATION_TOKEN` to the token from your own quote, not the redacted value in an example response.

```bash tab="curl"
$ curl -s 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","confirmation_token":"<confirmation_token from the quote>"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/image", {
  body: {"num_images":1,"model":"flux-pro","prompt":"a paper-cut mountain range at dawn","confirmation_token":process.env.CONFIRMATION_TOKEN!},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest.from_dict({
  "model": "flux-pro",
  "prompt": "a paper-cut mountain range at dawn",
  "confirmation_token": os.environ["CONFIRMATION_TOKEN"]
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## bitrate_mode

| Property | Value |
| --- | --- |
| Type | `BitrateMode` string |
| Default | Provider default where a model supports bitrate selection |
| Values or range | `standard`, `high` |
| Applies to | Video models publishing `video.bitrate_modes`; none currently published |
| CLI flag | `--bitrate` |

No currently published model exposes bitrate selection. The schema reserves these two values, and sending the field to a model without the capability is a `400`. These request fragments illustrate the field only; do not add it to a current generation.

### BitrateMode values

| Value |
| --- |
| `standard` |
| `high` |

```bash tab="curl" title="request fragment; unsupported by current models"
# JSON field for a model that publishes bitrate selection:
# "bitrate_mode": "standard"
```
```ts tab="TypeScript" title="request fragment; unsupported by current models"
const bitrate = { bitrate_mode: "standard" as const };
```
```python tab="Python" title="request fragment; unsupported by current models"
bitrate = {"bitrate_mode": "standard"}
```

## video_task

| Property | Value |
| --- | --- |
| Type | `VideoTask` string or null |
| Default | Omitted; the provider classifies the task from the prompt |
| Values or range | `reference`, `edit`, `extend`, as published in `references.video_tasks` |
| Applies to | Video requests carrying a reference video on a supporting model |
| CLI flag | No dedicated flag |

Choose what the input footage is for. `reference` uses its motion and timing to drive a new render; `edit` changes one thing while keeping source length and aspect ratio; `extend` continues it by the requested new duration. Edit takes one owned video with known duration of 4–30 seconds, refuses raw URLs, and uses the source duration when you omit the field. Unsupported tasks or missing reference video return `400`.

### VideoTask values

| Value |
| --- |
| `reference` |
| `edit` |
| `extend` |

```bash tab="curl"
$ curl -s https://api.nolgia.ai/v1/generate/video \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","video_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"],"video_task":"reference"}'
```
```ts tab="TypeScript"
import { createNolgiaClient } from "@nolgia/sdk";

const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: job, error } = await nolgia.POST("/generate/video", {
  body: {"model":"seedance-2.5","prompt":"a paper-cut mountain range at dawn, slow push-in as the sun rises","video_asset_ids":["5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"],"video_task":"reference"},
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(job.id);
```
```python tab="Python"
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_video
from nolgia.models import GenerateVideoRequest, Job

client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_video.sync(client=client, body=GenerateVideoRequest.from_dict({
  "model": "seedance-2.5",
  "prompt": "a paper-cut mountain range at dawn, slow push-in as the sun rises",
  "video_asset_ids": [
    "5a2f7c58-9e5a-4f1a-9c7f-2f0b6c3d1e42"
  ],
  "video_task": "reference"
}))
if not isinstance(job, Job):
    raise SystemExit(f"refused: {job}")
print(job.id)
```

## Every field, from the spec

These generated tables are the request source of truth. The sections above explain the shared controls; the full schemas also cover specialized controls, including image guidance, explicit face references, video shots and regeneration. See the [API reference](../api/) for operation responses and the [OpenAPI document](../api/openapi.yaml) for complete descriptions and constraints.

### Image request

<!-- gen:fields schema=GenerateImageRequest -->
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `confirmation_token` | string | No | Optional proof that this exact request and price were shown to the customer, from `POST /jobs/cost`.… |
| `model` | `ImageModel` | Yes |  |
| `prompt` | string | No | What to generate.… |
| `negative_prompt` | string, nullable | No | Negative prompt text.… |
| `image_size` | `ImageSize` | No |  |
| `aspect_ratio` | `ImageAspectRatio` | No |  |
| `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. |
| `seed` | integer, nullable | No | Reproducibility seed. The same seed with the same prompt and settings gives the same image on a model whose provider honors one; omit it for a different result every time. Not every provider honors it. |
| `guidance_scale` | number, nullable | No |  |
| `image_url` | string, nullable | No | Source image (https URL) for image-to-image restyle. When set, the model transforms this image instead of generating from scratch. |
| `image_urls` | array of string, nullable | No | Multiple reference images (https URLs) for models that support multi-reference input (OpenAI gpt-image models — e.g.… |
| `reference_asset_ids` | array of string, nullable | No | Reference images given as ids of your own image assets — the server resolves each to a signed URL and it rides the same multi-reference path as `image_urls` (the image lane's sibling of the video lane's `element_asset_ids`).… |
| `render_quality` | one of `auto`, `low`, `medium`, `high`, `xhigh`, `max` | No | How much detail the model spends on the render itself, on models that publish `image.render_quality` (the GPT Image family).… |
| `mask_asset_id` | string, nullable | No | Edit only PART of the reference image.… |
| `quality` | string, nullable | No | Quality/resolution tier for the selected model.… |
| `tags` | array of string | No | Applied to the resulting asset(s); normalized to lowercase. |
| `project_id` | string | No | Files the generated asset(s) into this project at creation.… |
| `preset_slug` | string, nullable | No | Slug of the preset this generation was launched from, if any.… |
| `aura` | boolean, nullable | No | Applies Aura, the Nolgia character engine: server-side photoreal composition layered onto the prompt (people render as photographs, real skin, real light, no AI gloss).… |
| `face_reference_asset_id` | string, nullable | No | Image asset (owned by the caller) whose face conditions the render for identity.… |
| `face_check_consent` | boolean, nullable | No | Records your consent to the face identity check for the `face_reference_asset_id` photo (once per photo; it stays recorded for later requests).… |
| `character_id` | string, nullable | No | One of your characters (`GET /characters`, created on the Create Characters page).… |
| `character_ids` | array of string, nullable | No | An ORDERED cast of up to 4 of your characters rendered together (two-person dialogue scenes, duets, family commercials).… |
| `location_id` | string, nullable | No | One of your locations (`GET /locations`): the place this render is set in.… |
| `brand_kit_id` | string, nullable | No | One of your brand kits (`GET /brand-kits`).… |
| `brand_kit_mode` | `BrandKitMode` | No |  |
| `product_id` | string, nullable | No | One of your products (`GET /products`): the product this render shows.… |
| `style_id` | string, nullable | No | One of your saved styles (`GET /styles`).… |
| `element_ids` | array of string, nullable | No | Registry elements (`GET /elements`) to condition this render: each element's reference images are attached as image references (after any `image_url`/`image_urls` and any face/character reference, which keeps its slot) and its `canonical_description` rides into the prompt verbatim with the binding clause ("100% matches the reference") - the belt-and-braces continuity stack.… |
<!-- /gen -->

### Video request

<!-- gen:fields schema=GenerateVideoRequest -->
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `confirmation_token` | string | No | Optional proof that this exact request and price were shown to the customer, from `POST /jobs/cost`.… |
| `model` | `VideoModel` | Yes |  |
| `prompt` | string | Yes | Text prompt.… |
| `negative_prompt` | string, nullable | No | What to keep OUT of the clip.… |
| `image_url` | string, nullable | No | Required for image-to-video models; ignored for text-to-video. |
| `end_image_url` | string, nullable | No | Final-frame image (https URL) for start+end frame pinning on models that support it (Seedance 2.0 Pro i2v, Seedance 2.5, Seedance 2.0 Fast and Mini, FLUX 3 Video, MiniMax Hailuo 3, MiniMax H3 Max i2v).… |
| `end_image_asset_id` | string, nullable | No | One of your image assets to use as the final frame (server resolves it to a signed URL). Same semantics as `end_image_url`; provide at most one of the two. |
| `video_asset_ids` | array of string, nullable | No | Reference videos for models with `references.video_refs_max > 0` on `GET /models` (`seedance-2.5`: up to 10; `seedance-2.0-pro-r2v`: up to 3; `minimax-h3` takes none), given as ids of your video assets — the server resolves each to a signed URL and forwards them as the provider's `video_urls`.… |
| `video_urls` | array of string, nullable | No | Raw https reference-video URLs, for callers that host media outside Nolgia.… |
| `video_task` | `VideoTask` | No |  |
| `element_asset_ids` | array of string, nullable | No | Element/reference images for reference-to-video models, given as ids of your image assets — resolved to signed URLs and forwarded as the provider's `image_urls`.… |
| `image_urls` | array of string, nullable | No | Raw https element-image URLs. Counted against the same 9-image cap as `element_asset_ids`. Prefer `element_asset_ids`. |
| `audio_asset_ids` | array of string, nullable | No | Reference audio tracks for models with `references.audio_refs_max > 0` on `GET /models` (`seedance-2.5`: up to 10 with no per-track ceiling; `minimax-h3`: up to 3, each at most 15 seconds; Seedance 2.0 Pro r2v takes none, its primary route has no reference-audio slot), given as ids of your audio assets — resolved to signed URLs and forwarded as the provider's `audio_urls`.… |
| `audio_urls` | array of string, nullable | No | Raw https reference-audio URLs. Counted against the same per-model cap as `audio_asset_ids` (`references.audio_refs_max`, never more than 10). Prefer `audio_asset_ids`. |
| `reference_voice_ids` | array of string, nullable | No | Preset voices for Grok Imagine 1.5 reference-to-video (models with `references.voice_refs_max > 0` on `GET /models`), each a `voice_id` from xAI's Text-to-Speech roster (for example `eve`, the default; case-insensitive, validated by xAI).… |
| `bitrate_mode` | `BitrateMode` | No |  |
| `aspect_ratio` | `AspectRatio` | No |  |
| `duration_seconds` | integer | No | Clip length in seconds.… |
| `seed` | integer, nullable | No | Reproducibility seed.… |
| `generate_audio` | boolean, nullable | No | Ask the model to generate a synchronized audio track (dialogue/ambient/SFX).… |
| `strip_audio` | boolean, nullable | No | Deliver the clip with NO audio stream at all: every audio track the model rendered is removed on delivery by a stream copy (the video stream is untouched), and the asset records `has_audio: false`.… |
| `quality` | string, nullable | No | Quality/resolution tier for the selected model (e.g.… |
| `shots` | array of `VideoShot`, nullable | No | Multi-shot sequence: divide the clip into sequential shots, each with its own prompt, duration, and optional sound direction.… |
| `tags` | array of string | No | Applied to the resulting asset(s); normalized to lowercase. |
| `project_id` | string | No | Files the generated asset into this project at creation (the async video asset lands in the project when the job completes).… |
| `preset_slug` | string, nullable | No | Slug of the preset this generation was launched from, if any.… |
| `source_video_asset_id` | string, nullable | No | Regenerate one of your completed videos at the model's top resolution: the referenced video asset is re-rendered at 2K via the provider's native regeneration flow (models with `video.regeneration` on `GET /models` — MiniMax Hailuo 3's 768P→2K Video Regeneration).… |
| `character_id` | string, nullable | No | One of your characters (`GET /characters`).… |
| `use_character_voice` | boolean, nullable | No | Attaches the lead character's (character_id, or the first of character_ids) voice clip as a reference audio track (audio_asset_ids, emitted after your own audio tracks and audio_urls, taking the next @Audio slot) and adds a voice line to the prompt.… |
| `character_ids` | array of string, nullable | No | An ORDERED cast of up to 4 of your characters rendered together in one clip.… |
| `location_id` | string, nullable | No | One of your locations (`GET /locations`): the place this clip is set in.… |
| `brand_kit_id` | string, nullable | No | One of your brand kits (`GET /brand-kits`).… |
| `brand_kit_mode` | `BrandKitMode` | No |  |
| `product_id` | string, nullable | No | One of your products (`GET /products`): the product this clip shows.… |
| `style_id` | string, nullable | No | One of your saved styles (`GET /styles`).… |
| `element_ids` | array of string, nullable | No | Registry elements (`GET /elements`) to condition this clip: each element's reference images are appended to the element-reference slots (before any `character_id` reference, which stays appended last) and its `canonical_description` rides into the prompt verbatim with the binding clause ("100% matches the reference") - the belt-and-braces continuity stack.… |
| `motion_id` | string, nullable | No | A camera move from the library on `GET /motions` (for example `push-in`, `orbit-left`, `crane-up`, `rack-focus`).… |
| `motion_strength` | `CameraMoveStrength` | No |  |
<!-- /gen -->

### Audio request

<!-- gen:fields schema=GenerateAudioRequest -->
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `confirmation_token` | string | No | Optional proof that this exact request and price were shown to the customer, from `POST /jobs/cost`.… |
| `model` | `AudioModel` | Yes |  |
| `prompt` | string | Yes | For TTS this is the text to speak; for music/SFX it is the description.… |
| `voice` | string, nullable | No | TTS voice id (model-specific): one of the model's `audio.voices`, or the `voice_id` of one of your custom voices (GET /voices) on a model whose `audio.custom_voices` is true.… |
| `speed` | number, nullable | No | Speaking rate as a multiple of the voice's natural pace; 1 is natural.… |
| `character_id` | string, nullable | No | One of your characters.… |
| `duration_seconds` | integer, nullable | No | Currently ignored; never forwarded to audio providers. |
| `format` | `AudioFormat` | No |  |
| `tags` | array of string | No | Applied to the resulting asset(s); normalized to lowercase. |
| `project_id` | string | No | Files the generated asset into this project at creation.… |
| `preset_slug` | string, nullable | No | Slug of the preset this generation was launched from, if any.… |
<!-- /gen -->

### 3D request

<!-- gen:fields schema=Generate3DRequest -->
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `confirmation_token` | string | No | Optional proof that this exact request and price were shown to the customer, from `POST /jobs/cost`.… |
| `model` | `Generate3DModel` | No | Defaults to hunyuan3d-v3 when both model and quality are omitted. |
| `quality` | one of `draft`, `standard` | No | Draft selects trellis; standard selects hunyuan3d-v3. A value that contradicts an explicit model returns 400. |
| `image_asset_ids` | array of string | No | Your image assets in front, back, left, right order. Trellis takes exactly one. Supply exactly one of image_asset_ids and image_url. |
| `image_url` | string | No | Hosted HTTPS front image. Supply exactly one of image_asset_ids and image_url. |
| `texture` | boolean | No | Defaults to true. False creates an untextured white model and is available only with hunyuan3d-v3. |
| `pbr` | boolean | No | Defaults to false. PBR materials require hunyuan3d-v3 with textures enabled. |
| `tags` | array of string | No | Applied to the 3D asset; normalized to lowercase. |
| `project_id` | string | No | Files the 3D asset into this project when the job completes. The project must exist and belong to the caller (400 otherwise). |
| `preset_slug` | string, nullable | No | Slug of the preset this generation was launched from, if any. Same semantics as on `POST /generate/video`. |
<!-- /gen -->

## Traps

> [!WARNING]
> A public-figure likeness refusal can fail with `ip_detected`. The observed refunded refusal reports `failure.credits_refunded: true`; read that field on your own job instead of inferring a refund from the code. A provider-billed moderation failure can report `false`.

> [!NOTE]
> For about ten minutes after an API deploy, a brand-new model id can answer `400 validation` with “unknown … model” from an instance on the previous revision while the new revision already accepts it. If the new id is in the catalog, retry after a minute instead of changing a correct model id.

> [!TIP]
> `POST /jobs/cost` validates the generation body before quoting it and refuses invalid requests with the same generation error code as submission. Use it to catch an unsupported tier, duration or reference combination before starting a job.

There is no safety-checker toggle or prompt-expansion flag on generation requests; the server composes the image prompt itself, `enhanced_prompt` on the asset shows what ran, and `POST /generate/video/enhance-prompt` is a separate one-credit helper.

## Error responses

| Situation | Response |
| --- | --- |
| Unknown model, unsupported field value or invalid reference combination | `400`, `code: validation`; correct the request, except for the new-model deploy window above |
| Expired, foreign, malformed or mismatched confirmation token | `422`, `code: confirmation_rejected` |
| Wallet cannot pay for the request | `402`, `code: out_of_credits` |
| Submitted job later fails | Read `failure.code`, `failure.message` and `failure.credits_refunded` on the job |

## Next steps

:::cards
- [Model APIs](./models.html): Browse the catalog and choose an inference method.
- [Uploads](./uploads.html): Put references in your Library before generating.
- [Errors](./errors.html): Handle validation, policy failures and refunds explicitly.
:::
