Sessions
Server-side conversation continuity. You send only the new turn. We assemble the context. It is opt-in per request with one field, session_id. Every session-mode tool (list, inspect, cost, delete) lives under /v1/conversations.
The one-field contract
Add session_id (a UUID you mint, canonical hyphenated hex, case-insensitive) to any /v1/chat/completions request:
curl -sS $IRONSTRATUM_BASE_URL/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $IRONSTRATUM_API_KEY" \
-d '{
"model": "qwen3.8-27b",
"session_id": "7b9dc46e-1f0a-4c1e-8f2b-3a9d10e11f01",
"messages": [{"role": "user", "content": "Remember this number: 42"}]
}'
Two conventions do all the work:
- Delta-only messages. In session mode,
messagescarries ONLY the new turn. The gateway prepends the stored conversation prefix: you never resend history, so you pay network for one turn, not the whole transcript. - Unseen id auto-creates. The first request with a fresh
session_idcreates the conversation; subsequent requests append. No separate create call exists.
The response echoes session_id on session-mode turns and streams. It is an additive field, simply absent on full-context requests. Non-stream and stream: true behave identically. The id rides every chunk.
Without session_id, nothing changes. Full-context requests work exactly as before. They are stored passively under a gateway-minted id. See privacy for what is kept and for how long.
Overflow: the context law
The assembled context is every stored turn plus your new delta. It is checked against the model's context_tokens (from GET /v1/models) before anything reaches the model. Over the limit is a fail-fast 400 context_length_exceeded:
{
"error": {
"message": "The assembled session context exceeds this model's context_tokens. Start a new session_id or trim the conversation.",
"type": "invalid_request_error",
"param": "messages",
"code": "context_length_exceeded"
}
}
No partial state is created. The conversation is untouched. Remediation is yours to choose. Mint a new session_id (fresh context), or delete the conversation and start over. Models without a published window are not enforced. The check is only as good as the catalog.
Same-session serialization
Concurrent requests against one session_id would interleave turns. The platform prevents it. The second request waits behind a bounded lock (30 s default). If the wait expires, it answers 429 rate_limited with nothing stored. Retry the same request shortly. This is the one live emitter of the 429 envelope (see rate posture). Per-key throttling is separate, still future.
A client that serializes its own turns per session never sees this.
Prefix stability
The stored prefix is immutable history. Turns append. They are never rewritten, reordered, or truncated by the platform. A retry that lands (same session_id, same new turn) appends once. The session transaction commits delta + assistant reply + usage row atomically. An aborted or failed exchange stores nothing. Deleting the conversation is the only act that removes history. It is final. A session_id naming a deleted conversation is never reused. It never revives.
A session may switch models between turns. Each request dispatches under the model it names. The overflow check always uses that request's model window. The conversation's listed model_alias is the model that started it.
Inspecting and deleting
GET /v1/conversations: your key's live conversations, most-recently-active first (limitdefault 25, clamped to 100;totalis the unpaginated count).GET /v1/conversations/{id}: every turn in exchange order plus the per-conversation cost summary (itemized from its ledger rows).DELETE /v1/conversations/{id}: idempotent204for your id, live or already deleted; a foreign or unknown id is the same404 conversation_not_foundas any other not-found.DELETE /v1/conversations: every live conversation of the key, same ledger-integrity law.
Deletion removes content and tombstones the row. The anonymized financial ledger rows survive detached (billing integrity; see privacy). Idle conversations age out on a 30-day default window. The setting is PLATFORM_RETENTION_DAYS, applied internally.
Idempotency composes
Idempotency-Key and session_id work together. A replayed request restores the original response without appending a second turn. Replay hits the cache before the session is touched. Responses larger than the 8 MiB replay cache are not cached. A retry re-executes. In session mode, that appends the turn again. Keep idempotent session requests under the cap.