校验请求签名
curl --request POST \
--url https://api.moonshot.cn/v1/signatures/verify \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"nonce": "7d929748-0ae6-41c2-ab5d-a186498ad721",
"timestamp": 1786338000123,
"model": "kimi-k2.7-code",
"signature": "reqsigv1_<opaque-token>"
}
'import requests
url = "https://api.moonshot.cn/v1/signatures/verify"
payload = {
"nonce": "7d929748-0ae6-41c2-ab5d-a186498ad721",
"timestamp": 1786338000123,
"model": "kimi-k2.7-code",
"signature": "reqsigv1_<opaque-token>"
}
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({
nonce: '7d929748-0ae6-41c2-ab5d-a186498ad721',
timestamp: 1786338000123,
model: 'kimi-k2.7-code',
signature: 'reqsigv1_<opaque-token>'
})
};
fetch('https://api.moonshot.cn/v1/signatures/verify', 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.cn/v1/signatures/verify",
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([
'nonce' => '7d929748-0ae6-41c2-ab5d-a186498ad721',
'timestamp' => 1786338000123,
'model' => 'kimi-k2.7-code',
'signature' => 'reqsigv1_<opaque-token>'
]),
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.cn/v1/signatures/verify"
payload := strings.NewReader("{\n \"nonce\": \"7d929748-0ae6-41c2-ab5d-a186498ad721\",\n \"timestamp\": 1786338000123,\n \"model\": \"kimi-k2.7-code\",\n \"signature\": \"reqsigv1_<opaque-token>\"\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.cn/v1/signatures/verify")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"nonce\": \"7d929748-0ae6-41c2-ab5d-a186498ad721\",\n \"timestamp\": 1786338000123,\n \"model\": \"kimi-k2.7-code\",\n \"signature\": \"reqsigv1_<opaque-token>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.moonshot.cn/v1/signatures/verify")
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 \"nonce\": \"7d929748-0ae6-41c2-ab5d-a186498ad721\",\n \"timestamp\": 1786338000123,\n \"model\": \"kimi-k2.7-code\",\n \"signature\": \"reqsigv1_<opaque-token>\"\n}"
response = http.request(request)
puts response.read_body{
"valid": true
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}校验请求签名
校验 Kimi API 返回的请求签名,证明请求确实由 Kimi API 处理且请求的是指定模型,而非被转发到其他服务。
POST
/
v1
/
signatures
/
verify
校验请求签名
curl --request POST \
--url https://api.moonshot.cn/v1/signatures/verify \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"nonce": "7d929748-0ae6-41c2-ab5d-a186498ad721",
"timestamp": 1786338000123,
"model": "kimi-k2.7-code",
"signature": "reqsigv1_<opaque-token>"
}
'import requests
url = "https://api.moonshot.cn/v1/signatures/verify"
payload = {
"nonce": "7d929748-0ae6-41c2-ab5d-a186498ad721",
"timestamp": 1786338000123,
"model": "kimi-k2.7-code",
"signature": "reqsigv1_<opaque-token>"
}
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({
nonce: '7d929748-0ae6-41c2-ab5d-a186498ad721',
timestamp: 1786338000123,
model: 'kimi-k2.7-code',
signature: 'reqsigv1_<opaque-token>'
})
};
fetch('https://api.moonshot.cn/v1/signatures/verify', 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.cn/v1/signatures/verify",
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([
'nonce' => '7d929748-0ae6-41c2-ab5d-a186498ad721',
'timestamp' => 1786338000123,
'model' => 'kimi-k2.7-code',
'signature' => 'reqsigv1_<opaque-token>'
]),
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.cn/v1/signatures/verify"
payload := strings.NewReader("{\n \"nonce\": \"7d929748-0ae6-41c2-ab5d-a186498ad721\",\n \"timestamp\": 1786338000123,\n \"model\": \"kimi-k2.7-code\",\n \"signature\": \"reqsigv1_<opaque-token>\"\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.cn/v1/signatures/verify")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"nonce\": \"7d929748-0ae6-41c2-ab5d-a186498ad721\",\n \"timestamp\": 1786338000123,\n \"model\": \"kimi-k2.7-code\",\n \"signature\": \"reqsigv1_<opaque-token>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.moonshot.cn/v1/signatures/verify")
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 \"nonce\": \"7d929748-0ae6-41c2-ab5d-a186498ad721\",\n \"timestamp\": 1786338000123,\n \"model\": \"kimi-k2.7-code\",\n \"signature\": \"reqsigv1_<opaque-token>\"\n}"
response = http.request(request)
puts response.read_body{
"valid": true
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"code": "<string>"
}
}请求签名(Request Signature)用于证明一次请求确实到达了 Kimi API 本身,而不是被中间层转发到了其他服务或替换了模型。持有 nonce、时间戳、模型和签名的任何一方,都可以通过本接口验证 Kimi API 是否在该时间点以指定模型接受了这个请求,例如向用户或第三方证明服务背后调用的是 Kimi 官方 API、核验代理层没有偷换模型,或用于事后审计与争议举证。
调用 Chat Completions、Responses 或 Messages API 时,在请求头
X-Msh-Request-Nonce 中携带一个随机 nonce(推荐使用 UUID v4),响应头中就会返回 Msh-Request-Timestamp(Kimi API 接受该请求时的 Unix 毫秒时间戳)和 Msh-Request-Signature(以 reqsigv1_ 为前缀的签名 token),流式与非流式均支持。之后将 nonce、timestamp、请求中的 model 和 signature 提交到本接口,签名与三者完全一致时返回 valid: true,否则返回 valid: false。
签名只证明 Kimi API 在该时间点接受了这个 nonce 和请求模型,不证明请求最终成功或响应内容完整。服务端不记录 nonce,重放同一组参数仍会返回 valid: true,防重放和有效时间窗口需由调用方自行控制。
调用示例
调用示例
import os
import uuid
import requests
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.cn/v1",
)
nonce: str = str(uuid.uuid4())
model: str = "kimi-k2.7-code"
# 1. 携带 X-Msh-Request-Nonce 调用模型接口,并读取响应头
raw = client.chat.completions.with_raw_response.create(
model=model,
messages=[{"role": "user", "content": "你好"}],
extra_headers={"X-Msh-Request-Nonce": nonce},
)
timestamp: int = int(raw.headers["Msh-Request-Timestamp"])
signature: str = raw.headers["Msh-Request-Signature"]
# 2. 校验签名
verify = requests.post(
"https://api.moonshot.cn/v1/signatures/verify",
headers={
"Authorization": f"Bearer {os.environ['MOONSHOT_API_KEY']}",
"Content-Type": "application/json",
},
json={
"nonce": nonce,
"timestamp": timestamp,
"model": model,
"signature": signature,
},
)
print(verify.json()) # {"valid": true}
NONCE="$(uuidgen)"
MODEL="kimi-k2.7-code"
# 1. 携带 X-Msh-Request-Nonce 调用模型接口,并把响应头保存到文件
curl -sS -D response.headers -o response.json \
https://api.moonshot.cn/v1/chat/completions \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Msh-Request-Nonce: $NONCE" \
-d "{\"model\": \"$MODEL\", \"messages\": [{\"role\": \"user\", \"content\": \"你好\"}]}"
TIMESTAMP="$(awk -F': ' 'tolower($1)=="msh-request-timestamp" {gsub("\\r", "", $2); print $2}' response.headers)"
SIGNATURE="$(awk -F': ' 'tolower($1)=="msh-request-signature" {gsub("\\r", "", $2); print $2}' response.headers)"
# 2. 校验签名
curl -sS https://api.moonshot.cn/v1/signatures/verify \
-H "Authorization: Bearer $MOONSHOT_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"nonce\": \"$NONCE\", \"timestamp\": $TIMESTAMP, \"model\": \"$MODEL\", \"signature\": \"$SIGNATURE\"}"
const { randomUUID } = require("crypto");
const OpenAI = require("openai");
const apiKey = process.env.MOONSHOT_API_KEY;
const client = new OpenAI({
apiKey,
baseURL: "https://api.moonshot.cn/v1",
});
async function main() {
const nonce = randomUUID();
const model = "kimi-k2.7-code";
// 1. 携带 X-Msh-Request-Nonce 调用模型接口,并读取响应头
const { response } = await client.chat.completions
.create(
{ model, messages: [{ role: "user", content: "你好" }] },
{ headers: { "X-Msh-Request-Nonce": nonce } },
)
.withResponse();
const timestamp = Number(response.headers.get("Msh-Request-Timestamp"));
const signature = response.headers.get("Msh-Request-Signature");
// 2. 校验签名
const verify = await fetch("https://api.moonshot.cn/v1/signatures/verify", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ nonce, timestamp, model, signature }),
});
console.log(await verify.json()); // { valid: true }
}
main();
授权
请求体
application/json
调用模型接口时通过 X-Msh-Request-Nonce 请求头发送的 nonce,需与原值完全一致。
Minimum string length:
1示例:
"7d929748-0ae6-41c2-ab5d-a186498ad721"
模型接口响应头 Msh-Request-Timestamp 返回的 Unix 毫秒时间戳。
必填范围:
x >= 1示例:
1786338000123
调用模型接口时请求体中的 model 值,需与原值完全一致。
Minimum string length:
1示例:
"kimi-k2.7-code"
模型接口响应头 Msh-Request-Signature 返回的签名 token。
Minimum string length:
1示例:
"reqsigv1_<opaque-token>"
响应
校验结果
签名是否有效。true 表示该签名由 Kimi API 签发,且与提交的 nonce、timestamp、model 完全匹配;否则为 false。
示例:
true
此页面对您有帮助吗?