Model APIs

Platform headers

On this page
  1. Authorization
  2. Content-Type
  3. Idempotency-Key
  4. X-Nolgia-Surface
  5. X-Request-Id
  6. timeout_seconds
  7. ticket
  8. Response headers
  9. Next steps

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.

shell
curl -s https://api.nolgia.ai/v1/me \
  -H "Authorization: Bearer $NOLGIA_TOKEN"
TypeScript
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);
Python
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.

shell
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"}'
TypeScript
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);
Python
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.

shell
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"}'
TypeScript
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);
Python
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.

shell
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"}'
TypeScript
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);
Python
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.

shell
curl -s https://api.nolgia.ai/v1/me \
  -H "Authorization: Bearer $NOLGIA_TOKEN" \
  -H "X-Request-Id: mountain-request-1"
TypeScript
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);
Python
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.

shell
curl -s "https://api.nolgia.ai/v1/jobs/$JOB_ID/wait?timeout_seconds=120" \
  -H "Authorization: Bearer $NOLGIA_TOKEN"
TypeScript
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);
Python
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.

shell
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>"
TypeScriptexample
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);
}
Pythonexample
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

Next steps #