Model APIs
Platform headers
On this page
Use bearer authentication for API calls, an idempotency key for generation retries, and a request id to connect a problem response to your logs. The two query parameters below control a wait or authorize a status stream; they are not headers.
There are no priority, runner-hint, retry-config or payload-storage headers.
The examples use the same client construction as the Quick Start. Set NOLGIA_TOKEN on your server and JOB_ID to a job you own. TypeScript examples run on the server; see Proxy setup before calling from a browser.
Authorization #
| Property | Value |
|---|---|
| Type | HTTP request header; string |
| Default | None; authenticate protected routes |
| Values | Bearer followed by a PAT beginning nol_ or a JWT |
| Applies to | Authenticated API routes; the job SSE route uses a ticket instead |
| SDK parameter | TypeScript client token; Python token; Rust builder bearer_token |
The token identifies the caller and its available permissions. Put it in the environment, never in a checked-in source file.
curl -s https://api.nolgia.ai/v1/me \
-H "Authorization: Bearer $NOLGIA_TOKEN"
import { createNolgiaClient } from "@nolgia/sdk";
const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data, error } = await nolgia.GET("/me");
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(data);
import os
from nolgia import AuthenticatedClient
from nolgia.api.auth import get_current_user
from nolgia.models import User
client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
account = get_current_user.sync(client=client)
if not isinstance(account, User):
raise SystemExit(f"refused: {account}")
print(account.to_dict())
Content-Type #
| Property | Value |
|---|---|
| Type | HTTP request header; media type |
| Default | Typed clients set it when serializing a JSON body |
| Values | application/json for the generation and quote examples |
| Applies to | API requests carrying JSON |
| SDK parameter | TypeScript body; Python generated request model passed as body |
Declare the representation you send. The typed clients serialize the request and set the JSON content type for you.
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"}'
import { createNolgiaClient } from "@nolgia/sdk";
const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data: image, error } = await nolgia.POST("/generate/image", {
body: { model: "flux-pro", prompt: "a paper-cut mountain range at dawn", num_images: 1 },
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(image.id);
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, ImageModel, Job
client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job = generate_image.sync(client=client, body=GenerateImageRequest(model=ImageModel("flux-pro"), prompt="a paper-cut mountain range at dawn"))
if not isinstance(job, Job):
raise SystemExit(f"refused: {job}")
print(job.id)
Idempotency-Key #
| Property | Value |
|---|---|
| Type | HTTP request header; string |
| Default | Without a key, identical request bodies still share the duplicate window |
| Values | A stable caller-chosen key for one intended generation |
| Applies to | Generation submission; five-minute claim window |
| SDK parameter | TypeScript client options.headers; Python client headers; Rust builder idempotency_key |
The same body with the same key, or with no key both times, returns 409 Conflict inside five minutes and names the earlier job_id. A different key means a deliberate new generation of the same body and can return 202. The 409 is never billed. The CLI accepts --idempotency-key or NOLGIA_IDEMPOTENCY_KEY.
curl -s https://api.nolgia.ai/v1/generate/image \
-H "Authorization: Bearer $NOLGIA_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: mountain-take-1" \
-d '{"model":"flux-pro","prompt":"a paper-cut mountain range at dawn"}'
import { createNolgiaClient } from "@nolgia/sdk";
const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!, undefined, {
headers: { "Idempotency-Key": "mountain-take-1" },
});
const { data: image, error } = await nolgia.POST("/generate/image", {
body: { model: "flux-pro", prompt: "a paper-cut mountain range at dawn", num_images: 1 },
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(image.id);
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, ImageModel, Job
client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"], headers={"Idempotency-Key": "mountain-take-1"})
job = generate_image.sync(client=client, body=GenerateImageRequest(model=ImageModel("flux-pro"), prompt="a paper-cut mountain range at dawn"))
if not isinstance(job, Job):
raise SystemExit(f"refused: {job}")
print(job.id)
X-Nolgia-Surface #
| Property | Value |
|---|---|
| Type | Optional HTTP request header; string |
| Default | Omitted; a server-authenticated platform agent can still receive hermes attribution |
| Values | The known calling surfaces below; the header is not an enum allow-list |
| Applies to | Calling-surface attribution on generation and related writes |
| SDK parameter | TypeScript client options.headers; Python client headers; Rust builder surface |
| Known value | Calling surface |
|---|---|
cli |
Nolgia CLI |
claude-code |
Claude Code integration |
codex |
Codex integration |
hermes |
Legacy value naming the platform's own agent (NOLGIA Agent). Kept for compatibility; not a product name. |
pipeline |
Pipeline runtime |
The CLI sets this header. Values are trimmed, lowercased and capped at 64 characters when persisted with a generation. Use pipeline for your own pipeline. hermes names the platform's agent: sending that string does not turn a customer token into a server-minted agent credential. The header itself is client-supplied attribution, not proof of identity.
curl -s https://api.nolgia.ai/v1/generate/image \
-H "Authorization: Bearer $NOLGIA_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Nolgia-Surface: pipeline" \
-d '{"model":"flux-pro","prompt":"a paper-cut mountain range at dawn"}'
import { createNolgiaClient } from "@nolgia/sdk";
const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!, undefined, {
headers: { "X-Nolgia-Surface": "pipeline" },
});
const { data: image, error } = await nolgia.POST("/generate/image", {
body: { model: "flux-pro", prompt: "a paper-cut mountain range at dawn", num_images: 1 },
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(image.id);
import os
from nolgia import AuthenticatedClient
from nolgia.api.generate import generate_image
from nolgia.models import GenerateImageRequest, ImageModel, Job
client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"], headers={"X-Nolgia-Surface": "pipeline"})
job = generate_image.sync(client=client, body=GenerateImageRequest(model=ImageModel("flux-pro"), prompt="a paper-cut mountain range at dawn"))
if not isinstance(job, Job):
raise SystemExit(f"refused: {job}")
print(job.id)
X-Request-Id #
| Property | Value |
|---|---|
| Type | Optional HTTP request header; string |
| Default | Request middleware assigns an id when absent |
| Values | Your request correlation id |
| Applies to | Request tracing and the request_id field in problem responses |
| SDK parameter | TypeScript client options.headers; Python client headers |
Save the request id with your own logs. The API accepts the header, includes it in its CORS allow-list, and echoes the middleware request id as request_id in problem bodies. Use Idempotency-Key, described above, when intentionally grouping retries of one generation.
curl -s https://api.nolgia.ai/v1/me \
-H "Authorization: Bearer $NOLGIA_TOKEN" \
-H "X-Request-Id: mountain-request-1"
import { createNolgiaClient } from "@nolgia/sdk";
const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!, undefined, {
headers: { "X-Request-Id": "mountain-request-1" },
});
const { data, error } = await nolgia.GET("/me");
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
console.log(data);
import os
from nolgia import AuthenticatedClient
from nolgia.api.auth import get_current_user
from nolgia.models import User
client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"], headers={"X-Request-Id": "mountain-request-1"})
account = get_current_user.sync(client=client)
if not isinstance(account, User):
raise SystemExit(f"refused: {account}")
print(account.to_dict())
timeout_seconds #
| Property | Value |
|---|---|
| Type | Query parameter; integer seconds |
| Default | OpenAPI declares 300 seconds; the current handler uses 30 seconds when omitted, so pass an explicit value |
| Values | 1 through 900 |
| Applies to | GET /jobs/{id}/wait |
| SDK parameter | TypeScript params.query.timeout_seconds; Python timeout_seconds; Rust request builder timeout_seconds |
The server holds this request until the job is terminal or the wait window closes. This parameter changes how long you wait for a response, not the job's generation deadline.
curl -s "https://api.nolgia.ai/v1/jobs/$JOB_ID/wait?timeout_seconds=120" \
-H "Authorization: Bearer $NOLGIA_TOKEN"
import { createNolgiaClient } from "@nolgia/sdk";
const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const { data, error, response } = await nolgia.GET("/jobs/{id}/wait", {
params: { path: { id: process.env.JOB_ID! }, query: { timeout_seconds: 120 } },
});
if (response.status === 408) console.log("Still running; wait again.");
else if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
else console.log(data);
import os
from nolgia import AuthenticatedClient
from nolgia.api.jobs import wait_for_job
from nolgia.models import Job
client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
response = wait_for_job.sync_detailed(os.environ["JOB_ID"], client=client, timeout_seconds=120)
if response.status_code == 408:
print("Still running; wait again.")
elif isinstance(response.parsed, Job):
print(response.parsed.to_dict())
else:
raise SystemExit(f"refused: {response.parsed}")
| Parameter | In | Required | Description |
|---|---|---|---|
id |
path | Yes | Job UUID. |
timeout_seconds |
query | No |
ticket #
| Property | Value |
|---|---|
| Type | Query parameter; opaque string |
| Default | None; required for the job stream |
| Values | A fresh ticket from POST /jobs/{id}/sse-ticket, valid for 60 seconds and one use |
| Applies to | GET /jobs/{id}/sse |
| SDK parameter | Ticket endpoint's ticket response field, passed in the stream URL |
Create the ticket with your bearer token, then use it as the stream's only credential. Do not add a bearer header to the stream request. On reconnect, issue a new ticket; a consumed ticket cannot be reused. The TypeScript and Python stream readers below are examples that print the received SSE bytes; Streaming explains the frames.
curl -sS -X POST "https://api.nolgia.ai/v1/jobs/$JOB_ID/sse-ticket" -H "Authorization: Bearer $NOLGIA_TOKEN"
curl -N "https://api.nolgia.ai/v1/jobs/$JOB_ID/sse?ticket=<ticket from the response>"
import { createNolgiaClient } from "@nolgia/sdk";
const nolgia = createNolgiaClient(process.env.NOLGIA_TOKEN!);
const id = process.env.JOB_ID!;
const { data, error } = await nolgia.POST("/jobs/{id}/sse-ticket", {
params: { path: { id } },
});
if (error) throw new Error(`${error.title}: ${error.detail ?? ""}`);
const response = await fetch(`https://api.nolgia.ai/v1/jobs/${id}/sse?ticket=${encodeURIComponent(data.ticket)}`);
if (!response.ok || !response.body) throw new Error(`stream: ${response.status}`);
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
for (;;) {
const { done, value } = await reader.read();
if (done) break;
process.stdout.write(value);
}
import os
import httpx
from nolgia import AuthenticatedClient
from nolgia.api.jobs import create_job_sse_ticket
from nolgia.models import SSETicket
client = AuthenticatedClient(base_url="https://api.nolgia.ai/v1", token=os.environ["NOLGIA_TOKEN"])
job_id = os.environ["JOB_ID"]
ticket = create_job_sse_ticket.sync(job_id, client=client)
if not isinstance(ticket, SSETicket):
raise SystemExit(f"refused: {ticket}")
with httpx.stream("GET", f"https://api.nolgia.ai/v1/jobs/{job_id}/sse", params={"ticket": ticket.ticket}, timeout=None) as response:
response.raise_for_status()
for line in response.iter_lines():
print(line)
Response headers #
These headers describe a response; do not send them to configure model retries.
| Header | Value and where it appears | What to do |
|---|---|---|
Retry-After |
Seconds until retry: public share resolver 429 responses; OAuth retry responses use 5; busy edit sessions use 2 |
Wait at least that interval before retrying the refused operation |
Retry-After-Reset |
RFC 3339 reset timestamp on the per-account generation-quota 429 |
Wait until the quota resets; a concurrent-generation refusal does not supply this header |
Content-Type: application/problem+json |
Authentication and handler problem responses | Parse the problem body and branch on status and, when present, code |
Content-Type: application/json |
Ordinary JSON API responses | Parse the endpoint's response schema |
Content-Type: text/event-stream |
Job and agent SSE streams | Consume event frames until the stream closes |
| Field | Type | Required | Description |
|---|---|---|---|
code |
string | No | Machine-readable error code.… |
type |
string | Yes | A URI reference identifying the problem type. |
title |
string | Yes | |
status |
integer | Yes | |
detail |
string | No | |
instance |
string | No | |
job_id |
string | No | The job this refusal points at, so a client can follow it without reading detail.… |
request_id |
string | No |

