Skip to main content
POST
/
v1
/
chat
/
completions
Create Chat Completion
curl --request POST \
  --url https://api.moonshot.ai/v1/chat/completions \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "messages": [
    {
      "role": "user",
      "content": "Hello",
      "name": null,
      "partial": false
    }
  ],
  "model": "kimi-k2.7-code"
}
'
import requests

url = "https://api.moonshot.ai/v1/chat/completions"

payload = {
"messages": [
{
"role": "user",
"content": "Hello",
"name": None,
"partial": False
}
],
"model": "kimi-k2.7-code"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
messages: [{role: 'user', content: 'Hello', name: null, partial: false}],
model: 'kimi-k2.7-code'
})
};

fetch('https://api.moonshot.ai/v1/chat/completions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.moonshot.ai/v1/chat/completions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'messages' => [
[
'role' => 'user',
'content' => 'Hello',
'name' => null,
'partial' => false
]
],
'model' => 'kimi-k2.7-code'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://api.moonshot.ai/v1/chat/completions"

payload := strings.NewReader("{\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hello\",\n \"name\": null,\n \"partial\": false\n }\n ],\n \"model\": \"kimi-k2.7-code\"\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.moonshot.ai/v1/chat/completions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hello\",\n \"name\": null,\n \"partial\": false\n }\n ],\n \"model\": \"kimi-k2.7-code\"\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.moonshot.ai/v1/chat/completions")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Hello\",\n \"name\": null,\n \"partial\": false\n }\n ],\n \"model\": \"kimi-k2.7-code\"\n}"

response = http.request(request)
puts response.read_body
{
  "id": "<string>",
  "object": "chat.completion",
  "created": 123,
  "model": "<string>",
  "choices": [
    {
      "index": 123,
      "message": {
        "role": "assistant",
        "content": "<string>",
        "tool_calls": [
          {
            "id": "<string>",
            "type": "function",
            "function": {
              "name": "<string>",
              "arguments": "<string>"
            }
          }
        ],
        "reasoning_content": "<string>"
      }
    }
  ],
  "usage": {
    "prompt_tokens": 123,
    "completion_tokens": 123,
    "total_tokens": 123,
    "cached_tokens": 123
  }
}
{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}
{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}
{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}
Create a chat completion request. The model generates a response based on the provided message list.
The content field supports the following two forms:Plain text string
"content": "Hello"
Array of objects (for multimodal input)Each element in the array is distinguished by the type field:
"content": [
    { "type": "text", "text": "Describe this image" },
    { "type": "image_url", "image_url": { "url": "data:image/png;base64,..." } },
    { "type": "video_url", "video_url": { "url": "data:video/mp4;base64,..." } }
]
image_url and video_url also support passing a string directly, equivalent to the url field in object form:
{ "type": "image_url", "image_url": "data:image/png;base64,..." }

Parameter Description

Each element in the array has the following fields:
ParameterRequiredDescriptionType
typerequiredContent type"text" | "image_url" | "video_url"
textrequired when type=textText contentstring
image_urlrequired when type=image_urlFor transmitting images. Supports object form {"url": "..."} or a URL string directlyobject | string
video_urlrequired when type=video_urlFor transmitting videos. Supports object form {"url": "..."} or a URL string directlyobject | string
When image_url is passed as an object, its fields are:
ParameterRequiredDescriptionType
urlrequiredImage content specified via base64 encoding or file idstring
When video_url is passed as an object, its fields are:
ParameterRequiredDescriptionType
urlrequiredVideo content specified via base64 encoding or file id, for example data:video/mp4;base64,...string
Both the object form (url field) and the string shorthand support the following formats:
  • Base64 encoding: data:image/png;base64,... or data:video/mp4;base64,...
  • File reference: ms://<file_id>
See Use the Kimi Vision Model.

Usage Example

import os
import base64

from openai import OpenAI
from openai.types.chat import ChatCompletion

client: OpenAI = OpenAI(
    api_key=os.environ.get("MOONSHOT_API_KEY"),
    base_url="https://api.moonshot.ai/v1",
)

# Encode the image to base64
with open("your_image_path", "rb") as f:
    img_base: str = base64.b64encode(f.read()).decode("utf-8")

response: ChatCompletion = client.chat.completions.create(
    model="kimi-k2.6",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": f"data:image/jpeg;base64,{img_base}",
                    },
                },
                {
                    "type": "text",
                    "text": "Describe this image",
                },
            ],
        }
    ],
)
print(response.choices[0].message.content)
curl https://api.moonshot.ai/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $MOONSHOT_API_KEY" \
    -d '{
        "model": "kimi-k2.6",
        "messages": [
            {
                "role": "user",
                "content": [
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": "data:image/jpeg;base64,/9j/4AAQ..."
                        }
                    },
                    {
                        "type": "text",
                        "text": "Describe this image"
                    }
                ]
            }
        ]
    }'
const fs = require("fs");
const OpenAI = require("openai");

const client = new OpenAI({
    apiKey: process.env.MOONSHOT_API_KEY,
    baseURL: "https://api.moonshot.ai/v1",
});

