认证
每个请求都在请求头中携带你的 API 密钥。每个账户一个密钥,适用于所有端点和所有模型,请求头有两种形式可选。
请求头 · OpenAI SDK
Authorization: Bearer YOUR_API_KEY 请求头 · Anthropic SDK
x-api-key: YOUR_API_KEY 接受的请求头
在每个 /v1 端点上,两种请求头都会被读取,无论该端点使用哪种格式。发送其中一种即可。
| 请求头 | 说明 |
|---|---|
Authorization: Bearer <key> | 最先检查。Bearer 的 B 要大写,密钥前加一个空格。OpenAI SDK 发送此请求头。 |
x-api-key: <key> | 当请求没有 Authorization: Bearer 请求头时读取。Anthropic SDK 发送此请求头。 |
使用 OpenAI SDK 时,设置密钥和 base URL;SDK 会发送 Authorization: Bearer。
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com/v1"
)
response = client.chat.completions.create(
model="shannon-3",
messages=[
{"role": "user", "content": "Hello, Shannon!"}
]
)
print(response.choices[0].message.content) import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'YOUR_API_KEY',
baseURL: 'https://api.shannon-ai.com/v1'
});
const response = await client.chat.completions.create({
model: 'shannon-3',
messages: [
{ role: 'user', content: 'Hello, Shannon!' }
]
});
console.log(response.choices[0].message.content); curl -X POST "https://api.shannon-ai.com/v1/chat/completions" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "shannon-3",
"messages": [
{"role": "user", "content": "Hello, Shannon!"}
]
}' 使用 Anthropic SDK 时,设置密钥和不带 /v1 的 base URL;SDK 会发送 x-api-key。
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com"
)
message = client.messages.create(
model="shannon-3",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello, Shannon!"}
]
)
print("".join(block.text for block in message.content if block.type == "text")) import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: 'YOUR_API_KEY',
baseURL: 'https://api.shannon-ai.com'
});
const message = await client.messages.create({
model: 'shannon-3',
max_tokens: 1024,
messages: [
{ role: 'user', content: 'Hello, Shannon!' }
]
});
console.log(message.content.filter((block) => block.type === 'text').map((block) => block.text).join('')); curl -X POST "https://api.shannon-ai.com/v1/messages" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "shannon-3",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello, Shannon!"}
]
}' 哪些端点需要密钥
| 端点 | 密钥 |
|---|---|
POST /v1/chat/completions | 必需 |
POST /v1/messages | 必需 |
POST /v1/responses | 必需 |
POST /v1/tokenize | 必需 |
POST /v1/messages/count_tokens | 必需 |
GET /v1/models | 无需 |
你的密钥
- 密钥是
sk-后接 43 个字符,字符取自A–Z、a–z、0–9、-和_:共 46 个字符。 - 每个账户恰好有一个密钥。首次打开密钥与用量页面时创建。
- 该密钥拥有你账户的完整 API 访问权限:所有端点、所有模型和全部余额。
- 密钥没有到期日期。在你轮换或撤销它之前一直有效。
轮换与撤销
你在密钥与用量页面上轮换和撤销密钥。 密钥与用量
| 操作 | 结果 |
|---|---|
| 轮换 | 签发新密钥,旧密钥失效。新密钥立即可用。 |
| 撤销 | 密钥失效,且不会签发新密钥。请轮换以重新获得可用的密钥。 |
- 两者都立即生效:下一个使用旧密钥的请求会得到
401。请把 60 秒视为旧密钥在所有位置都被拒绝之前的上限。 - 账户的所有客户端使用同一个密钥,因此轮换会影响全部客户端。轮换后请立即把新密钥放入你的客户端。
- 余额、用量和限流保护属于账户,而不属于密钥。新密钥沿用相同的余额,以及当前这一分钟的相同请求计数。
错误
每个认证失败的状态码都是 401,类型为 authentication_error。可通过消息区分具体情况。
| 状态码 | 类型 | 消息 | 时机 |
|---|---|---|---|
401 | authentication_error | Missing authentication | 请求既没有 Authorization: Bearer 请求头,也没有以 sk- 开头的 x-api-key 请求头。小写的 bearer,以及不带 Bearer 的 Authorization 值,也会得到此回复。 |
401 | authentication_error | Invalid API key | 该密钥不是任何账户的当前密钥:可能输错了、已被撤销,或已被轮换替换。 |
{
"error": {
"type": "authentication_error",
"message": "Invalid API key",
"code": "invalid_api_key",
"param": null
}
} {
"type": "error",
"error": {
"type": "authentication_error",
"message": "Invalid API key"
}
} - 在除
/v1/messages之外的所有路径上,error对象还包含code: "invalid_api_key"(缺少密钥时同样如此)以及param: null。 - 密钥会在读取请求体之前检查。没有有效密钥的请求,即使请求体无效或过大,也会得到
401。 - 不以
sk-开头的Authorization: Bearer值不会被视为 API 密钥。它会得到401,消息表明令牌无效或已过期。
浏览器与 CORS
- API 只对固定列表中的来源响应跨源浏览器请求。来自其他源的页面上的 JavaScript 无法读取
/v1的回复。 - 请从你的服务器调用 API,让页面与你的服务器通信。这样也能让密钥不出现在页面源码中。
- 服务端代码和命令行工具不受影响:此规则仅由浏览器执行。
- 在 shannon-ai.com 上登录并不能认证
/v1请求。那里不会读取 cookie;密钥是唯一的凭证。 - 对于允许的来源,浏览器可以发送
content-type、authorization、x-api-key、anthropic-version、anthropic-beta、openai-beta和x-request-id,并可以读取回复头x-request-id。
保管好密钥
- 请把密钥保存在服务器上。不要放进网页、移动应用或公开仓库:任何持有它的人都可以花光你的全部余额。
- 从环境变量或密钥存储中加载密钥,而不要写进代码里。
- 如果密钥可能已泄露,请在密钥与用量中轮换它。旧密钥会立即失效。
- 泄露之后,请查看密钥与用量中的请求列表。它显示该密钥在过去 30 天内发出的每个请求。