用 client_credentials 换取访问令牌
访问令牌的默认有效期为 1 小时。客户端应缓存令牌并在到期前获取新令牌, 无需在每个业务请求前调用本端点。本端点独立限流为 10 requests/min/client_id。
实际授予的 scope 是凭据已授权 scope 与本次请求 scope 的交集。
请求未授权的 scope 时返回 invalid_scope,不会自动缩减权限后继续签发。
POST
/oauth/tokenRequest body
requiredapplication/x-www-form-urlencodedgrant_typestringrequiredclient_idstringrequired前缀 `dr_live_ci_` / `dr_test_ci_`,标识环境与凭据。
client_secretstringrequired前缀 `dr_live_cs_` / `dr_test_cs_`。仅创建时显示一次,服务端只存 hash。
必须保存在服务端密钥管理系统或环境变量中,不得嵌入网页、移动端应用或代码仓库。
scopestring空格分隔。省略时授予该凭据已授权的全部 scope。
Responses
200签发访问令牌。
access_tokenstringrequiredtoken_typestringrequiredexpires_inintegerrequired有效秒数,默认 3600。
scopestringrequired实际授予的 scope,即凭据已授权 scope 与本次请求 scope 的交集。
400`unsupported_grant_type`(只支持 client_credentials)或
`invalid_scope`(请求了该凭据未被授权的 scope)。
errorobjectrequiredShow propertiesHide properties
codestringrequiredmessagestringrequireddetailsErrorDetail[]Show propertiesHide properties
Array of
ErrorDetailfieldstringrequiredreasonstringrequiredrequest_idstringrequired401`invalid_client`(client_id 或 client_secret 不正确)或
`credential_expired`(凭据已过有效期)。不同错误码便于集成方确定处理方式。
errorobjectrequiredShow propertiesHide properties
codestringrequiredmessagestringrequireddetailsErrorDetail[]Show propertiesHide properties
Array of
ErrorDetailfieldstringrequiredreasonstringrequiredrequest_idstringrequired429API 同时采用分钟配额和秒级突发限制,两者使用不同的等待时间:
- `rate_limit_exceeded`:已达到分钟配额,默认值为 20 req/min/key。
`Retry-After` 表示距下一分钟窗口的秒数。
- `burst_limit_exceeded`:已达到 2 req/s/key 的短时请求限制。
`Retry-After` 通常为 1 秒。
秒级突发限制不会提高分钟配额。即使请求速率不超过 2 req/s,
每分钟请求总量仍不得超过对应凭据的分钟配额。
`/oauth/token` 另有独立配额(10 req/min/client_id)。
errorobjectrequiredShow propertiesHide properties
codestringrequiredmessagestringrequireddetailsErrorDetail[]Show propertiesHide properties
Array of
ErrorDetailfieldstringrequiredreasonstringrequiredrequest_idstringrequired503`api_temporarily_unavailable` 表示 API 功能、凭据服务或订单依赖暂时不可用。
可以使用设有次数上限的指数退避策略重试,避免短时间内发送大量重复请求。
errorobjectrequiredShow propertiesHide properties
codestringrequiredmessagestringrequireddetailsErrorDetail[]Show propertiesHide properties
Array of
ErrorDetailfieldstringrequiredreasonstringrequiredrequest_idstringrequiredRequest
curl -X POST "https://api.darkroom.net/v2/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d '{
"grant_type": "client_credentials",
"client_id": "dr_live_ci_8f2a1c9d4b7e",
"client_secret": "dr_live_cs_3e6b0a5f9c21",
"scope": "orders:write orders:read"
}'const response = await fetch("https://api.darkroom.net/v2/oauth/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: JSON.stringify({
"grant_type": "client_credentials",
"client_id": "dr_live_ci_8f2a1c9d4b7e",
"client_secret": "dr_live_cs_3e6b0a5f9c21",
"scope": "orders:write orders:read"
})
});import requests
response = requests.post(
"https://api.darkroom.net/v2/oauth/token",
headers={
"Content-Type": "application/x-www-form-urlencoded"
},
json={
"grant_type": "client_credentials",
"client_id": "dr_live_ci_8f2a1c9d4b7e",
"client_secret": "dr_live_cs_3e6b0a5f9c21",
"scope": "orders:write orders:read"
},
)Response
{
"access_token": "string",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "string"
}{
"error": {
"code": "string",
"message": "string",
"details": [
{
"field": "string",
"reason": "string"
}
]
},
"request_id": "string"
}{
"error": {
"code": "string",
"message": "string",
"details": [
{
"field": "string",
"reason": "string"
}
]
},
"request_id": "string"
}{
"error": {
"code": "string",
"message": "string",
"details": [
{
"field": "string",
"reason": "string"
}
]
},
"request_id": "string"
}{
"error": {
"code": "string",
"message": "string",
"details": [
{
"field": "string",
"reason": "string"
}
]
},
"request_id": "string"
}