套餐管理
套餐用于配置 API Key 可访问的模型网关路由,以及按周期生效的请求数和 Token 数限流。套餐可启用或禁用,禁用后绑定该套餐的 API Key 无法通过套餐访问路由。
rps 和 tps 是历史 API 字段名:rps 表示配置周期内的请求数上限,tps 表示配置周期内的 Token 数上限,二者并非固定按秒计数。rps 范围为 0..2147483647,tps 为非负整数;0 表示不限量。周期单位支持 minute、hour、day、month、year;空或未知单位归一为 minute。
rpsPeriod / tpsPeriod 缺省为 1;各单位最大倍数为 minute=10080、hour=2160、day=1095、month=60、year=5。
套餐共享允许其他项目查看套餐,并将本项目的 API Key 绑定到该套餐。共享项目列表通过 PUT shares 整体替换;如果被移除的项目仍有 API Key 绑定该套餐,请求返回 409。所有 shares / share-targets 操作都要求 plan_share/global/manage 权限。sharedProjectIds 仅向拥有套餐全局读权限的调用方返回。
套餐仍被 API Key 绑定时不能删除,需先解除绑定。
| 方法 | 路径(产品接口统一前缀 /api/v1) | 功能 |
|---|---|---|
| GET | /plans | 查询套餐 |
| POST | /plans | 创建套餐 |
| GET | /plans/{id} | 获取套餐详情 |
| PATCH | /plans/{id} | 更新套餐 |
| DELETE | /plans/{id} | 删除套餐 |
| GET | /plans/{id}/shares | 查询套餐共享项目 |
| PUT | /plans/{id}/shares | 替换套餐共享项目 |
| GET | /plans/{id}/share-targets | 查询套餐可共享项目 |
查询套餐
功能介绍
查询当前调用方可见的套餐,包括本项目套餐和共享给本项目的套餐。
访问要求:有效 Token 和套餐读权限。普通调用方可查看本项目套餐;具有共享读权限时还可查看共享给本项目的套餐;具有全局读权限时可查看全部项目的套餐。
URI
GET /api/v1/plans
查询参数
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| page | integer | 否 | 页码,从 1 开始 |
| page_size | integer | 否 | 每页数量;建议显式传入,例如 20;省略时部分列表返回全部 |
请求消息
无请求体。
响应消息
| 参数 | 参数类型 | 描述 |
|---|---|---|
| items | array<plan.response> | 结果列表 |
| total | integer | 匹配总数 |
| page | integer | 页码,从 1 开始 |
| page_size | integer | 每页数量 |
请求示例
GET https://{endpoint}/api/v1/plans?page=1&page_size=20
x-keystone-token: <Keystone Token>
正常响应示例
HTTP/1.1 200
Content-Type: application/json
{
"items": [
{
"id": "id-example",
"name": "标准套餐",
"description": "",
"status": "active",
"projectId": "projectId-example",
"ownerUserId": "ownerUserId-example",
"backend": {
"catalog": "",
"type": "",
"id": "id-example"
},
"spec": {
"planKey": "pk-a1b2c3d4e5f6",
"rps": 0,
"rpsUnit": "minute",
"rpsPeriod": 1,
"tps": 0,
"tpsUnit": "minute",
"tpsPeriod": 1,
"status": "active",
"routeIds": []
},
"createdAt": "2026-09-21T00:00:00Z",
"updatedAt": "2026-09-21T00:00:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 1
}
状态码与错误码
成功状态码:200。
| HTTP | error | 说明 |
|---|---|---|
| 500 | internal_error | failed to list plans |
| 401 | unauthorized | authentication required |
此外,认证/授权中间件可返回 401 / 403;后端错误与错误封装见调用方式。
创建套餐
功能介绍
创建套餐,配置请求限流、Token 限流和可访问路由。
访问要求:有效 Token 和本项目的套餐写权限。
URI
POST /api/v1/plans
请求消息
Content-Type: application/json。
| 参数 | 参数类型 | 是否必选 | 描述 |
|---|---|---|---|
| name | string | 是 | 套餐名称 |
| description | string | 否 | 描述 |
| rps | integer | 否 | 配置周期内的请求数上限,范围为 0..2147483647;0 表示不限量,缺省为 0。 |
| rpsUnit | string | 否 | 请求限流周期单位,minute、hour、day、month 或 year;缺省为 minute。 |
| rpsPeriod | integer / null | 否 | 请求限流周期倍数,为有效范围内的正整数;缺省为 1。 |
| tps | int64 | 否 | 配置周期内的 Token 数上限,为非负整数;0 表示不限量,缺省为 0。 |
| tpsUnit | string | 否 | Token 限流周期单位,minute、hour、day、month 或 year;缺省为 minute。 |
| tpsPeriod | integer / null | 否 | Token 限流周期倍数,为有效范围内的正整数;缺省为 1。 |
| status | string | 否 | 套餐状态:active 表示启用,disabled 表示禁用;缺省为 active。 |
| routeIds | array | 否 | 可访问路由 ID 数组,可为空;为空时套餐未授权任何路由。 |
| labels | map<string, string> | 否 | 标签键值对 |
建议创建时完整指定限流周期和上限;不限制某类用量时传入 0。
响应消息
| 参数 | 参数类型 | 描述 |
|---|---|---|
| id | string | 资源唯一标识 |
| name | string | 套餐名称 |
| description | string | 描述 |
| status | string | 套餐状态:active 或 disabled |
| projectId | string | 所属项目 ID |
| projectName | string | 项目名称;空值时可能省略 |
| domainId | string | 所属部门 ID;空值时可能省略 |
| domainName | string | 部门名称;空值时可能省略 |
| ownerUserId | string | 创建者用户 ID |
| ownerName | string | 创建者名称;空值时可能省略 |
| backend | plan.backendRef | 后端资源标识 |
| spec | plan.Spec | 套餐配置快照,包含系统生成的 planKey、限流配置、状态和可访问路由 ID |
| labels | map<string, string> | 标签键值对;空值时可能省略 |
| sharedProjectIds | array | 套餐已共享的项目 ID 数组;仅向拥有套餐全局读权限的调用方返回,共享接收方无法通过该字段查看其他接收项目。 |
| createdAt | string(date-time) | 创建时间,RFC3339 |
| updatedAt | string(date-time) | 更新时间,RFC3339 |
请求示例
POST https://{endpoint}/api/v1/plans
x-keystone-token: <Keystone Token>
Content-Type: application/json
{
"name": "标准套餐",
"rps": 60,
"rpsUnit": "minute",
"rpsPeriod": 1,
"tps": 10000,
"tpsUnit": "minute",
"tpsPeriod": 1,
"routeIds": [
"route-id"
],
"status": "active"
}
正常响应示例
HTTP/1.1 201
Content-Type: application/json
{
"id": "id-example",
"name": "标准套餐",
"description": "",
"status": "active",
"projectId": "projectId-example",
"ownerUserId": "ownerUserId-example",
"backend": {
"catalog": "",
"type": "",
"id": "id-example"
},
"spec": {
"planKey": "pk-a1b2c3d4e5f6",
"rps": 60,
"rpsUnit": "minute",
"rpsPeriod": 1,
"tps": 10000,
"tpsUnit": "minute",
"tpsPeriod": 1,
"status": "active",
"routeIds": [
"route-id"
]
},
"createdAt": "2026-09-21T00:00:00Z",
"updatedAt": "2026-09-21T00:00:00Z"
}
状态码与错误码
成功状态码:201。
| HTTP | error | 说明 |
|---|---|---|
| 400 | invalid_request | malformed JSON body |
| 409 | conflict | 详细原因由 message 返回。 |
| 500 | internal_error | failed to persist plan |
| 403 | forbidden | write permission required |
| 401 | unauthorized | authentication required |
此外,认证/授权中间件可返回 401 / 403;后端错误与错误封装见调用方式。
获取套餐详情
功能介绍
获取套餐详情。共享接收项目可查看共享给本项目的套餐,但不会获取其他共享接收项目的信息。
访问要求:有效 Token 和套餐读权限;本项目套餐、共享给本项目的套餐或全局读权限范围内的套餐可读。
URI
GET /api/v1/plans/{id}
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| id | string | 是 | 目标资源 ID |
请求消息
无请求体。
响应消息
| 参数 | 参数类型 | 描述 |
|---|---|---|
| id | string | 资源唯一标识 |
| name | string | 套餐名称 |
| description | string | 描述 |
| status | string | 套餐状态:active 或 disabled |
| projectId | string | 所属项目 ID |
| projectName | string | 项目名称;空值时可能省略 |
| domainId | string | 所属部门 ID;空值时可能省略 |
| domainName | string | 部门名称;空值时可能省略 |
| ownerUserId | string | 创建者用户 ID |
| ownerName | string | 创建者名称;空值时可能省略 |
| backend | plan.backendRef | 后端资源标识 |
| spec | plan.Spec | 套餐配置快照,包含系统生成的 planKey、限流配置、状态和可访问路由 ID |
| labels | map<string, string> | 标签键值对;空值时可能省略 |
| sharedProjectIds | array | 套餐已共享的项目 ID 数组;仅向拥有套餐全局读权限的调用方返回,共享接收方无法通过该字段查看其他接收项目。 |
| createdAt | string(date-time) | 创建时间,RFC3339 |
| updatedAt | string(date-time) | 更新时间,RFC3339 |
请求示例
GET https://{endpoint}/api/v1/plans/resource-id
x-keystone-token: <Keystone Token>
正常响应示例
HTTP/1.1 200
Content-Type: application/json
{
"id": "id-example",
"name": "标准套餐",
"description": "",
"status": "active",
"projectId": "projectId-example",
"ownerUserId": "ownerUserId-example",
"backend": {
"catalog": "",
"type": "",
"id": "id-example"
},
"spec": {
"planKey": "pk-a1b2c3d4e5f6",
"rps": 0,
"rpsUnit": "minute",
"rpsPeriod": 1,
"tps": 0,
"tpsUnit": "minute",
"tpsPeriod": 1,
"status": "active",
"routeIds": [
"route-id"
]
},
"createdAt": "2026-09-21T00:00:00Z",
"updatedAt": "2026-09-21T00:00:00Z"
}
状态码与错误码
成功状态码:200。
| HTTP | error | 说明 |
|---|---|---|
| 500 | internal_error | failed to resolve shared plan |
| 401 | unauthorized | authentication required |
| 404 | not_found | plan not found |
此外,认证/授权中间件可返回 401 / 403;后端错误与错误封装见调用方式。
更新套餐
功能介绍
更新套餐的基本信息、状态、限流配置或可访问路由。
访问要求:有效 Token 和套餐写权限;只能更新本项目所属的套餐,共享接收项目不能修改共享套餐。
URI
PATCH /api/v1/plans/{id}
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| id | string | 是 | 目标资源 ID |
请求消息
Content-Type: application/json。
| 参数 | 参数类型 | 是否必选 | 描述 |
|---|---|---|---|
| name | string / null | 否 | 套餐名称 |
| description | string / null | 否 | 描述 |
| rps | integer / null | 否 | 配置周期内的请求数上限;0 表示不限量 |
| rpsUnit | string / null | 否 | 请求限流周期单位 |
| rpsPeriod | integer / null | 否 | 请求限流周期倍数 |
| tps | int64 / null | 否 | 配置周期内的 Token 数上限;0 表示不限量 |
| tpsUnit | string / null | 否 | Token 限流周期单位 |
| tpsPeriod | integer / null | 否 | Token 限流周期倍数 |
| status | string / null | 否 | 套餐状态:active 表示启用,disabled 表示禁用 |
| routeIds | array / null | 否 | 可访问路由 ID 数组 |
| labels | map<string, string> / null | 否 | 标签键值对 |
PATCH 仅需发送待修改字段。rps/tps 可以为 0,表示对应用量不限;周期倍数必须是有效范围内的正整数。修改限流周期会重置当前周期的已使用量。
响应消息
| 参数 | 参数类型 | 描述 |
|---|---|---|
| id | string | 资源唯一标识 |
| name | string | 套餐名称 |
| description | string | 描述 |
| status | string | 套餐状态:active 或 disabled |
| projectId | string | 所属项目 ID |
| projectName | string | 项目名称;空值时可能省略 |
| domainId | string | 所属部门 ID;空值时可能省略 |
| domainName | string | 部门名称;空值时可能省略 |
| ownerUserId | string | 创建者用户 ID |
| ownerName | string | 创建者名称;空值时可能省略 |
| backend | plan.backendRef | 后端资源标识 |
| spec | plan.Spec | 套餐配置快照,包含系统生成的 planKey、限流配置、状态和可访问路由 ID |
| labels | map<string, string> | 标签键值对;空值时可能省略 |
| sharedProjectIds | array | 套餐已共享的项目 ID 数组;仅向拥有套餐全局读权限的调用方返回,共享接收方无法通过该字段查看其他接收项目。 |
| createdAt | string(date-time) | 创建时间,RFC3339 |
| updatedAt | string(date-time) | 更新时间,RFC3339 |
请求示例
PATCH https://{endpoint}/api/v1/plans/resource-id
x-keystone-token: <Keystone Token>
Content-Type: application/json
{
"name": "更新后的名称"
}
正常响应示例
HTTP/1.1 200
Content-Type: application/json
{
"id": "id-example",
"name": "更新后的名称",
"description": "",
"status": "active",
"projectId": "projectId-example",
"ownerUserId": "ownerUserId-example",
"backend": {
"catalog": "",
"type": "",
"id": "id-example"
},
"spec": {
"planKey": "pk-a1b2c3d4e5f6",
"rps": 0,
"rpsUnit": "minute",
"rpsPeriod": 1,
"tps": 0,
"tpsUnit": "minute",
"tpsPeriod": 1,
"status": "active",
"routeIds": [
"route-id"
]
},
"createdAt": "2026-09-21T00:00:00Z",
"updatedAt": "2026-09-21T00:00:00Z"
}
状态码与错误码
成功状态码:200。
| HTTP | error | 说明 |
|---|---|---|
| 400 | invalid_request | malformed JSON body |
| 500 | internal_error | failed to bind routes |
| 403 | forbidden | write permission required |
| 401 | unauthorized | authentication required |
| 404 | not_found | plan not found |
| 409 | conflict | plan already exists |
此外,认证/授权中间件可返回 401 / 403;后端错误与错误封装见调用方式。
删除套餐
功能介绍
删除套餐。套餐仍被 API Key 绑定时返回 409,需先解除绑定。
访问要求:有效 Token 和套餐写权限;只能删除本项目所属且未被 API Key 绑定的套餐。
URI
DELETE /api/v1/plans/{id}
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| id | string | 是 | 目标资源 ID |
请求消息
无请求体。
响应消息
成功返回 204 No Content,无响应体。
请求示例
DELETE https://{endpoint}/api/v1/plans/resource-id
x-keystone-token: <Keystone Token>
正常响应示例
HTTP/1.1 204 No Content
状态码与错误码
成功状态码:204。
| HTTP | error | 说明 |
|---|---|---|
| 409 | conflict | 详细原因由 message 返回。 |
| 500 | internal_error | failed to remove plan detail |
| 403 | forbidden | write permission required |
| 401 | unauthorized | authentication required |
| 404 | not_found | plan not found |
此外,认证/授权中间件可返回 401 / 403;后端错误与错误封装见调用方式。
查询套餐共享项目
功能介绍
查询已被授予该套餐使用权限的项目。
访问要求:Token + plan_share/global/manage。
URI
GET /api/v1/plans/{id}/shares
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| id | string | 是 | 目标资源 ID |
请求消息
无请求体。
响应消息
| 参数 | 参数类型 | 描述 |
|---|---|---|
| projectIds | array | 套餐已共享的项目 ID 数组 |
请求示例
GET https://{endpoint}/api/v1/plans/resource-id/shares
x-keystone-token: <Keystone Token>
正常响应示例
HTTP/1.1 200
Content-Type: application/json
{
"projectIds": [
"project-id"
]
}
状态码与错误码
成功状态码:200。
| HTTP | error | 说明 |
|---|---|---|
| 403 | forbidden | plan share management permission required |
| 500 | internal_error | failed to list plan shares |
| 401 | unauthorized | authentication required |
| 404 | not_found | plan not found |
此外,认证/授权中间件可返回 401 / 403;后端错误与错误封装见调用方式。
替换套餐共享项目
功能介绍
用请求中的项目 ID 数组整体替换套餐的共享项目。传入空数组表示撤销全部共享。
访问要求:Token + plan_share/global/manage。
URI
PUT /api/v1/plans/{id}/shares
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| id | string | 是 | 目标资源 ID |
请求消息
Content-Type: application/json。
| 参数 | 参数类型 | 是否必选 | 描述 |
|---|---|---|---|
| projectIds | array | 否 | 共享项目 ID 数组;省略或传入空数组表示撤销全部共享 |
响应消息
| 参数 | 参数类型 | 描述 |
|---|---|---|
| projectIds | array | 更新后的共享项目 ID 数组 |
请求示例
PUT https://{endpoint}/api/v1/plans/resource-id/shares
x-keystone-token: <Keystone Token>
Content-Type: application/json
{
"projectIds": [
"project-id"
]
}
正常响应示例
HTTP/1.1 200
Content-Type: application/json
{
"projectIds": [
"project-id"
]
}
状态码与错误码
成功状态码:200。
| HTTP | error | 说明 |
|---|---|---|
| 403 | forbidden | plan share management permission required |
| 400 | invalid_request | malformed JSON body |
| 503 | backend_unavailable | failed to validate tenant projects |
| 500 | internal_error | failed to inspect current plan shares |
| 409 | conflict | 详细原因由 message 返回。 |
| 401 | unauthorized | authentication required |
| 404 | not_found | plan not found |
此外,认证/授权中间件可返回 401 / 403;后端错误与错误封装见调用方式。
查询套餐可共享项目
功能介绍
查询可作为套餐共享目标的项目。套餐所属项目不包含在结果中。
访问要求:Token + plan_share/global/manage。
URI
GET /api/v1/plans/{id}/share-targets
| 参数 | 类型 | 必选 | 描述 |
|---|---|---|---|
| id | string | 是 | 目标资源 ID |
请求消息
无请求体。
响应消息
| 参数 | 参数类型 | 描述 |
|---|---|---|
| items | array<keystone.Project> | 结果列表 |
请求示例
GET https://{endpoint}/api/v1/plans/resource-id/share-targets
x-keystone-token: <Keystone Token>
正常响应示例
HTTP/1.1 200
Content-Type: application/json
{
"items": [
{
"id": "project-id",
"name": "示例项目",
"domainId": "domainId-example"
}
]
}
状态码与错误码
成功状态码:200。
| HTTP | error | 说明 |
|---|---|---|
| 403 | forbidden | plan share management permission required |
| 503 | backend_unavailable | failed to list tenant projects |
| 401 | unauthorized | authentication required |
| 404 | not_found | plan not found |
| 500 | internal_error | internal server error |
此外,认证/授权中间件可返回 401 / 403;后端错误与错误封装见调用方式。