Responses API
The stateful /v1/responses endpoint, with server-side conversation history.
Telluvian implements OpenAI's Responses API as well as Chat Completions. The official SDKs work against it unchanged:
from openai import OpenAI
client = OpenAI(
api_key="sk_live_...",
base_url="https://api.telluvian.ai/v1",
)
response = client.responses.create(
model="google/gemma-4-31b-it",
input="Who was the first person on Mars?",
)
print(response.output_text)What makes it different
Chat Completions is stateless: you re-send the whole conversation on every call. The Responses API is stateful. You send only the new input plus the id of the previous response, and we rebuild the history server-side.
first = client.responses.create(
model="google/gemma-4-31b-it",
input="My favourite colour is crimson.",
)
second = client.responses.create(
model="google/gemma-4-31b-it",
previous_response_id=first.id,
input="What is my favourite colour?", # the colour is not re-sent
)
print(second.output_text) # "Crimson."Which should you use?
Use Chat Completions if you already keep the conversation in your own application state. It is one fewer thing for us to hold, and it is what most existing code and frameworks expect.
Use Responses if you would otherwise be storing the transcript purely to replay it to us, or if you are following OpenAI examples written against it.
Probe scores
Scoring is off by default. Set include_scores: true to enable it. The per-token output rides on
the content part, next to the text it describes:
response = client.responses.create(
model="google/gemma-4-31b-it",
extra_body={"include_scores": True},
input="Who was the first person on Mars?",
)
part = response.output[0].content[0]
for token, score in zip(part.tokens, part.scores["hallucination"]):
if score is not None and score > 0.5:
print(f"flagged: {token!r}")The same null-entry rule applies as in Reading the scores: the
array is always as long as tokens, but an individual entry may be null.
Omit include_scores, or pass include_scores: false through extra_body,
for an unscored request without the verification fee.
Streaming
The stream is a sequence of typed events, not the uniform chunks of Chat Completions:
stream = client.responses.create(
model="google/gemma-4-31b-it",
input="Tell me about Ada Lovelace.",
stream=True,
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)
elif event.type == "response.completed":
print(f"\n{event.response.usage.output_tokens} tokens")Events emitted, in order:
| Event | Carries |
|---|---|
response.created | The response object, status: "in_progress" |
response.in_progress | Same |
response.output_text.delta | delta (text), and available scores when probing is enabled |
response.output_text.done | The complete text |
response.completed | The final response, with usage |
Managing stored responses
Responses are stored by default so they can be continued.
fetched = client.responses.retrieve(response.id) # GET
client.responses.delete(response.id) # DELETEPass store=False to make the response unavailable for retrieval or continuation
with previous_response_id. This is not a no-storage setting: request auditing,
billing, and configured transcript logging still apply.
client.responses.create(
model="google/gemma-4-31b-it",
input="Nothing to keep.",
store=False,
)Field mapping
If you are porting from Chat Completions:
| Chat Completions | Responses |
|---|---|
messages | input (a string, or a list of messages) |
a leading system message | instructions |
max_tokens | max_output_tokens |
choices[0].message.content | output_text |
usage.prompt_tokens | usage.input_tokens |
usage.completion_tokens | usage.output_tokens |
finish_reason: "length" | status: "incomplete" |
instructions apply to one call only
instructions is not inherited by a response that continues this one. If
a later call in the chain needs the same instruction, pass it again. This
matches OpenAI's behaviour, and it means a system prompt can never become
silently sticky across a conversation.
Pricing
Identical to Chat Completions: the same per-token rates, the same verification
fee when explicitly enabled. Routing adds $0.05 per 1M input tokens when
telluvian/gallery-1 picks the model. See
Pricing. Continuing a chain re-sends the stored
history to the model, so input tokens grow with the conversation, exactly as
they would if you had re-sent it yourself.