BYOK 管理 API
查询供应商,并创建、查看和编辑企业 BYOK 配置。
BYOK管理 API
接口参考待联调:当前控制台通过 keys 列表提交多把密钥,并使用 model_mappings、byok_provider_model_ids 等字段;下文旧例的单密钥 schema/config 结构不能直接套用。 以下是待核对的接口资料,不作为可直接接入的正式示例。控制台操作请按对应使用指南完成。
概述
BYOK(Bring Your Own Key)管理API用于管理用户自带的API密钥,支持添加、查看和编辑各种AI服务提供商的密钥配置。这允许企业使用自己的API密钥而不是平台提供的密钥。
基础信息
- Base URL:
YOUR_GATEWAY_MANAGEMENT_BASE_URL - 认证方式: AccessKey/SecretKey签名 或 JWT Token
- 请求格式: JSON
- 响应格式: JSON
权限说明
| 操作 | 主账号 | RAM管理员 | RAM成员 |
|---|---|---|---|
| 创建BYOK | ✅ | ✅ | ❌ |
| 查看BYOK列表 | ✅ | ✅ | ❌ |
| 查看用户BYOK | ✅ | ✅ | ❌ |
| 编辑BYOK | ✅ | ✅ | ❌ |
注意: 所有BYOK操作都需要管理员权限(主账号或RAM管理员)。
API接口列表
1. 获取BYOK提供商列表
查询系统支持的BYOK提供商,以及模型列表。
接口信息
- Path:
/byok/list - Method:
GET - 权限: 主账号、RAM管理员
请求参数
无参数
请求示例
GET /byok/list
X-Access-Key-Id: AK_xxx
X-Timestamp: 2024-01-01T12:00:00+00:00
X-Signature: xxx
响应示例
{
"code": 0,
"data": [
{
"ID": 10,
"Name": "百度OpenAI",
"Desc": "百度OpenAI",
"Schema": "{\n \"title\": \"API Token\",\n \"properties\": {\n \"api_key\": {\n \"type\": \"string\",\n \"title\": \"ApiKey\"\n }\n }\n}",
"ChannelTypeID": 40,
"Icon": "",
"BaseUrl": "https://qianfan.baidubce.com/v2",
"TestRouter": "",
"ChannelType": {
"ID": 40,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"name": "Baidu",
"provider_name": "baidu",
"description": "baidu",
"label": "llm",
"base_url": "https://qianfan.baidubce.com/v2",
"channel": null,
"support_models": [
{
"ID": 343,
"CreatedAt": "2025-12-10T15:02:24.726661+08:00",
"UpdatedAt": "2025-12-17T17:01:00.030477+08:00",
"type_id": 4,
"name": "deepseek-v3.2",
"model_info_id": 245,
"description": "",
"price": 0,
"ratio": 1,
"inputprice": 20000,
"outputprice": 30000,
"cached_price": 2000,
"image_price": 0,
"completion_ratio": 1,
"other_price": "0",
"provider_price": 0,
"provider_input_price": 20000,
"provider_output_price": 30000,
"provider_cached_price": 2000,
"provider_image_price": 0,
"provider_other_price": "0",
"provider_rpm": 15000,
"provider_tpm": 1200000,
"tpm_threshold": 99,
"rpm_threshold": 99,
"context": 128000,
"max_output": 64000,
"latency": 20153,
"throughput": 11,
"precision": "fp16",
"auto_route": true,
"currency": "CNY",
"provider_filter": "",
"country_code": "CN",
"manual_priority": -20,
"supported_apis": "/v1/chat/completions,/v1/messages",
"url_path": "",
"other_info": "",
"model_info": {
"ID": 245,
"CreatedAt": "2025-12-02T11:12:23.716222+08:00",
"UpdatedAt": "2025-12-02T11:15:27.214011+08:00",
"company": "DeepSeek",
"company_id": 9,
"company_info": {
"ID": 0,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"icon64": "",
"name": "",
"description": "",
"website": "",
"model_infos": null
},
"model_name": "Deepseek V3.2",
"copy_name": "deepseek/deepseek-v3.2",
"desc": "DeepSeek-V3.2 是一款大型语言模型,...... ",
"offical_site": "https://deepseek.com",
"open_source": "https://deepseek.com",
"licence": "https://deepseek.com",
"model_type_id": 1,
"model_type": {
"ID": 0,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"display_name": "",
"ModelInterfaceCatalog": null,
"status": 0
},
"support_models": null,
"supports_prompt_cache": true,
"priority": 1,
"currency": "CNY",
"original_price": 0,
"original_input_price": 20000,
"original_output_price": 30000,
"original_cached_price": 2000,
"original_image_price": 0,
"original_other_price": "",
"model_use_cases": null,
"input_modalities": null,
"output_modalities": null,
"extend_info": {
"ID": 0,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"model_info_id": 0,
"input_schema": "",
"output_schema": "",
"price_schema": "",
"usage": 0,
"preview_url": "",
"preview_video": ""
}
},
"channel_types": {
"ID": 0,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"name": "",
"provider_name": "",
"description": "",
"label": "",
"base_url": "",
"channel": null,
"support_models": null
}
}
]
}
}
],
"msg": "查询成功"
}
2. 获取用户BYOK列表
查询当前用户配置的所有BYOK。
接口信息
- Path:
/byok/user/list - Method:
GET - 权限: 主账号、RAM管理员
请求参数
无参数
请求示例
GET /byok/user/list
X-Access-Key-Id: AK_xxx
X-Timestamp: 2024-01-01T12:00:00+00:00
X-Signature: xxx
响应示例
{
"code": 0,
"data": [
{
"id": 46,
"byok_provider_name": "Azure",
"schema": "{\"deployments\":[{\"api_key\":\"YOUR_PROVIDER_API_KEY\",\"endpoint_url\":\"YOUR_AZURE_OPENAI_ENDPOINT\",\"model_id\":\"gpt-5\",\"model_slug\":\"openai/gpt-5\"}],\"model_api_name\":[\"openai/gpt-5\"]}",
"model_api_name": [
"openai/gpt-5"
],
"is_enabled": true,
"always_use_this_key": false,
"schema_struct": "{\n \"title\": \"Azure Configuration(Deployments)\",\n \"type\": \"object\",\n \"properties\": {\n \"deployments\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"model_slug\": {\n \"type\": \"string\",\n \"title\": \"Model Slug\"\n },\n \"endpoint_url\": {\n \"type\": \"string\",\n \"title\": \"Endpoint URL\"\n },\n \"api_key\": {\n \"type\": \"string\",\n \"title\": \"API Key\"\n },\n \"model_id\": {\n \"type\": \"string\",\n \"title\": \"Model ID\"\n }\n },\n \"required\": [\n \"model_slug\",\n \"endpoint_url\",\n \"api_key\",\n \"model_id\"\n ]\n },\n \"minItems\": 1\n }\n },\n \"required\": [\n \"deployments\"\n ]\n}",
"model_mapping": [],
"support_model": [
{
"ID": 106,
"CreatedAt": "2025-07-22T10:54:15.445333+08:00",
"UpdatedAt": "2025-11-20T17:18:45.519544+08:00",
"type_id": 28,
"name": "gpt-4.1",
"model_info_id": 74,
"description": "",
"price": 0,
"ratio": 1,
"inputprice": 12500,
"outputprice": 100000,
"cached_price": 1250,
"image_price": 0,
"completion_ratio": 0,
"other_price": "",
"provider_price": 0,
"provider_input_price": 12500,
"provider_output_price": 100000,
"provider_cached_price": 1250,
"provider_image_price": 0,
"provider_other_price": "",
"provider_rpm": 10000,
"provider_tpm": 1000000,
"tpm_threshold": 80,
"rpm_threshold": 80,
"context": 0,
"max_output": 0,
"latency": 1089,
"throughput": 14,
"precision": "",
"auto_route": true,
"currency": "USD",
"provider_filter": "",
"country_code": "CN",
"manual_priority": 0,
"supported_apis": "/v1/chat/completions,/v1/messages",
"model_info": {
"ID": 74,
"CreatedAt": "2025-02-20T15:54:58.348372+08:00",
"UpdatedAt": "2025-06-04T18:23:43.977268+08:00",
"company": "OpenAI",
"company_id": 6,
"company_info": {
"ID": 0,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"icon64": "",
"name": "",
"description": "",
"website": "",
"model_infos": null
},
"model_name": "GPT-5-pro",
"copy_name": "openai/gpt-5-pro",
"desc": "",
"offical_site": "",
"open_source": "",
"licence": "",
"model_type_id": 1,
"model_type": {
"ID": 0,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"display_name": ""
},
"support_models": null,
"supports_prompt_cache": false,
"priority": 5,
"currency": "CNY",
"original_price": 0,
"original_input_price": 50000,
"original_output_price": 90000,
"original_cached_price": 0,
"original_image_price": 0,
"original_other_price": "",
"model_use_cases": null,
"input_modalities": null,
"output_modalities": null,
"extend_info": {
"ID": 0,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"model_info_id": 0,
"input_schema": "",
"output_schema": "",
"price_schema": "",
"usage": 0,
"preview_url": "",
"preview_video": ""
}
},
"channel_types": {
"ID": 0,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"name": "",
"provider_name": "",
"description": "",
"label": "",
"base_url": "",
"channel": null,
"support_models": null
}
}
]
}
],
"msg": "查询成功"
}
3. 创建BYOK配置
添加新的BYOK配置。
接口信息
- Path:
/byok/create - Method:
POST - 权限: 主账号、RAM管理员
请求参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| byok_provider_id | int | 是 | 提供商ID | 1 |
| channel_type_id | int | 是 | 渠道id | 21 |
| schema | string | 是 | byok结构信息 | 见下方示例 |
| model_mappings | object | 是 | 模型别名映射 | 见下方示例 |
| is_enabled | bool | 是 | 是否启用 | true |
| always_use_this_key | bool | 是 | 是否总是使用这个key | 见下方示例 |
| support_model_id | array | 是 | 支持的模型 ID 列表 | [12] |
config对象: 根据不同提供商包含不同字段,参考"获取BYOK提供商列表"返回的config_fields。
请求示例
OpenAI配置示例:
POST /byok/create
Content-Type: application/json
X-Access-Key-Id: AK_xxx
X-Timestamp: 2024-01-01T12:00:00+00:00
X-Signature: xxx
{
"always_use_this_key": true,
"byok_provider_id": 0,
"channel_type_id": 0,
"is_enabled": true,
"model_mappings": [
{
"custom_name": "string",
"support_model_name": "string"
}
],
"schema": "string",
"support_model_id": [
0
]
}
响应示例
{
"data": {},
"msg": "新建Byok成功"
}
4. 编辑BYOK配置
更新已有的BYOK配置。 如果没有schema的变更,那么不需要传入schema
接口信息
- Path:
/byok/edit - Method:
POST - 权限: 主账号、RAM管理员
请求参数
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| id | integer | 是 | BYOK配置ID | 1 |
| name | string | 否 | 新的配置名称 | 更新后的名称 |
| config | object | 否 | 新的配置信息 | 见下方示例 |
| status | integer | 否 | 状态:1启用,2禁用 | 1 |
请求示例
POST /byok/edit
Content-Type: application/json
X-Access-Key-Id: AK_xxx
X-Timestamp: 2024-01-01T12:00:00+00:00
X-Signature: xxx
{
"always_use_this_key": true,
"byok_id": 0,
"is_enabled": true,
"model_mappings": [
{
"custom_name": "string",
"support_model_name": "string"
}
],
"schema": "string"
}
响应示例
{
"data": {},
"msg": "更新成功"
}
5 获取模型列表方法
完整调用示例
Python完整示例
import requests
import hashlib
import hmac
import base64
import json
from datetime import datetime, timezone
from urllib.parse import urlencode
class BYOKAPI:
def __init__(self, base_url, access_key_id, secret_key):
self.base_url = base_url
self.access_key_id = access_key_id
self.secret_key = secret_key
def _sign(self, method, uri, body):
body_bytes = json.dumps(body, separators=(',', ':')).encode('utf-8') if body is not None else b''
body_hash = base64.b64encode(
hashlib.sha256(body_bytes).digest()
).decode()
timestamp = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%S+00:00')
string_to_sign = f"{method}\n{uri}\n{timestamp}\n{body_hash}"
signature = base64.b64encode(
hmac.new(
self.secret_key.encode(),
string_to_sign.encode(),
hashlib.sha256
).digest()
).decode()
return timestamp, signature
def _request(self, method, path, body=None, params=None):
uri = path
if params:
uri = f"{path}?{urlencode(params)}"
timestamp, signature = self._sign(method, uri, body)
resp = requests.request(
method,
f"{self.base_url}{uri}",
data=json.dumps(body, separators=(',', ':')).encode('utf-8') if body is not None else None,
timeout=30,
headers={
"Content-Type": "application/json",
"X-Access-Key-Id": self.access_key_id,
"X-Timestamp": timestamp,
"X-Signature": signature
}
)
resp.raise_for_status()
return resp.json()
# -------- APIs --------
def list_providers(self):
return self._request("GET", "/byok/list")
def list_user_byoks(self):
return self._request("GET", "/byok/user/list")
def create_byok(self, *, byok_provider_id, channel_type_id,
schema_dict, support_model_id,
model_mappings=None,
is_enabled=True,
always_use_this_key=False):
body = {
"byok_provider_id": byok_provider_id,
"channel_type_id": channel_type_id,
"schema": json.dumps(schema_dict, ensure_ascii=False),
"support_model_id": support_model_id,
"model_mappings": model_mappings or [],
"is_enabled": is_enabled,
"always_use_this_key": always_use_this_key
}
return self._request("POST", "/byok/create", body)
def edit_byok(self, *, byok_id,
schema_dict=None,
model_mappings=None,
is_enabled=None,
always_use_this_key=None):
body = {
"byok_id": byok_id
}
if schema_dict is not None:
body["schema"] = json.dumps(schema_dict, ensure_ascii=False)
if model_mappings is not None:
body["model_mappings"] = model_mappings
if is_enabled is not None:
body["is_enabled"] = is_enabled
if always_use_this_key is not None:
body["always_use_this_key"] = always_use_this_key
return self._request("POST", "/byok/edit", body)
Node.js完整示例
使用 Node.js 18 或以上版本,先执行 npm install axios,将代码保存为 .cjs 文件。替换为获准的测试环境和凭证;底部示例包含写入操作,接口契约仍需按页首说明核准。
const crypto = require('crypto');
const axios = require('axios');
class BYOKAPI {
constructor(baseUrl, accessKeyId, secretKey) {
this.baseUrl = baseUrl;
this.accessKeyId = accessKeyId;
this.secretKey = secretKey;
}
calculateSignature(method, uri, body) {
const bodyBytes = body ? JSON.stringify(body) : '';
const bodyHash = crypto.createHash('sha256')
.update(bodyBytes)
.digest('base64');
const timestamp = new Date().toISOString().replace(/\.\d{3}Z$/, '+00:00');
const stringToSign = `${method}\n${uri}\n${timestamp}\n${bodyHash}`;
const signature = crypto.createHmac('sha256', this.secretKey)
.update(stringToSign)
.digest('base64');
return { timestamp, signature };
}
async request(method, uri, body = null, params = null) {
let fullUri = uri;
if (params) {
const queryString = new URLSearchParams(params).toString();
fullUri = `${uri}?${queryString}`;
}
const { timestamp, signature } = this.calculateSignature(method, fullUri, body);
const config = {
method,
url: `${this.baseUrl}${fullUri}`,
headers: {
'Content-Type': 'application/json',
'X-Access-Key-Id': this.accessKeyId,
'X-Timestamp': timestamp,
'X-Signature': signature
}
};
if (body && method === 'POST') {
config.data = body;
}
const response = await axios(config);
return response.data;
}
async listProviders() {
return this.request('GET', '/byok/list');
}
async listUserBYOKs() {
return this.request('GET', '/byok/user/list');
}
async createBYOK(provider, name, config) {
return this.request('POST', '/byok/create', {
provider,
name,
config
});
}
async editBYOK(byokId, updates) {
return this.request('POST', '/byok/edit', {
id: byokId,
...updates
});
}
}
// 使用示例
(async () => {
const api = new BYOKAPI(
'http://your-domain.com',
'AK_xxx',
'SK_xxx'
);
try {
// 1. 获取提供商列表
const providers = await api.listProviders();
console.log('提供商列表:', providers);
// 2. 创建BYOK
const byok = await api.createBYOK('openai', '生产OpenAI', {
api_key: 'sk-proj-xxxxx',
organization: 'org-xxxxx'
});
console.log('创建BYOK:', byok);
// 3. 获取用户BYOK列表
const userBYOKs = await api.listUserBYOKs();
console.log('用户BYOK:', userBYOKs);
// 4. 更新BYOK
const updated = await api.editBYOK(byok.data.id, {
name: '更新后的配置',
status: 1
});
console.log('更新BYOK:', updated);
} catch (error) {
console.error('API调用失败:', error.response?.data || error.message);
}
})();
使用场景
场景1: 多环境密钥管理
为不同环境配置不同的BYOK:
# 生产环境
production_byok = api.create_byok(
provider="openai",
name="生产环境-OpenAI",
config={
"api_key": "YOUR_PROVIDER_API_KEY",
"organization": "org-production"
}
)
# 测试环境
testing_byok = api.create_byok(
provider="openai",
name="测试环境-OpenAI",
config={
"api_key": "sk-proj-testing-xxxxx",
"organization": "org-testing"
}
)
# 开发环境
dev_byok = api.create_byok(
provider="openai",
name="开发环境-OpenAI",
config={
"api_key": "sk-proj-dev-xxxxx",
"organization": "org-dev"
}
)
场景2: 密钥轮换
定期轮换API密钥以提高安全性:
# 更新密钥
api.edit_byok(
byok_id=1,
config={
"api_key": "YOUR_PROVIDER_API_KEY",
"organization": "org-xxxxx"
}
)
场景3: 多提供商配置
配置多个AI服务提供商:
# OpenAI
openai_byok = api.create_byok(
provider="openai",
name="OpenAI GPT",
config={"api_key": "sk-proj-xxxxx"}
)
# Anthropic Claude
anthropic_byok = api.create_byok(
provider="anthropic",
name="Anthropic Claude",
config={"api_key": "sk-ant-xxxxx"}
)
# Azure OpenAI
azure_byok = api.create_byok(
provider="azure",
name="Azure OpenAI",
config={
"api_key": "azure-key",
"endpoint": "YOUR_AZURE_OPENAI_ENDPOINT",
"api_version": "2024-02-15-preview"
}
)
场景4: 临时禁用BYOK
在密钥泄露或需要维护时临时禁用:
# 禁用BYOK
api.edit_byok(byok_id=1, status=2)
# 恢复启用
api.edit_byok(byok_id=1, status=1)
错误码说明
| 错误码 | 说明 | 解决方法 |
|---|---|---|
| 400 | 参数错误或配置格式不正确 | 检查请求参数和config格式 |
| 401 | 未认证 | 检查AccessKey和签名 |
| 403 | 权限不足(非管理员) | 需要主账号或RAM管理员权限 |
| 404 | BYOK配置不存在 | 检查BYOK ID |
| 422 | API密钥验证失败 | 检查提供的API密钥是否有效 |
| 500 | 服务器错误 | 联系技术支持 |
安全建议
- 密钥加密存储: 系统会加密存储所有API密钥
- 密钥脱敏显示: 列表查询时API密钥会被脱敏显示(如
sk-****) - 定期轮换: 建议定期更换API密钥
- 最小权限原则: 为不同环境使用不同的API密钥,限制权限范围
- 监控使用情况: 通过
last_used_at字段监控密钥使用情况 - 及时禁用: 发现密钥泄露时立即禁用
注意事项
- 管理员权限: 所有BYOK操作都需要管理员权限(主账号或RAM管理员)
- 配置验证: 创建BYOK时系统会验证API密钥的有效性
- 提供商支持: 不同提供商支持的模型和配置字段不同,参考
/byok/list返回的信息 - 密钥格式: 确保API密钥格式正确,包含必要的前缀(如OpenAI的
sk-proj-)
相关文档
示例运行范围
完整客户端示例需要 Python 3 与 requests;JavaScript 客户端需要 Node.js 与 axios。后续业务片段复用前文创建的客户端实例,不是独立脚本。执行创建、修改或删除前,仅使用获准的测试环境及测试数据。这里的本地语法检查不代表接口联调通过。