kimik3.io/API guide
Kimi K3 API
Kimi K3 speaks the OpenAI Chat Completions format: change one base_url and your existing code runs. Below: auth, parameters, a request that works, and how to tell a real success from a silent failure.
K3 is OpenAI-format compatible. Any OpenAI SDK works — you point base_url at an endpoint that carries kimi-k3 and set the model string. That is the whole integration.
Quickstart
This calls K3 through EvoLink, which carries kimi-k3 on an OpenAI-compatible endpoint. Swap the base_url for any other gateway and the rest is unchanged.
from openai import OpenAI
client = OpenAI(
api_key="YOUR_EVOLINK_API_KEY",
base_url="https://direct.evolink.ai/v1", # <-- the one line you change
)
response = client.chat.completions.create(
model="kimi-k3",
messages=[
{"role": "user", "content": "Explain prompt caching in two sentences."},
],
)
print(response.choices[0].message.content)
print(response.usage)
curl https://direct.evolink.ai/v1/chat/completions \
-H "Authorization: Bearer $EVOLINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kimi-k3",
"messages": [
{"role": "user", "content": "Explain prompt caching in two sentences."}
]
}'
Auth is a bearer token: Authorization: Bearer <key>. Keep it in an environment variable, never in source. The endpoint path is /v1/chat/completions — if you are using an OpenAI SDK, give it the /v1 root and let the SDK append the rest.
The key: where to get one — decide by what you'll call
The code above needs an API key, and the right source depends on one question. Will you only ever call Kimi models? Then go direct to Moonshot — no intermediary, and this page's code works there with base_url="https://api.moonshot.ai/v1". Will K3 sit alongside GPT, Claude, or Gemini? Then you want a gateway — one key and one balance for all of them. The two worth considering are EvoLink and OpenRouter; we measured both head-to-head, and this site's examples default to EvoLink because it returns Moonshot's native response shape unchanged. Three things are identical on every route:
- The rates — $3.00 / $0.30 / $15.00 per 1M tokens, date-stamped.
- The model's behaviour — cache blocks and reasoning billing; it's the same model.
- Your code — OpenAI format everywhere; switching later is one
base_url.
What differs is everything around the call:
| Moonshot direct | Via EvoLink | |
|---|---|---|
| Getting started | A separate Moonshot platform account | One account, 10 free credits, sign up from anywhere in minutes |
| Models on the key | The Kimi family | GPT, Claude, Gemini, K3, and dozens of the world's mainstream models — one key, one endpoint |
| Billing operations | Another balance to fund, watch, and reconcile — per provider you add | One balance and one statement across every model you call |
| Multi-model & agent work | Model routing, fallbacks, and A/B evals mean juggling one account per provider | Routing, fallback, and model comparison are a string change on the same key |
Considering OpenRouter instead? Same list price, same model, same cache — but it renames K3's reasoning_content field, and code written against Moonshot's docs goes silently blind on it. The measured comparison covers that, reliability, and latency.
Signing up drops you into the dashboard with onboarding and 10 free credits. Already have an account? Grab a key from your dashboard →
What a real response looks like
Trimmed, but otherwise exactly what came back:
{
"id": "chatcmpl-6a593017ec44f116fb614895",
"object": "chat.completion",
"created": 1784229923,
"model": "kimi-k3",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "OK",
"reasoning_content": "The user is asking me to reply with exactly \"OK\". This is a simple request with no complications..."
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": 90,
"completion_tokens": 47,
"total_tokens": 137,
"completion_tokens_details": {"reasoning_tokens": 31},
"prompt_tokens_details": {"cached_tokens": 90}
}
}
About cached_tokens: 90 equalling prompt_tokens: this was a repeat call of the same 90-token prompt, and small prompts can hit the cache in full. The 256-token block granularity we measured elsewhere shows up once your prefix passes ~1k tokens — the caching page has both datasets.
Two fields deserve attention because they have no OpenAI equivalent:
message.reasoning_content— K3's thinking, returned alongside the answer. Readcontentfor the answer. Reasoning is not a mode you enable on K3; it is always on.usage.completion_tokens_details.reasoning_tokens— how many output tokens went to thinking. Above, 31 of 47 tokens for a two-letter reply. That is billed at the output rate.
Confirm the call actually worked
An HTTP 200 is not proof of success on K3. Check four things:
modelechoes backkimi-k3— not a fallback the gateway silently substituted.finish_reasonisstop, notlength—lengthwith empty content is the signature of the reasoning-budget trap.contentis a real string, not"".usage.total_tokensis non-zero — and tells you what you spent.
In code, the one assertion worth writing:
choice = response.choices[0]
if choice.finish_reason == "length" and not choice.message.content:
raise RuntimeError(
f"Reasoning consumed the whole budget "
f"({response.usage.completion_tokens_details.reasoning_tokens} reasoning tokens). "
f"Raise max_completion_tokens."
)
Parameters that matter
| Parameter | Default | What you need to know |
|---|---|---|
model | — | Exactly kimi-k3. Not kimi-k3-chat, not moonshot-k3. A wrong ID at least fails loud: HTTP 404 with a did_you_mean hint in the error body (measured 2026-07-18). |
max_completion_tokens | 131,072 | Leave it alone unless you know what you're doing. Reasoning draws from this budget; cap it low and you get billed for an empty string. The full story. Overshooting is not validated either: we sent 2,000,000 — above the documented 1,048,576 ceiling — and got a normal 200, silently clamped (2026-07-18). |
stream | false | Strongly recommended at long context — we measured 52s on a 498k-token prompt. |
stream_options | — | Set {"include_usage": true} or you get no usage block while streaming, and you are blind to spend. |
tools | — | Function calling, max 128 tools, JSON Schema format. |
tool_choice | auto |
auto works (measured — K3 emits tool_calls and finish_reason: "tool_calls"). Naming a specific function returns HTTP 400: "tool_choice 'specified' is incompatible with thinking enabled" — K3's always-on reasoning rules out forced tool choice. Measured 2026-07-18. |
response_format | {"type":"text"} |
Supports json_object and json_schema for structured output. |
prompt_cache_key | null | We could not measure any effect for prefix reuse — caching already happens automatically. What we tested. |
reasoning_effort | — | Through EvoLink, only max is supported (per EvoLink's docs, verified 2026-07-20) — and passing low or high returns HTTP 200 with the value silently ignored, no consistent effect on reasoning depth (our 2026-07-18 re-test). Moonshot's docs for direct access list low / high / max, default max (quickstart, read 2026-07-20). Do not trust it to validate. |
Full parameter and response-schema reference: EvoLink's kimi-k3 API docs (docs.evolink.ai).
Vision input
K3 takes images — with two constraints that break the pattern most OpenAI-vision code assumes. Per Moonshot's official quickstart (read 2026-07-20): public image URLs are not supported — send the image as base64 or as an ms://<file-id> reference — and the message content must be an array of objects, not a plain string. We have not benchmarked vision ourselves yet; this section is documentation, not measurement.
Streaming
Server-sent events, terminated by data: [DONE]. The wrinkle specific to K3: the first tokens you receive are reasoning, not your answer. On realistic short prompts (n=10, direct.evolink.ai, one afternoon window, 2026-07-18) the median was 11.3s to the first reasoning token and 21.4s to the first content token, with single runs anywhere from 2.9s to 40s — heavy hour-to-hour swing. A trivial "say OK" prompt is far faster: 2.8s on 2026-07-16, 3.35s re-measured 07-18. And in three of five 2026-07-16 runs, no content token ever arrived because a 128-token ceiling was consumed by thinking.
stream = client.chat.completions.create(
model="kimi-k3",
messages=[{"role": "user", "content": "Count to three."}],
stream=True,
stream_options={"include_usage": True}, # or you get no usage at all
)
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta
if getattr(delta, "reasoning_content", None):
pass # thinking — usually not what you render
if delta.content:
print(delta.content, end="", flush=True)
If you render reasoning_content to users, know that you are showing them the model's scratchpad. Most products want to show a spinner during reasoning and stream only content.
One more thing to plan for: at peak hours you may hit 429s or capacity errors. Our 2026-07-18 run went 50 calls with zero failures, but that is one day in one window — build a retry path, keep the error reference handy, and check live status if calls start failing.
API FAQ
What is the Kimi K3 model ID?
Exactly kimi-k3. Get it wrong — kimi-k3-chat, say — and you get an HTTP 404 whose error body includes "did_you_mean": "kimi-k3", flags the error as permanent (don't retry the same ID), and points you at GET /v1/models (measured 2026-07-18).
Is Kimi K3 OpenAI-compatible?
Yes. K3 is served over the standard /v1/chat/completions shape, so any OpenAI SDK works unchanged — you set base_url and the model string. The two K3-specific additions are reasoning_content in the message and reasoning_tokens in usage.
Do I need a Moonshot account to use the Kimi K3 API?
No. Any endpoint that carries kimi-k3 works — through EvoLink, one account with 10 free credits reaches K3 alongside GPT, Claude, Gemini, and dozens of the world's mainstream models, at the same rates as Moonshot direct.
What base_url do I use for Kimi K3?
Through EvoLink: https://direct.evolink.ai/v1. Direct to Moonshot: https://api.moonshot.ai/v1 (per Moonshot's quickstart, read 2026-07-20). The rest of your code is identical either way.
Get a key and run the code above
EvoLink carries kimi-k3 on an OpenAI-compatible endpoint — one key reaches GPT, Claude, Gemini, and dozens of the world's mainstream models. 10 free credits, sign up from anywhere — no Chinese phone number.