DEV Community

Cover image for Kimi K3.1 Pro API: Endpoints, Tool Calling, Caching and Errors
Hassann
Hassann

Posted on Originally published at apidog.com

Kimi K3.1 Pro API: Endpoints, Tool Calling, Caching and Errors

The Kimi K3.1 Pro API runs at https://api.moonshot.ai/v1 with model IDs kimi-k3.1-pro and kimi-k3.1-pro-highspeed. It speaks three wire formats: OpenAI Chat Completions, the Responses API and Anthropic Messages, so the SDKs you already use work with a changed base URL. The model unlocks after a $1 minimum top-up.

Try Apidog today

This is the reference for production code. For your first call, streaming and the Codex or Claude Code setups, read how to use Kimi K3.1 Pro; for costs, see Kimi K3.1 Pro pricing. Facts come from Moonshot's K3.1 Pro quickstart and linked docs, read October 24, 2026.

Kimi K3.1 Pro Responses API, Anthropic API and Chat Completions

Moonshot exposes K3.1 Pro through three API surfaces. Pick the one your client library or agent already speaks; the model, key and billing are the same on all three.

Surface Format Endpoint Typical client
Chat Completions OpenAI https://api.moonshot.ai/v1/chat/completions openai SDK, most frameworks
Responses API OpenAI Responses https://api.moonshot.ai/v1/responses Codex (wire_api = "responses")
Messages API Anthropic https://api.moonshot.ai/anthropic/v1/messages Anthropic SDK, Claude Code

They differ in how you set the cache TTL and where usage lands (see caching below). Coming from K3? Our Kimi K3 API guide still applies; K3.1 Pro is a post-trained K3 with the same 1,048,576-token context.

Kimi K3.1 Pro API key: unlock and check access

You need a funded account and a key from the right product. Four steps:

  1. Top up at least $1 on the Kimi API platform. K3.1 Pro is a flagship model and unlocks only after a successful top-up.
  2. Create a key in the API keys console and export it as MOONSHOT_API_KEY.
  3. Confirm the model is visible to that key with GET /v1/models.
  4. Call kimi-k3.1-pro from code.
curl https://api.moonshot.ai/v1/models \
  --header "Authorization: Bearer $MOONSHOT_API_KEY" | grep -o '"kimi-k3.1-pro[^"]*"'
Enter fullscreen mode Exit fullscreen mode

If the model isn't listed, fix that first. Kimi API, Kimi Code and Kimi Membership are separate products: a Kimi Code key won't work on the API endpoint, and a membership doesn't become API balance.

Request parameters that matter for K3.1 Pro

Most OpenAI parameters behave as you'd expect. These are the ones that differ or catch people out:

Parameter What to know
reasoning_effort Top-level field: "low", "high" or "max" (default "max"). Thinking is always on.
thinking Don't send it. K3.1 Pro doesn't support it; use reasoning_effort instead.
max_completion_tokens Defaults to 131072. Maximum output is 1,048,576 minus your prompt tokens.
response_format json_schema with strict: true. Parse message.content only, never reasoning_content.
partial Put "partial": true on a final assistant message to continue from a prefix.
tool_choice "required" forces at least one tool call; "auto" lets the model decide.
prompt_cache_options {"mode": "implicit", "ttl": "5m" or "1h"} on Chat Completions and Responses.

Reasoning tokens count toward your usage, so use "low" for classification and extraction. Preserved Thinking is always on, so every assistant message goes back with its reasoning_content intact (thinking models guide).

Kimi K3.1 Pro tool calling: a complete loop in Python

A production tool loop on K3.1 Pro follows four rules from Moonshot's docs:

  • Force a tool call on the first turn with tool_choice="required", then switch to "auto".
  • Append the complete assistant message, reasoning_content and tool_calls included.
  • Send one tool message per tool_call_id.
  • Cap the number of turns so a confused model can't loop forever.
import json, os
from openai import OpenAI

client = OpenAI([REDACTED CREDENTIAL],
                base_url="https://api.moonshot.ai/v1")

TOOLS = [{"type": "function", "function": {
    "name": "get_order_status",
    "description": "Look up an order's shipping status by ID",
    "parameters": {"type": "object",
                   "properties": {"order_id": {"type": "string"}},
                   "required": ["order_id"]}}}]

def get_order_status(order_id):
    return {"order_id": order_id, "status": "shipped"}

