Choose a model, enter your prompt, and see the result.
HiAPI Blog
HiAPI
Generate it with HiAPI
A working integration that calls Claude Sonnet 4.6 through hiapi's OpenAI-compatible Chat Completions API — a single request that returns a real completion, plus the production patterns (streaming, tool calls, adaptive thinking) you'll actually use once the demo works.
Prerequisite: an hiapi API key. Grab one from the dashboard — it's a single sk-... string, and the same key works across every enabled model in your account, not just this one.
Everything below was run against the live API while writing this piece.
Claude Sonnet 4.6 is a text model on the standard Chat Completions endpoint — not the async /v1/tasks flow hiapi uses for image/video/audio models. One request, one response, no polling.
curl https://api.hiapi.ai/v1/chat/completions \
-H "Authorization: Bearer sk-<your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"messages": [
{"role": "user", "content": "Explain how an HTTP cache works in three short paragraphs."}
]
}'
Response (trimmed):
{
"id": "msg_bdrk_011Cf8Bo25qCVFFQF5ETk8Wf",
"model": "claude-sonnet-4-6",
"object": "chat.completion",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "..." },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 13, "completion_tokens": 4, "total_tokens": 17 }
}
Same call in Python, using only requests:
import requests
resp = requests.post(
"https://api.hiapi.ai/v1/chat/completions",
headers={"Authorization": "Bearer sk-<your-api-key>"},
json={
"model": "claude-sonnet-4-6",
"messages": [
{"role": "user", "content": "Explain how an HTTP cache works in three short paragraphs."}
],
},
timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(data["choices"][0]["message"]["content"])
print(data["usage"]) # prompt_tokens / completion_tokens / total_tokens
Because the shape is OpenAI-compatible, this also works unmodified with the official openai Python/JS SDKs — just point base_url at https://api.hiapi.ai/v1 and pass your hiapi key.
Set "stream": true and read Server-Sent Events. Each chunk carries a delta.content fragment; the stream ends with finish_reason: "stop" on the final chunk followed by a [DONE] sentinel:
curl https://api.hiapi.ai/v1/chat/completions \
-H "Authorization: Bearer sk-<your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"messages": [{"role": "user", "content": "Count 1 to 3"}],
"stream": true
}'
data: {"choices":[{"delta":{"content":"","role":"assistant"},"finish_reason":null,"index":0}]}
data: {"choices":[{"delta":{"content":"Here"},"finish_reason":null,"index":0}]}
data: {"choices":[{"delta":{"content":" you"},"finish_reason":null,"index":0}]}
data: {"choices":[{"delta":{},"finish_reason":"stop","index":0}]}
data: [DONE]
Accumulate choices[0].delta.content across chunks to reconstruct the full text.
Declare functions the same way you would against OpenAI, then replay the assistant's tool_calls message plus a tool result message on the next turn:
curl https://api.hiapi.ai/v1/chat/completions \
-H "Authorization: Bearer sk-<your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"messages": [{"role": "user", "content": "What is the status of task demo-123?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_task_status",
"description": "Look up a task by ID.",
"parameters": {
"type": "object",
"properties": {"task_id": {"type": "string"}},
"required": ["task_id"],
"additionalProperties": false
}
}
}],
"tool_choice": "auto"
}'
The response returns finish_reason: "tool_calls" with the function name and JSON-encoded arguments in choices[0].message.tool_calls. Run your function locally, then send the result back as a role: "tool" message with a matching tool_call_id in the next request — the model continues from there.
Claude Sonnet 4.6 supports an opt-in reasoning pass. Add "thinking": {"type": "adaptive"} and pick an effort level (low, medium, high, or max) via output_config.effort:
{
"model": "claude-sonnet-4-6",
"messages": [{"role": "user", "content": "Compare two approaches and state the trade-offs."}],
"thinking": {"type": "adaptive"},
"output_config": {"effort": "high"}
}
The readable reasoning trace comes back in choices[0].message.reasoning_content; the raw reasoning_details array carries signature metadata you must preserve unchanged if you continue the conversation into a tool call — don't parse, display, or invent it, just pass it straight through on the next request.
Auth failures return HTTP 401 with a hiapi_error envelope:
{
"error": {
"code": "permission_denied",
"message": "This API key is invalid. Check that it is correct or use another API key and try again.",
"type": "hiapi_error"
}
}
Check response.status_code before touching response.json()["choices"], and log error.request_id if you need to escalate — support can trace a specific call from it.
Chat Completions calls aren't idempotent by request ID the way /v1/tasks jobs are — a retried request is a new completion. For production traffic, wrap calls in your own retry-with-backoff on 5xx/timeouts, and cap max_tokens so a retry storm can't run up an unbounded bill.
Is claude-sonnet-4-6 the exact model ID I should send?
Yes — send the bare string claude-sonnet-4-6 in the model field. hiapi routes it through Anthropic's Claude Sonnet 4.6 behind an OpenAI-compatible interface, so no provider-specific prefix is needed.
Does this use the same /v1/tasks flow as hiapi's image and video models?
No. Text models like Claude Sonnet 4.6 use the synchronous POST /v1/chat/completions endpoint — one request, one response (or one SSE stream). /v1/tasks is only for media models (image, video, audio), which run async and return a URL to poll or a callback.
Can I use the OpenAI SDK instead of raw curl/requests?
Yes. Since the endpoint is OpenAI-compatible, point the official openai SDK's base_url at https://api.hiapi.ai/v1 and use your hiapi key as the api_key — no other code changes needed for basic chat, streaming, or tool calls.
Does Claude Sonnet 4.6 support image input?
Yes, via content blocks — set a message's content to an array containing a block with type: "image_url" and image_url.url pointing at a public image URL, alongside your text block.
What happens if I omit thinking?
Adaptive thinking is opt-in per the current release — omit the thinking field (or set thinking.type to disabled) and the model answers directly with no reasoning_content in the response.
Where do I check current pricing before running a large batch? hiapi's pricing page lists live per-token rates for Claude Sonnet 4.6 — check it before budgeting, since rates can change and this article doesn't hardcode a number that could go stale.