Skip to main content

Sessions: group requests into a conversation

/ API docs

← API quickstartView as Markdown

A session is one conversation: every request that belongs to it, grouped under one row in the dashboard's Transactions, with the conversation's total tokens and cost. Sessions also let context compaction (the Context Compacter page) keep a long conversation within the model's context window.

Supported tools group by themselves

OpenCode, Claude Code, Claude Desktop, Codex, Harness AI, Zed, RikkaHub and LobeHub (through its New API entry) already group their requests: one conversation in the tool is one session in the dashboard, with nothing to configure. Chatbox requests appear as separate sessions for now.

Everything else, such as your own scripts and SDK calls, starts a new session with every request unless it names one.

Name the session with a header

Send the same opencheese-session-uuid header with every request of the conversation:

bash
SESSION=$(uuidgen)

curl https://api.opencheese.dev/v1/chat/completions \
  -H "Authorization: Bearer $OPENCHEESE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "opencheese-session-uuid: $SESSION" \
  -d '{"model": "MODEL_ID", "messages": [{"role": "user", "content": "Name three cheeses."}]}'

The header works the same way on /v1/chat/completions, /v1/responses, /v1/messages and the image endpoints, so a conversation that mixes them stays one session.

When to send it

Send one session id per conversation when:

  • a chat or agent loop sends several requests that build on each other;
  • your app makes background calls for a conversation, such as a title or a summary: give them the conversation's id so their cost is counted with it;
  • one task spans several models: the session keeps them together.

Leave the header out when the requests are independent, such as a batch of classifications or a one-off question. Each request is then its own session.

Never reuse one id for unrelated conversations: they would appear as one session, and context compaction would treat them as one conversation.

Format

  • Use a new random UUID (version 4) for each conversation, such as 2f1c6d0e-8a4b-4c55-9b7e-3d2a1f0e9c84.
  • The gateway also accepts any id of 1 to 256 characters made of letters, digits, _, ., : and -, but a UUID is the safe choice.
  • Any other value is refused with invalid_session_header (HTTP 400; on /v1/chat/completions it arrives as the assistant's reply).

Every chat, responses, messages and image response returns the session id it was recorded under in the opencheese-session-uuid response header, streaming responses included. Without your own header that is a new id, which you can send back on the next request to continue the same session.

Python

python
import uuid
from openai import OpenAI

client = OpenAI(base_url="https://api.opencheese.dev/v1", api_key="YOUR_OPENCHEESE_API_KEY")
session = str(uuid.uuid4())
history = [{"role": "user", "content": "Name three cheeses."}]

first = client.chat.completions.create(
    model="MODEL_ID",
    messages=history,
    extra_headers={"opencheese-session-uuid": session},
)
history.append({"role": "assistant", "content": first.choices[0].message.content})
history.append({"role": "user", "content": "Which one melts best?"})

second = client.chat.completions.create(
    model="MODEL_ID",
    messages=history,
    extra_headers={"opencheese-session-uuid": session},
)
print(second.choices[0].message.content)

With the Anthropic SDK, pass the same header as extra_headers to client.messages.create, or once for the whole client as default_headers.

JavaScript

javascript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.opencheese.dev/v1",
  apiKey: process.env.OPENCHEESE_API_KEY,
  defaultHeaders: { "opencheese-session-uuid": crypto.randomUUID() }
});

const reply = await client.chat.completions.create({
  model: "MODEL_ID",
  messages: [{ role: "user", content: "Name three cheeses." }]
});
console.log(reply.choices[0].message.content);

A client created with defaultHeaders puts all of its requests in one session, so create one client per conversation, or pass the header per request with client.chat.completions.create(body, { headers: { "opencheese-session-uuid": id } }).

The cheese has holes. Your infrastructure should not.