What you'll build
By the end of this guide you'll have a working call to gpt-6.1-sol, the reasoning-grade text model in hiapi's GPT-6.1 Sol family, returning streamed text from a single HTTP request. You'll get a copy-paste curl command, a small Python client, and the handful of rules that trip people up — the two biggest being that the endpoint is /v1/responses (not /v1/chat/completions) and that streaming is mandatory.
Prerequisites: a hiapi API key. Create one on the API Keys dashboard and keep it secret — every request sends it as Authorization: Bearer sk-<your-key>.
gpt-6.1-sol is text-only (chat, reasoning, coding). For capabilities and an online try-it box, see the gpt-6.1-sol model page.
Minimal working example
The Sol family speaks the Responses API: POST /v1/responses. Two things are non-negotiable:
"stream": true— the model rejectsstream:falsewith400 invalid_request_error(stream: must be true).inputis an array of message objects — a bare string returnsinput: has incorrect typeonce streaming is on.
curl
curl -N https://api.hiapi.ai/v1/responses \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6.1-sol",
"input": [
{
"type": "message",
"role": "user",
"content": [
{ "type": "input_text", "text": "Explain idempotency keys in one sentence." }
]
}
],
"stream": true
}'
-N disables curl's output buffering so you see the Server-Sent Events (SSE) arrive live. The stream is a sequence of event: / data: pairs; the text you want shows up as response.output_text.delta chunks and is repeated in full in the terminal response.completed event.
Python
No SDK required — hiapi is plain HTTP, so requests with stream=True is enough:
import json
import requests
API_KEY = "sk-<your-key>"
payload = {
"model": "gpt-6.1-sol",
"input": [
{
"type": "message",
"role": "user",
"content": [
{"type": "input_text", "text": "Explain idempotency keys in one sentence."}
],
}
],
"stream": True,
}
with requests.post(
"https://api.hiapi.ai/v1/responses",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json=payload,
stream=True,
timeout=120,
) as resp:
resp.raise_for_status()
text = ""
for line in resp.iter_lines(decode_unicode=True):
if not line or not line.startswith("data:"):
continue
event = json.loads(line[len("data:"):].strip())
etype = event.get("type")
if etype == "response.output_text.delta":
text += event["delta"]
elif etype == "response.completed":
usage = event["response"]["usage"]
print(f"\n[tokens: in={usage['input_tokens']} "
f"out={usage['output_tokens']} total={usage['total_tokens']}]")
print(text)
Keying off the JSON's own type field (rather than the event: line) keeps the parser robust: each SSE frame arrives as two lines — event: <type> and data: <json> — so filtering to data: lines and reading event["type"] is all you need.
Production notes
- Streaming is the only mode. There is no non-streaming variant;
stream:falseis a 400. Build your client around SSE from the start, with a read timeout and a reconnect/retry on dropped connections. - Don't send
max_output_tokens. This execution profile rejects it (not supported by this execution profile). Constrain length through the prompt or a system instruction instead. - System prompt → top-level
instructions. Put persona and formatting rules there rather than in a message:
{
"model": "gpt-6.1-sol",
"instructions": "You are a terse assistant. Answer in one short sentence.",
"input": [
{ "type": "message", "role": "user",
"content": [{ "type": "input_text", "text": "What is a webhook?" }] }
],
"reasoning": { "effort": "low" },
"stream": true
}
- Tune reasoning vs. cost. gpt-6.1-sol is a reasoning model;
reasoning.effortacceptslowandmedium(defaultmedium). Lower effort spends fewer reasoning tokens — and reasoning tokens are billable, surfaced underusage.output_tokens_details.reasoning_tokensin the final event. - Multi-turn. Continue a conversation by appending prior turns (both user and assistant messages) to the
inputarray on the next request. - Auth failures are 401. A bad or revoked key returns
401with codepermission_denied("This API key is invalid."). Catch it instead of retrying — a retry won't fix a wrong key. - Pricing is per token (input + output + reasoning). Check current rates on the pricing page rather than hardcoding numbers.
Related reading
- gpt-6.1-sol model page — capabilities, context window, and an online try-it box.
- hiapi API docs — authentication, endpoints, and the shared request format.
- Pricing — per-token rates and credit top-ups.
FAQ
Why do I get "Model does not support this protocol"?
You called /v1/chat/completions. The Sol family is Responses-only — switch the URL to /v1/responses. (On related models the message reads "This model currently supports /v1/responses only.")
Why "stream: must be true"?
gpt-6.1-sol only streams. Set "stream": true and read the SSE response; there is no buffered, non-streaming reply.
How do I add a system prompt?
Use the top-level instructions field (a plain string), not a system message inside input.
Can I cap the output length with max_output_tokens?
No — this profile returns invalid_parameter for max_output_tokens. Ask for brevity in the prompt or instructions instead.
How do I get the final answer without handling every delta?
Read the last event, response.completed: the full text is at response.output[0].content[0].text, and token usage is at response.usage.
Is gpt-6.1-sol the same as gpt-5.6-sol?
They're the same Sol family and share this Responses-API streaming contract; gpt-6.1-sol is the newer generation. Both reject /v1/chat/completions.