messages = [{"role": "user", "content": "Where is order A-1042?"}]
tool_choice = "required"
for _ in range(8):  # hard cap on turns
    resp = client.chat.completions.create(
        model="kimi-k3.1-pro", reasoning_effort="high",
        messages=messages, tools=TOOLS, tool_choice=tool_choice)
    msg = resp.choices[0].message
    messages.append(msg)  # whole message, not msg.content
    if not msg.tool_calls:
        print(msg.content)
        break
    for call in msg.tool_calls:
        result = get_order_status(**json.loads(call.function.arguments))
        messages.append({"role": "tool", "tool_call_id": call.id,
                         "content": json.dumps(result)})
    tool_choice = "auto"
Enter fullscreen mode Exit fullscreen mode

The classic bug is appending msg.content instead of msg, which drops tool_calls and reasoning_content.

Tool calling at scale with search_tools

When your agent has dozens or hundreds of tools, don't send every definition on every request. Moonshot's K3 tool calling best practice recommends this flow:

  1. Declare one search_tools function (your backend implements it) plus a few core tools.
  2. Set tool_choice: "required" on the first turn so the model retrieves before answering.
  3. Inject the matching tool definitions through a system message that carries a tools field.
  4. Let the model call the loaded tools on later turns, with tool_choice back on "auto".
# after search_tools returns ["create_github_pr"]
messages.append({"role": "system",
                 "tools": [CATALOG["create_github_pr"]]})
Enter fullscreen mode Exit fullscreen mode

Injected definitions use the top-level tools format and apply from that message onward. The server doesn't retain them, so keep the message in later requests. Neither changing tool_choice nor appending a definition breaks the prefix cache.

Vision and video input

K3.1 Pro accepts images and video alongside text and returns text. Make content an array of parts: an image_url part (the quickstart example sends a base64 data URL, and notes public image URLs aren't supported) or a video_url part that points at an uploaded file with an ms:// ID.

from pathlib import Path

video = client.files.create(file=Path("demo.mp4"), purpose="video")
content = [{"type": "video_url", "video_url": {"url": f"ms://{video.id}"}},
           {"type": "text", "text": "Summarize this video."}]
Enter fullscreen mode Exit fullscreen mode

Pass content as the user message, and delete the file with client.files.delete(video.id) when you're done.

Context caching in code

Caching is automatic for repeated prefixes with a 5-minute default TTL. Cache hits bill at $0.20 per million tokens against $2.00 for uncached input, and a 1-hour write costs $4.00 against $2.00 for 5 minutes. On a 1M-token prefix, the 1-hour TTL pays for itself after two hits.

Put stable content first (system prompt, tool definitions, docs), changing content last, and no timestamps in the prefix. With the openai SDK, pass the TTL through extra_body:

resp = client.chat.completions.create(
    model="kimi-k3.1-pro",
    messages=[{"role": "system", "content": DOCS},
              {"role": "user", "content": question}],
    extra_body={"prompt_cache_options": {"mode": "implicit", "ttl": "1h"}},
)
d = resp.usage.prompt_tokens_details
print(resp.usage.prompt_tokens, d.cached_tokens,
      getattr(d, "cache_write_tokens", 0))
Enter fullscreen mode Exit fullscreen mode

The Anthropic API sets the TTL with a top-level cache_control field; markers inside messages are ignored:

curl https://api.moonshot.ai/anthropic/v1/messages \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer $MOONSHOT_API_KEY" \
  --data '{"model": "kimi-k3.1-pro", "max_tokens": 256,
    "cache_control": {"type": "ephemeral", "ttl": "1h"},
    "messages": [{"role": "user", "content": "Hello"}]}'
Enter fullscreen mode Exit fullscreen mode

Where cache usage shows up depends on the surface:

Surface Cache read Cache write
Chat Completions usage.prompt_tokens_details.cached_tokens usage.prompt_tokens_details.cache_write_tokens
Responses usage.input_tokens_details.cached_tokens usage.input_tokens_details.cache_write_tokens
Messages usage.cache_read_input_tokens usage.cache_creation_input_tokens

When streaming Chat Completions, set stream_options.include_usage=true to get usage in the final chunk. Each hit renews the TTL, which is locked at first write. Full rules: the context caching guide.

Kimi K3.1 Pro API errors and fixes

Most failures fall into six patterns. Check error.type on every 429, because the fix depends on it.

