Token 套餐与多模态 API
Token API 提供套餐查询与购买、付款恢复、额度与用量查询,以及多模态模型调用。白牌客户可以在自己的产品中完成这些操作,无需先进入平台控制台。
1. 配置用户身份权限
在当前应用的“API 与权限 → 用户身份权限”申请已发布的 Token API 产品。配置用户登录回调,使用授权码 + PKCE,让用户确认操作范围。用户 Access Token 属于当前应用的用户 OAuth Client;不能用模型节点的 API Key 或应用身份 Token 替代。
| 操作 | 最小 Scope | 客户权限 |
|---|---|---|
| 读取套餐 | commerce.catalog.read | 当前客户的商业读取权 |
| 读取原订单 | commerce.order.read | 当前客户的商业读取权 |
| 创建订单/恢复付款 | commerce.checkout.create | 当前付款主体的付款操作权 |
| 读取模型 | inference.models.read | 当前用户的产品调用授权 |
| 调用模型 | inference.invoke | 当前用户的产品调用授权及可用额度 |
| 读取额度 | inference.balance.read | 当前客户账务账户读取权 |
| 读取用量 | inference.usage.read | 当前客户账务账户读取权 |
自动配置成功后确认“API 与权限”中的实际绑定状态为已绑定,再通过 PKCE 重新获取包含本次最小 Scope 的用户 Token。Audience 由当前启用的产品及权限签发,客户无需手工添加;配置漂移或更新前的旧 Token 可能被拒绝。
API 权限配置、用户同意和客户自身权限都需要当前有效。模型调用用户无需付款人权限;套餐付款成功也不会自动授予用户权限。
完成用户身份认证后,使用当前应用的用户 OAuth Client Token 调用 /open-platform/v1/delegated-grants,保存当前用户的产品授权。
application_id、environment和api_product_id:使用当前应用的稳定 ID、明确的sandbox|production环境及 API 产品。scopes:仅填写本次需要的权限。- 资源范围:使用
{"resource_type":"token_product","resource_ids":["<product_code>"]}。
保存响应中的 Grant ID,供后续调用使用。授权撤销或到期后,调用会被拒绝。创建与撤销参数请参见用户授权。
使用当前环境提供的 GOODVISION_API_BASE,并在每次请求中携带以下请求头。环境明确选择 sandbox|production;Client、绑定和 Scope 由平台派生,请求不接受价格、账务账户或执行节点地址。
Authorization: Bearer ${GOODVISION_USER_ACCESS_TOKEN}
X-GV-Organization-ID: ${GOODVISION_CUSTOMER_ORGANIZATION_ID}
X-GV-Application-ID: ${GOODVISION_APPLICATION_ID}
X-GV-Environment: ${GOODVISION_APPLICATION_ENVIRONMENT}
X-GV-API-Product-ID: ${GOODVISION_API_PRODUCT_ID}
X-GV-Delegated-Grant-ID: ${GOODVISION_DELEGATED_GRANT_ID}
X-GV-Product-Code: ${GOODVISION_PRODUCT_CODE}平台会核验这些请求头对应的应用、授权和产品范围。同一应用的 Sandbox 与 Production 分别使用独立的运行身份、授权、订单和额度。
2. 查询、购买与恢复
| Endpoint | 用途 |
|---|---|
GET /open-platform/v1/token-packages | 读取当前可售套餐、价格、Credits换算、期限、购买资格、模型倍率及条款 |
POST /open-platform/v1/token-orders | 按所选版本和条款创建原订单 |
GET /open-platform/v1/token-orders | 读取当前客户/应用的订单 |
GET /open-platform/v1/token-orders/{id} | 查询原订单及付款状态 |
POST /open-platform/v1/token-orders/{id}:checkout | 创建或恢复该订单的原 Hosted Checkout |
创建订单发送稳定的 Idempotency-Key,正文只包含当前目录返回的选择:
{
"package_id": "<catalog.package.id>",
"package_version": 3,
"accepted_terms_sha256": "<catalog.package.terms_sha256>"
}购买和付款分两步完成:
- 保存创建订单返回的 Order ID。
- 向该订单的
:checkout接口发送原付款操作键,打开返回的checkout_url。 - 客户完成付款后,查询原订单。只有
status=paid才表示付款已确认。 - 调用余额 API,单独核对额度是否到账。
客户回跳后,请先查询状态,再展示付款成功。
应用内购买可在创建订单时增加return_reference: "application-entry"。成功和取消都返回应用已审核发布的 HTTPS 访问地址,并带回payment、payment_order、organization、application、environment和product。不传任意返回URL;后续地址调整不改变原订单。返回参数只定位原订单,payment=success不能替代GET /open-platform/v1/token-orders/{id}的paid回执。等待确认时可有时限地自动回读,错误或超时提供手动回读,确认付款后再查询余额。SaaSdemo展示同订单付款入口,无需另外创建付款订单或重新登录。
请求超时或响应丢失时,保留原订单、正文和请求键,继续查询并恢复原请求,避免重复创建订单或付款。
套餐版本或条款变化会返回 409。重新读取目录,让用户确认新条件。若返回的套餐版本、条款摘要或订单与原操作不一致,保留原内容和键并继续恢复,确认前不展示成功。
Credits加量包政策
加量包是一次性购买,不自动续费。套餐声明 units_per_credit 时,使用 units 除以该比例显示 Credits。历史 Token 单位保持原样,换算比例以原套餐声明为准。
响应仅返回 validity_days 或 validity_months 中的一项:
- 天数:每一天按 24 小时计算。
- 自然月:从确认付款的 UTC 时间开始计算。目标月份没有对应日期时,使用该月最后一天,例如 1 月 31 日至 2 月 28 日。
到账后,以原额度批次的 expires_at 为准。迟到回调和新套餐版本不会延长原有效期。
subscription_requirement 可指定适用的已成交 plan_codes,allow_free 默认 false。以目录的 eligibility.eligible 判断能否新购,reason 说明原因:
| 原因 | 含义 |
|---|---|
unrestricted | 无订阅限制 |
eligible_subscription | 当前订阅符合要求 |
subscription_required | 需要符合要求的订阅 |
不符合资格的套餐仍可展示,并提示客户开通或续费适用套餐。套餐名称、试用状态和待生效升级不能用于判断资格。已安排取消的订阅在实际截止前仍有效。
新购无资格时返回 403 和 token_customer_denied。重新读取目录,区分订阅资格缺失与客户权限不足。已接受的原订单和原付款可继续恢复,即使客户后来不再满足新购资格。
退款按原订单的 refund_policy 处理:
| 值 | 规则 |
|---|---|
none | 不退款 |
unused | 仅整包未使用、且无在途预留时,可通过获授权的运营流程退款 |
历史订单未提供此字段时,使用原“未使用整包”规则。展示购买时的退款政策。
3. 模型与调用
GET /open-platform/v1/inference/models 返回当前可调用且有合格额度的模型。每个模型的 x_gv.execution_profiles 列出可执行的协议、输入模态和上限组合,例如:
{
"protocol": "openai_chat",
"input_modalities": ["text", "image"],
"context_limit": 32768,
"output_limit": 4096,
"supports_tools": false
}从 x_gv.execution_profiles 中选择一条同时满足协议、输入模态和上限的配置,不能组合不同条目的能力。openai_chat、openai_responses、anthropic_messages 分别对应下方三个接口。
图像、音频和文件输入需要模型声明对应的原生协议。未声明的媒体会在额度预留前被拒绝;上限未知的模型不会出现在目录中。每次调用仍会重新检查当前授权、额度和模型状态。
本期返回文本,支持明确声明的用户侧函数工具;不开放音频输出、视频输入、内置收费工具、独立图片/视频生成、后台执行或保存的响应状态。Responses 请求携带完整上下文,store 和 background 如有则设为 false,不传 previous_response_id。
POST /open-platform/v1/inference/chat/completions
POST /open-platform/v1/inference/responses
POST /open-platform/v1/inference/messages每次调用需指定模型、固定的 Idempotency-Key 和正整数输出上限:
| 协议 | 输出上限参数 |
|---|---|
| Chat | max_completion_tokens 或 max_tokens |
| Responses | max_output_tokens |
| Messages | max_tokens |
一次请求仅支持一个输出结果。输入模态和协议需在模型支持范围内。
{
"model": "<eligible_model_id>",
"max_completion_tokens": 1024,
"stream": true,
"messages": [
{"role": "user", "content": [{"type": "text", "text": "请说明这张图片的内容"}, {"type": "image_url", "image_url": {"url": "https://assets.example.test/example.png"}}]}
]
}流式响应使用 text/event-stream。保存响应头 X-GV-Inference-Request-ID,用于查询用量中的 request_id。
同一逻辑请求键最多执行一次,再次提交返回 409,不会重复消耗。超时、流中断或缺少最终用量时,预留额度会进入待核对状态。请查询原请求,不要更换键重复调用。
调用前,平台按模型的保守输入上限和本次输出上限预留额度。结果确定后,按实际输入/输出 Token 和购买时的倍率结算,并释放差额。
倍率以百万分比整数保存,消耗计算为 ceil((输入 Token × 输入倍率 + 输出 Token × 输出倍率) / 1000000)。响应分别返回原始 Token 用量和套餐消耗。
4. 额度、用量与拒绝处理
GET /open-platform/v1/token-balance 返回当前 available、reserved、consumed、expired、revoked 及最多 100 个额度批次。使用 next_grant_cursor 作为下一次的 grant_cursor。
先读取套餐、批次、余额和用量中的 ledger_unit。usd_micros_v1 表示一单位为百万分之一美元:10000001 为 USD 10.000001;未声明时沿用原加权 Token 或明确的 Credits 换算,不推断为美元。美元额度与购买价格独立,同一范围不能混用单位或转换历史额度。
美元模型价由 usd_price_version 固定,input_usd_per_million_micros 和 output_usd_per_million_micros 分别为每百万输入/输出 Token 的微美元整数价格;权重字段为零。消耗为 ceil((输入 Token × 输入价格 + 输出 Token × 输出价格) / 1000000),整请求只舍入一次,结果仍是微美元。展示和导出须保留低于一美分的精度;不要将微美元整数显示成 Token 或直接显示成美元。
额度批次
购买额度在 grants 中返回,商业赠送和订阅周期额度在 benefit_grants 中返回。两类批次共用最多 100 条的分页上限和游标,总额度包含两类实际已发放批次。
商业额度的 benefit.source_type 可为 welcome、subscription、activity 或 campaign,并包含来源、政策版本、周期和有效期。这些字段说明已发放额度的来源,不能据此判断某项赠额政策已开放。benefit_grants 为空或缺失时,也需单独确认政策状态。
blocked=true 表示该批次已停止新预留,在途请求仍按原分配结算或释放。用量 allocations 保留 source_type、policy_id 等来源引用,order_id 和 package_id 可为空。赠送额度不表示购买或付款,不创建订单;美元计量只表示可消费额度面值,不表示已付收入或可退款金额。
查询使用记录
GET /open-platform/v1/token-usage?limit=50 返回使用记录及 next_cursor,下一页使用 cursor。分页展示每次查询时的状态;刷新时从第一页开始。
| 状态 | 说明 |
|---|---|
reserved | 请求进行中,额度已预留 |
pending_review | 结果待核对 |
settled | 已结算 |
released | 已确认零消耗,预留已释放 |
筛选与统计
使用 offset=0&limit=50 获取分页统计,可添加 from、to(ISO 8601 时间,含起点、不含终点)、model、status、package_id、order_id 和 grant_id(购买额度批次)。此模式不能同时使用 cursor 或原请求精确查询。
响应的 page、summary、models、regions、trend、trend_granularity 和 packages 覆盖全部匹配记录。趋势使用完整 UTC 查询周期:
| 粒度 | 范围 |
|---|---|
granularity=auto | 默认七天内按小时、一年内按天、更长周期按月 |
hour | 必须提供起点,最多 31 天 |
day | 最多 366 天 |
翻页时保持原筛选;刷新时读取最新记录。
统计字段说明如下:
| 字段 | 说明 |
|---|---|
summary.requests | 包括已结算和未结算的逻辑请求 |
settled_requests、released_requests、review_requests | 分别为已结算、已释放、待核查请求数 |
reserved_units | 匹配请求当前仍占用的预留额度 |
consumed | 按购买时模型倍率计算的实际扣减;缓存读取包含在输入 Token 内 |
allocations | 每条请求的套餐版本、原订单、额度批次、到期时间和实际扣减/预留 |
packages | 按套餐版本汇总的实际扣减 |
一次请求可使用多个套餐,分组请求数存在重叠,不能跨组相加。按套餐筛选时,仍返回匹配请求的全部批次和总扣减,便于核对。原始 Token 不估算分摊到各套餐,套餐额度也不作为货币金额展示。
恢复一次调用时,使用响应中的 X-GV-Inference-Request-ID 精确查询:
GET /open-platform/v1/token-usage?request_id=<X-GV-Inference-Request-ID>精确查询在当前客户、应用、环境、产品和账务账户范围内返回零或一条记录,不能同时传 cursor 或 limit。
settled:已扣减。released:已确认零消耗。reserved或pending_review:继续等待或核对。
空结果表示当前没有可读记录,不能据此判断上游零消耗或改键重发。查询需要 inference.usage.read 和账务读取权,普通模型调用权限不包含账务读取权。
| 状态码 | 下一步 |
|---|---|
401/403 | 重新确认当前用户登录、应用用户身份、API 权限、用户授权和客户自身权限 |
402 | 额度不足、到期或存在待核对请求;读取当前状态后处理 |
409 | 查询原订单/原请求,保持原键;变化的购买条件需要重新确认 |
422 | 修正购买参数、模型、输入能力、输出上限或分页参数 |
429 | 按 Retry-After 等待,保留原键 |
503 | 保留原订单/原键;先查结果,再恢复操作 |
API 产品发布与当前应用权限仍以开发者工作台的实际状态为准。代码模板和本指南不代表某个环境已经开通。
用户空间与模型权限
客户空间由用户上下文解析,不要求用户填写内部 ID。进入个人空间或关联多应用用户不会自动开通模型 Scope、用户授权或额度;这些权限仍按本文独立核验。