LLM & Media APIChat & completions

Chat & completions

The native GPUniq chat API — completions, server-side chat sessions with full history, shareable transcripts, the generations library, and natural-language to shell commands.

The native surface at /v1/llm/* returns GPUniq's wrapped envelope and adds what the OpenAI protocol has no room for: server-side chat sessions, USD cost on every response, and the generations library.

If you want a drop-in replacement for api.openai.com instead — for Claude Code, Cursor, Aider or the official SDKs — use OpenAI compatibility.

Requests are authenticated with X-API-Key: gpuniq_... on native routes (a dashboard JWT via Authorization: Bearer also works). The default model when you omit model is claude-haiku-4-5.

Simple chat

response = client.llm.chat("claude-haiku-4-5", "Explain how transformers work")
print(response)

Chat completion (full)

data = client.llm.chat_completion(
    messages=[
        {"role": "system", "content": "You are a helpful AI assistant."},
        {"role": "user", "content": "What is gradient descent?"},
    ],
    model="claude-sonnet-4-6",
    temperature=0.7,
    max_tokens=1000,
    top_p=0.9,
)

print(data["content"])
print(f"Tokens used: {data['tokens_used']}  cost: ${data['cost_usd']:.6f}")

Parameters

body
messages

List of message objects with role ("system", "user", "assistant") and content.

body
model

Model slug (e.g., claude-opus-4-7, gpt-5.2, gemini-3-pro). Defaults to claude-haiku-4-5.

body
max_tokens

Maximum tokens in the response.

body
temperature

Sampling temperature (0.0-2.0). Higher = more creative.

body
top_p

Top-p nucleus sampling parameter.

A non-streaming request asking for max_tokens > 4096 is rejected up front with streaming_required. Set "stream": true or use the job-based long-poll API — see Long generations.

Chat sessions

Persistent conversations stored server-side — the model sees the full history on every call, so you send one message rather than re-uploading the transcript.

Persistent conversations stored server-side — the model sees the full history on every call:

# Create a session
session = client.llm.create_chat_session(
    model="claude-sonnet-4-6",
    title="Research Assistant",
)

# Send messages within the session
reply = client.llm.send_message(
    chat_id=session["id"],
    message="What are the key papers on attention mechanisms?",
    temperature=0.5,
)

# List all sessions
sessions = client.llm.list_chat_sessions(limit=50)

# Get a session with full message history
full = client.llm.get_chat_session(chat_id=session["id"])

# Update title
client.llm.update_chat_session(chat_id=session["id"], title="New Title")

# Delete
client.llm.delete_chat_session(chat_id=session["id"])

Sharing a transcript

POST /v1/llm/chats/{chat_id}/share returns a public link to a read-only copy of the conversation, reusing the existing link if one was already created. Anyone with the token can read it through GET /v1/llm/chats/shared/{share_token} without a key.

curl -X POST https://api.gpuniq.com/v1/llm/chats/42/share \
  -H "X-API-Key: gpuniq_your_key"

Messages and context

EndpointWhat it does
GET /v1/llm/chats/{chat_id}/messagesPage through a session's messages.
DELETE /v1/llm/chats/{chat_id}/messages/{message_id}Remove one message from the history.
GET /v1/llm/chats/{chat_id}/contextThe messages the next turn will be sent with. Pass ?model= to see the history as trimmed for that model's context window.
POST /v1/llm/chats/{chat_id}/turnsRecord a turn you already generated and paid for on a streaming surface, so it lands in the session history. Never charges.

Generating images inside a session

Posting to /v1/llm/chats/{chat_id}/messages with an image model puts the prompt and the resulting image into the chat history as a turn. See Generating an image inside a chat session.

The generations library

Every image, video, music and audio generation you run is recorded. GET /v1/llm/generations returns a page of them, newest first.

Query parameterEffect
kindFilter by media kind.
modelFilter by model slug.
qFree-text search over prompts.
limitPage size, default 40.
before_idPass the previous page's next_before_id to continue. A null there means there is nothing older.

GET /v1/llm/generations/{generation_id} returns one in full; DELETE on the same path removes it.

curl "https://api.gpuniq.com/v1/llm/generations?kind=video&limit=20" \
  -H "X-API-Key: gpuniq_your_key"

Generate terminal commands

POST /v1/llm/generate-commands turns a natural-language task into an ordered list of shell commands, each annotated with a danger_level. The Python SDK has no helper for this endpoint — call it over HTTP.

FieldTypeNotes
promptstringRequired, 1–1000 characters.
max_commandsint1–10, default 5.
modelstringOptional; the server default is used when omitted.
contextobjectOptional — OS, shell history, environment.
import requests

body = requests.post(
    "https://api.gpuniq.com/v1/llm/generate-commands",
    headers={"X-API-Key": "gpuniq_your_key"},
    json={"prompt": "find all Python files larger than 1MB and sort by size",
          "max_commands": 5},
).json()
if body["exception"] != 0:              # refusals arrive as HTTP 200
    raise RuntimeError(body["data"])

for c in body["data"]["commands"]:
    print(f"[{c['danger_level']}] {c['command']}  # {c['description']}")

The response also carries explanation, warnings, alternatives, tokens_used, cost_usd and balance_usd. Per-command fields beyond command, description and danger_level (step, requires_confirmation, expected_output) are written by the model and may be missing. If the model's reply cannot be parsed, commands comes back empty with the reason in explanation — treat an empty list as a result to handle, not as success.

This endpoint predates the shared error catalog: its error_code values are upper-case (INSUFFICIENT_BALANCE), unlike the lower-case codes on every other surface. Compare case-insensitively if you branch on them.

Errors

Every failure returns a structured error_code you can branch on. The full catalog, envelope shapes and recovery recipes live in the Error reference.