async function main() {
    // Encode the image to base64
    const imgBase = fs.readFileSync("your_image_path").toString("base64");

    const response = await client.chat.completions.create({
        model: "kimi-k2.6",
        messages: [
            {
                role: "user",
                content: [
                    {
                        type: "image_url",
                        image_url: {
                            url: `data:image/jpeg;base64,${imgBase}`,
                        },
                    },
                    {
                        type: "text",
                        text: "Describe this image",
                    },
                ],
            },
        ],
    });
    console.log(response.choices[0].message.content);
}

main();

Non-streaming Response

{
    "id": "cmpl-04ea926191a14749b7f2c7a48a68abc6",
    "object": "chat.completion",
    "created": 1698999496,
    "model": "kimi-k2.6",
    "choices": [
        {
            "index": 0,
            "message": {
                "role": "assistant",
                "content": "Hello, Li Lei! 1+1 equals 2. If you have any other questions, feel free to ask!"
            },
            "finish_reason": "stop"
        }
    ],
    "usage": {
        "prompt_tokens": 19,
        "completion_tokens": 21,
        "total_tokens": 40,
        "cached_tokens": 10
    }
}

Streaming Response

data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}

data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}

...

data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":19,"completion_tokens":13,"total_tokens":32,"cached_tokens":12}}

data: [DONE]
The model name in the response example will be returned based on the model parameter in the request. When using the kimi-k2.6 model, the "model" field in the response will show "kimi-k2.6".
The Kimi API is stateless and does not retain conversation history. To implement multi-turn dialogue, append the previous assistant reply (and any tool results, if applicable) back into the messages array before sending the next request.
messages = [
    {"role": "system", "content": "You are Kimi."},
    {"role": "user", "content": "Hello, my name is Li Lei."}
]

completion = client.chat.completions.create(model="kimi-k2.6", messages=messages)
reply = completion.choices[0].message

# Append the assistant reply back into messages for the next turn
messages.append({"role": "assistant", "content": reply.content})
messages.append({"role": "user", "content": "What is 1+1?"})
When the conversation history grows too long, retain only the most recent messages or compress earlier turns to avoid exceeding the model’s context limit.
Use the response_format parameter to constrain the model output format:
  • {"type": "text"} (default): plain text output
  • {"type": "json_object"}: forces a valid JSON Object output
  • {"type": "json_schema", "json_schema": {...}}: outputs structured data according to the given JSON Schema (Structured Output)
When using json_object, you must explicitly describe the expected JSON fields and types in the system prompt or user prompt, otherwise the model may produce unexpected results.
{
  "model": "kimi-k2.6",
  "messages": [
    {"role": "system", "content": "Please output JSON containing title, author, and summary fields."},
    {"role": "user", "content": "Summarize this article..."}
  ],
  "response_format": {"type": "json_object"}
}
Pass external tools defined as JSON Schema via the tools parameter. The model can decide to invoke them when appropriate.Request example
{
  "model": "kimi-k2.6",
  "messages": [{"role": "user", "content": "What is the weather in Beijing today?"}],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get the weather for a given city",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {"type": "string", "description": "City name"}
          },
          "required": ["city"]
        }
      }
    }
  ]
}
tool_calls in the responseWhen finish_reason is "tool_calls", the model returns a tool_calls array containing id, function.name, and function.arguments:
{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "",
      "tool_calls": [{
        "id": "call_xxx",
        "type": "function",
        "function": {
          "name": "get_weather",
          "arguments": "{\"city\":\"Beijing\"}"
        }
      }]
    },
    "finish_reason": "tool_calls"
  }]
}
Submitting tool execution resultsAfter executing the tool locally, append the result back into messages using role="tool". The tool_call_id must match the id from the request:
{"role": "tool", "tool_call_id": "call_xxx", "content": "Sunny, 25°C"}
kimi-k2.6 and kimi-k2.7-code support thinking mode: the model first outputs its reasoning process (reasoning_content) before producing the final answer.Request parameters
FieldTypeDescription
thinking.type"enabled" | "disabled"Thinking switch (kimi-k2.7-code is always enabled and cannot be disabled)
thinking.keepnull | "all"Preserved Thinking: whether to retain historical reasoning_content in context (only supported by kimi-k2.6)
Response fieldsIn non-streaming responses, choices[0].message contains:
FieldDescription
contentFinal answer
reasoning_contentReasoning process (returned only when thinking mode is enabled)
{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "1+1 equals 2.",
      "reasoning_content": "The user asked a basic math question, simply add the numbers."
    }
  }]
}
When using a thinking model in multi-turn conversations, always preserve the reasoning_content of each historical assistant message in messages, otherwise the model may lose reasoning context.
Set stream: true to enable streaming output. The model returns content incrementally in Server-Sent Events (SSE) format. Recommended for scenarios requiring real-time feedback, such as chat, code generation, and long text output.
completion = client.chat.completions.create(
    model="kimi-k2.6",
    messages=[{"role": "user", "content": "Explain what recursion is."}],
    stream=True
)