Symptom Cause Fix
401 or 404 Wrong product key, region mismatch, no balance, or wrong model name Use a Kimi API key, check balance, confirm the model in GET /v1/models, clear stale env vars and proxies
429 engine_overloaded_error Server capacity Wait per Retry-After, back off, lower concurrency. Topping up won't help.
429 rate_limit_reached_error Your org hit concurrency, RPM, TPM or TPD Slow down or move up a tier
429 exceeded_current_quota_error Low balance, overdue account or expired voucher Check the balance API and top up
finish_reason: "length" Output hit max_completion_tokens Raise the limit or continue with partial mode
Same tool called again and again Broken message layout Append the message as-is, match every tool_call_id, assemble streamed tool_calls fully, then add client-side repeat detection

Watch retries. The OpenAI SDK retries 2 times by default on connection errors, 408, 409, 429 and 5xx, so one call can become three requests against your RPM. On a low tier, lower the client's max_retries and back off on error.type yourself. Requests interrupted by a 429 aren't charged.

If a third-party agent fails, call the API directly with the same key, endpoint and model. If that works, the tool is the problem. See the troubleshooting page and error codes.

Kimi K3.1 Pro rate limits by tier

Your cumulative top-up sets your tier on the limits page:

Tier Cumulative top-up Concurrency RPM TPM
Tier0 $1 1 3 500,000 (1.5M per day)
Tier1 $10 15 100 2,000,000
Tier2 $20 40 100 3,000,000
Tier3 $100 50 200 3,000,000
Tier4 $1,000 60 200 4,000,000
Tier5 $3,000 100 300 5,000,000

Tier0 allows 3 requests per minute, and every turn of a tool loop is a request. A five-turn agent run already spills past one minute at that tier, so budget $10 cumulative before you test agents seriously.

Contract-test the Kimi API with Apidog CLI

A contract test catches the day your tool loop stops getting tool_calls back. Let your coding agent build it with Apidog CLI. Install and log in once:

npm install -g apidog-cli@latest
apidog login --with-token <YOUR_TOKEN>
apidog skill install
Enter fullscreen mode Exit fullscreen mode

Then prompt Claude Code, Codex or whichever agent you use:

In Apidog project <projectId>, create an environment for https://api.moonshot.ai/v1
and an endpoint for POST /chat/completions. Add a test case that sends model
kimi-k3.1-pro, reasoning_effort "low", one get_order_status tool and
tool_choice "required". Assert status 200 and that choices[0].message.tool_calls
is non-empty. Run it and report failures.
Enter fullscreen mode Exit fullscreen mode

The agent reads the schema, validates its payload and runs the case:

apidog environment create kimi-prod --project <projectId> --base-url https://api.moonshot.ai/v1
apidog endpoint create --project <projectId> --file ./endpoint.json
apidog cli-schema get test-case-create
apidog cli-schema validate test-case-create --file case.json
apidog test-case create --project <projectId> --file case.json
apidog run --test-case <caseId> --project <projectId> -e <envId> -r cli,json
Enter fullscreen mode Exit fullscreen mode

Test cases need a valid category; apidog test-case category --project <projectId> lists them. Once the run passes, swap -r cli,json for -r junit with --out-dir and the same check gates your CI, as our Apidog CLI CI/CD guide shows. Agent setup lives in Apidog CLI in Claude Code. Apidog's Free plan covers up to 4 users.

FAQ

What is the base URL for the Kimi K3.1 Pro API?

https://api.moonshot.ai/v1 for Chat Completions and the Responses API, and https://api.moonshot.ai/anthropic for the Anthropic-compatible Messages API.

Does the Kimi K3.1 Pro API support the thinking parameter?

No. Thinking is always on. Control it with the top-level reasoning_effort field ("low", "high" or "max").

Why do I get 429 right after topping up?

Read error.type. engine_overloaded_error is server capacity and a top-up won't fix it. rate_limit_reached_error means your tier's limits, and Tier0 allows only 3 RPM.

How do I know whether caching is working?

A non-zero cache read field in usage means a hit: prompt_tokens_details.cached_tokens on Chat Completions or cache_read_input_tokens on Messages.

Is there a free Kimi K3.1 Pro API tier?

No. The API needs a $1 minimum top-up. Free chat in the Kimi app is the $0 route, covered in how to use Kimi K3.1 Pro for free. For model background, see what Kimi K3.1 Pro is.

Top comments (0)