for chunk in completion:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
SSE Response FormatEach line starts with data:, followed by a JSON object. When finish_reason is null, content accumulates in delta.content; when finish_reason is not null, the output is complete:
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}

data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"content":"Hello"},"finish_reason":null}]}

data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":19,"completion_tokens":13,"total_tokens":32,"cached_tokens":12}}

data: [DONE]
stream_optionsUse stream_options: {"include_usage": true} to receive an additional usage field in the last chunk (before data: [DONE]), showing the token consumption of the request:
stream=True,
stream_options={"include_usage": True}
Partial Mode (Prefill) allows you to prefill an output prefix in the last assistant message of messages, guiding the model to continue generation in the format or direction you expect.How to EnableAppend an role="assistant" message at the end of the messages array, and set partial: true:
completion = client.chat.completions.create(
    model="kimi-k2.6",
    messages=[
        {"role": "user", "content": "Implement quicksort in Python."},
        {"role": "assistant", "content": "```python\n", "partial": True}
    ]
)
The model will continue generating code from ````python\n` instead of outputting explanatory text first.Common Use Cases
  • Force the model to start with a specific format (e.g., JSON’s {, a code block’s ````python`)
  • Maintain role name prefixes in role-play scenarios (combined with the name field)
  • When finish_reason="length", use the same prefix to continue truncated content
Do not mix Partial Mode with response_format={"type": "json_object"}, as this may lead to unexpected model responses. To guide JSON output, use Structured Output directly, or set partial: true and prefill { separately.

Authorizations

Authorization
string
header
required

The Authorization header expects a Bearer token. Use an MOONSHOT_API_KEY as the token. This is a server-side secret key. Generate one on the API keys page in your dashboard.

Body

application/json
messages
object[]
required

A list of messages in the conversation so far. Each element has the format {"role": "user", "content": "Hello"}. role supports system, user, assistant, or tool. content must not be empty. The content field can be a string or an array[object] (for multimodal input).

model
enum<string>
default:kimi-k2.7-code
required

Model ID. Either kimi-k2.7-code or its high-speed variant kimi-k2.7-code-highspeed; the two are the same model with identical parameters, while the high-speed variant outputs at approximately 180 Tokens/s (up to 260 Tokens/s in short-context scenarios).

Available options:
kimi-k2.7-code,
kimi-k2.7-code-highspeed
max_tokens
integer
deprecated

Deprecated, please refer to max_completion_tokens

max_completion_tokens
integer

The maximum number of tokens to generate for the chat completion. If not specified, defaults to a reasonable integer such as 1024. If the result reaches the maximum number of tokens without ending, the finish reason will be "length"; otherwise, it will be "stop". This refers to the length of tokens you expect us to return, not the total length of input plus output. If input plus max_completion_tokens exceeds the model context window, the API returns invalid_request_error.

response_format
object

Controls the model output format. Default is {"type": "text"} for plain text output. Set to {"type": "json_object"} to enable JSON mode, ensuring output is a valid JSON object (you must guide the model to output JSON in the prompt). Set to {"type": "json_schema"} to enable Structured Output, constraining output to match a specified JSON Schema (recommended, requires the json_schema field). If you encounter schema validation issues, please submit feedback at walle GitHub Issues (https://github.com/MoonshotAI/walle/issues).

stop

Stop words, which will halt the output when a full match is found. The matched words themselves will not be output. A maximum of 5 strings is allowed, and each string must not exceed 32 bytes

stream
boolean
default:false

Whether to return the response in a streaming fashion. Default is false.

stream_options
object

Options for streaming responses

tools
object[]

A list of tools the model may call

Maximum array length: 128
prompt_cache_key
string

Used to cache responses for similar requests to optimize cache hit rates. For Coding Agents, this is typically a session id or task id representing a single session; if the session is exited and later resumed, this value should remain the same. For Kimi Code Plan, this field is required to improve cache hit rates. For other agents involving multi-turn conversations, it is also recommended to implement this field

safety_identifier
string

A stable identifier used to help detect users of your application that may be violating usage policies. The ID should be a string that uniquely identifies each user. It is recommended to hash the username or email address to avoid sending any identifying information

tool_choice

Controls whether the model calls tools. auto (default): the model decides whether to call tools; none: no tool calls; required: force a tool call; or pass an object specifying a particular function to force that tool call.

Available options:
auto,
none,
required
thinking
object

Controls thinking for the kimi-k2.7-code model, and whether to fully preserve reasoning_content across multi-turn conversations. Optional parameter. Default value is {"type": "enabled", "keep": "all"}.

Differences from kimi-k2.6:

  • type only accepts "enabled". Unlike kimi-k2.6, "disabled" is NOT supported — passing it returns an error. Thinking is always on for this model.
  • keep only accepts the valid value "all"; omitting it or passing "all" is treated as "all" on the server, while any other invalid value returns an error. Preserved Thinking is therefore always enabled for this model.

Response

Chat completion response

id
string

Unique identifier for the completion

object
string

Object type

Example:

"chat.completion"

created
integer

Unix timestamp of when the completion was created

model
string

Model used for the completion

choices
object[]

List of completion choices

usage
object