Skip to main content
预算子密钥是从普通 Sunra API key 创建的短期子密钥,带有 USD 支出上限和独立的 call receipt。为每个 agent turn 或 run 创建一把预算子密钥,可以限制 agent 的 LLM 访问,并分别核算每位终端用户的用量。该上限通过估算成本控制请求准入:实际结算支出可能超过上限,因此请在您自己的 authorization hold 中预留余量。Sunra 仍向父密钥所属的 organization 计费;预算子密钥提供额度限制和用量归属,并不是 wallet。

生命周期概览

  1. Mint:使用普通密钥创建预算子密钥。保存子密钥 id、业务 ref 和仅返回一次的 secret。
  2. 调用:在到期前,使用子密钥 secret 发起一次或多次 LLM 调用,显式指定输出上限并设置 call tag。
  3. 查看:使用普通密钥读取实时支出和 call receipt。
  4. 关闭:turn 结束后关闭子密钥。轮询直到 status: closed,再根据最终 spent_usd 结算用户的 authorization hold。
所有管理请求均使用 https://api.sunra.ai 和 Authorization: Key \$SUNRA_KEY,其中 SUNRA_KEY 必须是有效的普通密钥。预算子密钥不能调用管理端点。参见鉴权。

Media endpoints

媒体访问启用后,预算池子密钥可调用所有多模态队列端点及上传初始化,仍须遵守密钥自身的模型访问限制。通过 https://api.sunra.ai 使用 Authorization: Bearer <child secret> 调用: 不入池的 standalone 预算子密钥调用这些路由返回 403 budget_key_route_forbidden。上传初始化不计费,返回 201;使用响应中的签名上传 URL 传输文件。 每个媒体提交与 organization 额度冻结使用同一准入金额:pre_defined 端点按精确价,post_calculated 端点按价卡的 freeze_amount 冻结额。例如 seed-asr-2.0 为 1.00,seedance−2.5因端点不同为1.00,seedance-2.5 因端点不同为 18–21,seedance-2.0 为 8。结算按实际收费,可超过估价。这是估价准入,不是花费硬上限:池中已记账金额与在途持有之和超过授权时,池因‘liability‘暂停,新提交返回‘402budgetpoolpaused‘;需要先‘credit‘增加授权,再‘resume‘。可选的子密钥‘capusd‘同样只限制估价准入:8。结算按实际收费,可超过估价。这是估价准入,不是花费硬上限:池中已记账金额与在途持有之和超过授权时,池因 `liability` 暂停,新提交返回 `402 budget_pool_paused`;需要先 `credit` 增加授权,再 `resume`。可选的子密钥 `cap_usd` 同样只限制估价准入:1 cap 可先持有 1、再实收1、再实收 2;池总授权足够时仍 active,子密钥 spent_usd 记录 $2,下一次提交被拒绝。 402 准入响应中的 estimate_usd 给出该单所需的准入金额。同价的 N 个并发提交在结算释放持有前需要 N 倍可用授权余量;混合端点则需要各单准入金额之和。0.10池无法容纳0.10 池无法容纳 1.00 的音频持有;N 个每单冻结 21的视频提交需要N×21 的视频提交需要 N × 21 余量。实际费用较低时释放差额。失败调用若已收费,即使发票为 VOID 也会记录实收。 x-sunra-call-tag 只在提交 prediction 时校验。配置了 metadata.allowed_tags 的子密钥在提交时必须携带允许的 tag;上传、状态、结果、流与取消不要求 tag。子密钥只能读取或取消自己提交的 request;他人或不存在的 request 均返回 404,流接口也返回 HTTP 404。 关闭或撤销子密钥不会取消在途任务。池子密钥 close 返回 HTTP 200,在发票结算前 body 为 status: "finalizing",结算后为 closed;终值包含晚到的媒体收费。 /calls 先按数据库 ID 顺序列出 LLM 行,再列出媒体行。cursor 为调用 ID(chatcmpl_ 或 pd_)。open 列表不是快照:cursor 进入媒体段后新增的 LLM 行不会出现在本轮遍历中。完整账本应在 close 后从头读取,并确认 complete: true;calls_count 合计两类调用。媒体 receipt 含 endpoint、非 token 的 usage: { usage_key, usage, unit_amount }、提交 tag 与实际 cost_usd,不含 wire_id。 媒体 usage 缺失字段显式为 null:无 usage 数据的取消单或 charged-VOID 单返回 usage: { usage_key: null, usage: null, unit_amount: null },close 后保持一致;媒体 receipt 不含 token 计数器。

创建预算子密钥

向 POST /v1/budget-keys 发送 JSON body: 可选字段请直接省略,不要发送 null。未知的顶层字段会被拒绝。省略 models 时,子密钥继承父密钥的模型限制;设置后,每次调用都必须同时满足该列表和父密钥当前的 allowlist。 以下示例使用 jq 将到期时间设为一小时后,并创建上限为 $0.05 的密钥:
201 response 直接返回资源,不包含 data 包装层。示例值如下:
请立即保存 secret_key:mint 仅返回一次。 GET、list、receipt 和 close 均不会返回它。Mint 不具备幂等性:重复请求即使使用相同的 ref,也会创建不同的子密钥。如果 response 丢失,请先使用下文的恢复端点找到并关闭遗留密钥,再决定是否重新 mint。

使用子密钥调用 LLM API

使用 https://api-llm.sunra.ai 和 Authorization: Bearer <child secret>。仅支持以下端点: 除上述池子密钥媒体路由外,其他 API 操作,包括预算子密钥管理和 native/media embeddings,均以 403 budget_key_route_forbidden 拒绝子密钥。已过期或已撤销的凭证可能先在鉴权阶段失败;无法识别的 URL 仍可能返回 404。 使用 Chat Completions 时,每次子密钥请求都必须发送 max_tokens 或 max_completion_tokens,并选择模型支持的字段。两者都缺失时返回 400 max_tokens_required。值必须是正的 safe integer;如果同时提供两个字段,它们必须相等。Messages 使用 max_tokens,Responses 使用 max_output_tokens。后两种 API 可以根据模型配置的输出上限补充缺失值;显式发送上限可以明确本次调用的输出额度。 准入估算对每个图片、音频、视频或文档 part 预留 8,192 tokens。如果模型对该媒体类型单独计价,则使用对应的输入费率;否则将这些 tokens 折入 prompt_tokens,按 prompt/input 费率预留。这是估算约定,不是 provider 强制保证的上界。结算仍使用实际 usage。 文本部分按序列化后的整个请求(含 tools 与 system)保守估算,因此纯文本调用的实际结算几乎总是低于预留。已知只有三种情况实际结算会超过预留,请按您实际会遇到的情况确定 hold 余量:Anthropic 格式请求的 prompt cache 写入按缓存写入费率结算(输入费率的 1.25×,ttl 为 1 小时时为 2×),预留不包含这部分溢价(带 tool search 的 Claude 模型即使不写 cache_control 也可能写入缓存前缀);单个媒体 part 超过 8,192 tokens 的预留值,长音频、视频或多页文档较常见;以及 xAI Grok 模型,其推理 tokens 不受 max_tokens 约束——这类调用没有可靠上界,如果上限必须成立,请用 models 排除它们。 n 可以省略,但提供时必须为数字 1。best_of 即使为 1 也会被拒绝。 子密钥请求只能携带下列 portable 生成参数,以及所调用端点对应的输出上限字段。其他字段——provider extension bag 和其他写法的 ceiling,例如 extra_body、generation_config、generationConfig、max_new_tokens——一律返回 400 invalid_input:它们可能在转换后放大真实输出上限,使 reservation 失效。允许的顶层字段为:model, provider, stream, stream_options, messages, input, system, instructions, tools, tool_choice, parallel_tool_calls, response_format, text, temperature, top_p, top_k, stop, stop_sequences, seed, presence_penalty, frequency_penalty, logit_bias, logprobs, top_logprobs, user, metadata, store, previous_response_id, include, truncation, reasoning, reasoning_effort, thinking, service_tier, safety_identifier, prompt_cache_key, prompt_cache_retention, verbosity, n, encoding_format, dimensions。使用普通密钥发起的请求不受此限制。

推理预算必须低于输出上限

thinking 和 reasoning 若出现,必须是对象。thinking.type 必须严格为 "enabled" 或 "disabled";adaptive、未知、缺失或非字符串类型对所有子密钥一律拒绝。启用 thinking 时必须提供 thinking.budget_tokens。任何 thinking.budget_tokens 或 reasoning.max_tokens 都必须是正的 safe integer,且严格小于准入的输出上限;等于或超过上限,或格式错误(null、字符串、小数、零、负数、非 safe integer)均在 reservation、冻结额度、调用记录和上游请求之前返回 400 invalid_input。格式错误的值不会被当作”未传”。通过校验的预算原样转发。 对 Claude 模型(含别名)和 Messages 请求,比较时至少按 provider 的 1,024-token 最小推理配额计算,因此 512 的 thinking 预算按 1,024 处理。例如 max_tokens: 64 搭配 thinking: {"type":"enabled","budget_tokens":1024} 会返回 400 invalid_input(thinking.budget_tokens must be below the output ceiling);要使用该预算,请把输出上限设为至少 1,025 并为子密钥准备相应额度。effort 类控制(reasoning_effort、reasoning.effort、reasoning: {"enabled": true})仍然支持,且不会突破上限;thinking: {"type":"disabled"} 仍然支持,包括下文的 Qwen 转换。普通密钥和 session 不受影响。 使用 x-sunra-call-tag 标记调用,值最多为 128 个 printable ASCII 字符。它会作为 tag 出现在 receipt 中。如果密钥设置了 metadata.allowed_tags,缺失 tag 或 tag 不在集合内会返回 403 budget_call_tag_forbidden;否则该 header 为可选。普通密钥完全忽略该 header。 将返回的 secret 赋给 CHILD。-i 会显示 response header:
保存 x-sunra-prediction-id,用于将本次调用关联到对应的 receipt。Receipt 的 id 与该 header 的值逐字节一致;不要用 provider response ID 替代它。

关闭 Qwen Chat 的 thinking

在已映射的 Qwen → DashScope 路由上,子密钥的 Chat Completions 请求可使用 thinking: {"type":"disabled"}、reasoning_effort: "none",或同时使用两者。Sunra 会移除这些控制字段并发送原生关闭开关,保留输出上限和 n。子密钥必须允许所选模型和 tag。
支持的公共 ID 为 qwen/qwen3.7-flash、qwen/qwen3.7-plus、qwen/qwen3.7-max 和 qwen/qwen3.8-max,分别经 LiteLLM 解析到同名的 DashScope group(去掉 qwen/ 前缀)。是否支持取决于实际解析的路由;仅指定模型名称或 provider 偏好不能保证支持。 以下情况会在创建调用记录、冻结 credit 或预留预算之前返回 400 invalid_input:
  • 关闭意图与非 "none" 的 reasoning_effort、不完全等于 {"type":"disabled"} 的 thinking,或任意 reasoning 字段同时出现。
  • disabled thinking 对象包含额外字段,例如 budget_tokens。
  • 在未映射的 Qwen 路由上请求关闭,或在 Qwen Messages、Responses 上请求关闭。
  • 原生 enable_thinking(包括布尔值 false)或客户端 extra_body:子密钥仍拒绝这两个字段。
普通密钥行为不变,不应用此子密钥专用转换。非 Qwen 路由及没有关闭意图的请求保留原有行为。这不是跨供应商的通用保证。仅有 HTTP 200 不能证明 thinking 已关闭。 验证需要实际观测的用量,包括明确的 usage.reasoning_tokens: 0;字段缺失表示未知。

跟踪支出

读取密钥

将 mint 返回的子密钥 id 赋给 ID:
Response 包含与 mint 相同的资源字段,但不含 secret_key: 准入会在调用前预留估算售价。实际结算成本可能因在途调用的估算误差而超过上限。请在您自己的 authorization hold 中留出余量;不要根据 open 密钥的支出或 LLM response 已结束就释放 hold。未知的实时值不等于零。

读取逐调用 receipt

limit 默认为 100,允许 1–500。只要 has_more 为 true,就将 next_cursor 作为 after 请求下一页;该值是本页最后一行的 id。请原样传回并进行 URL encoding。无效 cursor 或属于其他子密钥的 cursor 会返回 400 invalid_input。 以下为包含一次已付费调用的密钥在关闭后的示例页面:
Receipt 包含 PAID、VOID、PENDING 和 UNCOLLECTIBLE 尝试。只有 PAID 行具有结算成本;其他状态的 cost_usd 均为 "0.00000000"。在创建调用记录之前被拒绝的请求不计入。completed_at 和 tag 可以为 null;wire_id 为可选字段。 usage 始终包含四个整数计数:input_tokens、output_tokens、cache_read_tokens 和 cache_write_tokens,不适用时为 0。存在 invoice.price_breakdown 时,计数来自这些计费分桶:input_tokens 仅表示未缓存的输入,三个输入分桶互不重叠,总 prompt tokens = input_tokens + cache_read_tokens + cache_write_tokens。cache_write_tokens 合并 5 分钟和 1 小时的缓存写入层级;output_tokens 为计费输出计数。 每行的 usage_exclusive 表示输入分桶是否互不重叠:用量来自 price_breakdown,或有效的持久化路由 dialect 标记使原始计数可被拆分时,为 true。缺少 price_breakdown 时,receipt 会尽可能读取原始用量中的平面或嵌套 cache 计数,并只减去 dialect 标记为已包含在输入中的分桶,结果最低为 0。若 dialect 标记缺失或格式无效,则保留原始输入计数,usage_exclusive 为 false;此时不能假定上述求和关系成立。实时行使用实时数据;闭票行只使用封存的发票、用量和 dialect 标记。历史封存发票无需迁移即可按 v2 展示。 带有 price_breakdown 的 PAID 行还包含 cost_breakdown,固定为 input_usd、cache_read_usd、cache_write_usd 和 output_usd 四个 8 位小数 USD 字符串,使用 decimal arithmetic 求和时精确等于 cost_usd。每个分桶先以用量 × 单价精确计算,5 分钟和 1 小时写入成本先合并,再使用 ROUND_HALF_EVEN 舍入到 8 位小数。舍入后,将 cost_usd − sum(rounded buckets) 加到精确金额最大的分桶;并列时按 input、cache read、cache write、output 的顺序选择。退款导致 amount_paid 与发票总额不同时,也使用同一规则对齐实际支付金额。非 PAID 行,以及缺少 price_breakdown 的旧 PAID 行,不包含 cost_breakdown。 calls_count 是 receipt 所有分页中的尝试总数,不只是当前页的行数。只有 closed 密钥的 complete 才为 true;open 和 finalizing 状态的 receipt 仍可能变化。最终对账时,请先关闭密钥,从第一页重新读取全部 receipt,并使用 decimal arithmetic 对 status: "PAID" 行的 cost_usd 求和。该总和等于 closed 后的 spent_usd,总行数等于 closed 后的 calls 和 receipt 的 calls_count。仅有 has_more: false 并不表示密钥已关闭。 usage.reasoning_tokens 是从上游用量观测到的可选非负整数。无论网关响应用哪个名字,receipt 里都统一用这一个键:Chat Completions 为 completion_tokens_details.reasoning_tokens,Responses 为 output_tokens_details.reasoning_tokens,Anthropic 形状的 /v1/messages 响应(Claude)为 output_tokens_details.thinking_tokens。明确的 0 表示上游报告了零 reasoning token;缺失表示上游根本没有报告该计数,即未知,不等于零。正数仍是输出 token 的明细,不会再次累加到输出 token 或发票中。实时行读取实时用量;闭票行只读取封存用量,即使实时用量随后变化也不受影响。历史封存记录中已存储的计数也可展示。receipt_version 为 2。

在 dashboard 中查看密钥

platform.sunra.ai/dashboard/budget 的 Budget 标签页在 Keys 下列出组织内的全部预算子密钥,不区分由哪把密钥签发、也不受 management 限制。可按 ref / 名称搜索、按状态和父密钥筛选;点开一行可查看逐调用 receipt。该页面只读:mint 与关闭仍由父密钥通过 API 完成。开放中的密钥在可用时显示上文的实时值,已关闭的密钥显示不可变的最终支出与调用次数。预算子密钥不会出现在 API tokens 页面。

关闭密钥

Close 不需要 body,并会阻止新调用。使用已关闭的子密钥调用会返回 401 budget_key_revoked。Close 不会取消已经准入的调用,它们仍可能继续结算。 Close 具有幂等性。密钥关闭后,重复请求返回相同的最终 snapshot;没有调用的密钥也会返回支出为零的 snapshot。也可以轮询 GET by ID,但即使 status 为 finalizing,GET 也返回 HTTP 200:请始终检查 body。对于独立预算密钥,GET by ID 和 close 会根据已持久化的结算核对未释放的 hold,因此正常情况下,每次调用的结算均已记录后即可完成 finalization。如果结算始终未到达,该 hold 会在调用准入后 30 分钟到期。如果实时状态丢失,finalization 会等待至 expires_at 加 30 分钟;未知实时值仍为 null,不代表零。封存由读取触发:满足上述条件后,仍需继续轮询 GET 或 close。存储故障或回执分批处理可能需要继续重试。

端到端示例

使用 Bash、支持 --fail-with-body 的 curl 和 jq 运行以下示例。按照鉴权中的说明将普通密钥赋给 SUNRA_KEY。示例使用 google/gemini-2.5-flash,父密钥必须允许该模型。它会创建一把上限为 $0.05、有效期为一小时的密钥,发起一次调用、读取 receipt、关闭密钥并打印最终支出。Close 前读取的 receipt 仍可能处于 pending 状态。 如果调用或 receipt 读取失败,exit handler 也会尝试关闭密钥。请在应用中保存打印出的 ref 和子密钥 ID,以便在执行中断后恢复处理。
Mint 结果不明确时,不要自动重试 mint。应用需要最终的逐调用账目时,请按上文说明,在 closed 后重新读取全部 receipt 分页。重复发送 LLM 请求不会被去重,可能再次产生费用。

找回丢失的 ticket

如果 mint response 或本地 ticket 记录丢失,可使用已保存的 ref 找回子密钥 ID:
Response 形如 { "data": [...], "has_more": false, "next_cursor": null },data 中包含预算子密钥资源,不含 secret。必须至少提供 ref、parent_api_key_id 或 closed_by_api_key_id 中一个筛选条件。ref 如提供,必须非空且最多 256 个字符;parent_api_key_id 是精确匹配的字符串,长度为 1–128,不做去空格或大小写转换。多个条件同时提供时按 AND 匹配。未知或其他组织的父 ID 返回空列表,不授予任何权限。limit 默认为 100,允许 1–100。如果 has_more 为 true,将不透明的 next_cursor 进行 URL encoding 后作为 after 请求下一页。多个密钥可以共用同一个 ref;请检查所有匹配项并关闭遗留密钥。 List 用于找回密钥。请使用 GET by ID 或 close 获取最终账目状态,不要根据 open 状态的 list 结果结算 authorization hold。Secret 无法找回。 按签发父密钥列出可见子票,无需 ref:
列表默认按创建时间倒序、内部 ID 倒序排列,先应用权限再分页;has_more 仅表示还有可见记录。旧的有效 ref 游标可继续使用。游标锚点必须匹配当前组织、筛选条件与可见性;不匹配返回 400 invalid_input,请重新开始扫描。游标不是快照,也不是授权凭证。

管理权限与恢复

所有预算资源响应(mint、get、list 中的每一项和 close)都包含有效的 management。该模式同时约束资源读取、calls 回执读取、关闭和列表可见性: 恢复不需要新的 admin key。请使用原组织内另一把 active 普通密钥处理未结 ticket。父密钥查询失败返回可重试的 503 budget_store_unavailable,绝不视为已撤销;父密钥重新激活后,后续请求再次受限。撤销父密钥阻止新的子密钥调用,但不会取消已准入的调用或自动封存回执。 这只是预算管理授权收窄,不是租户隔离。同组织普通密钥仍可通过 /v1/completions 查看子票调用与费用。独立的对账密钥在父密钥有效时不能读取 parent_only 回执;应使用签发父密钥的凭证,或选择 org 模式。需要真正的租户隔离时,应使用独立组织。 parent_only 创建按 rollout 启用;启用前返回 400 budget_key_parent_only_disabled,不要删除 management 后自动重试。筛选和有效模式输出始终提供。运维需先完成全部 auth/apiv1 管理实例的升级并确认索引,再在 auth 设置 BUDGET_KEYS_PARENT_ONLY_ENABLED=true;存在受保护记录后,回滚也必须保留授权检查。

这把密钥做了什么?

分别读取四个来源;不提供聚合 /activity 端点。管理读取使用同组织、有效的普通密钥。 预算列表必须至少提供 ref、parent_api_key_id、closed_by_api_key_id 中一个条件,同时提供时按 AND 匹配。关闭者 ID 与父 ID 一样,按 1–128 字符的字符串精确匹配。未知或其他组织的筛选 ID 返回空列表。可选 time_range_start / time_range_end 为带时区的 ISO 日期时间(例如 2026-09-15T12:00:00Z),两端均包含;可以只给一端,起点不得晚于终点。time_field 为 created_at(默认)、close_requested_at 或 closed_at;缺少所选时间戳的记录被排除。按所选时间倒序,再按内部 ID 倒序。无效筛选、时间范围、时间字段或游标返回 400 invalid_input。 每个预算资源包含 created_at、close_requested_at、closed_by_api_key_id;未知值为 null。closed_at 表示最终回执封存时间。封存前首次接受的显式 POST /close 将认证调用者和服务器时间戳与持久化准入撤销原子写入,即使随后返回 503 也保留归因。重试、其他关闭者和终结锁接管都不能覆盖。惰性 GET、calls 触发的终结以及 mint 清理不会填写归因,除非封存前已接受显式关闭。历史 null 表示未知,不能推断父密钥就是关闭者。 撤销响应为 { data: [...], has_more: false }。每项包含 id、object: "api_key_revocation"、api_key_id、revoked_at、revoked_by 和可为 null 的 reactivated_at。存储机制仅保留最近 50 项,一次返回,无游标。目标可以已撤销;同组织的有效普通密钥均可读取。未知或跨组织目标返回 404 api_key_not_found;预算子密钥目标返回 400 invalid_input;子密钥和 session 调用者禁止访问。依赖故障返回 503 budget_store_unavailable,不会伪造空历史。 Actor 结构为 {type: "api_key" | "user" | "system" | "unknown", id: string | null}。api_key / user 的 ID 指向实际执行操作的主体;成员 JWT 撤销记录成员为 user,后端内部撤销记录 system 且 ID 为 null,未知执行者为 unknown 且 ID 为 null。绝不使用密钥创建者代替。已撤销状态下重试不会新增记录;重新激活会在最后一条未结束记录上写入 reactivated_at,再次撤销才追加新记录。已有成员授权的密钥详情 / 列表也返回最新 revoked_at / revoked_by 摘要(重新激活后仍保留)以及 revocation_history。不回填历史撤销:null 摘要或空数组不代表从未撤销。超出最近 50 条的旧记录不再保留,不提供历史完整性时间标记。 各来源保留自己的游标约定:
  • 预算列表使用不透明的 after=next_cursor,最多 256 字符;limit 为 1–100,默认 100。创建时间分页保留原游标,并按当前筛选和可见性验证锚点。其他时间字段使用版本化游标,绑定组织、调用者、筛选条件、范围和时间字段;修改后必须从第一页重扫,不匹配返回 400。分页不是快照。
  • completions 使用 starting_after(最后一行 ID),拒绝 ending_before;按内部 ID 倒序,支持包含端点的创建时间范围筛选,limit 默认 10、最大 10000;不能使用预算列表游标。
  • 子密钥 /calls 使用最后一条 completion 的精确 ID 作为 after;limit 为 1–500,默认 100。
  • revocations 一次返回保留数组,不使用分页游标。
重叠扫描包含端点的时间窗口,按稳定的子密钥 / completion / 撤销事件 ID 去重。单独跟踪未完成的子密钥 ID,轮询 GET 直到 closed:创建时间扫描发现不了后续封存,关闭请求时间扫描也不表示最终回执已经就绪。可辅以父 ID + time_field=closed_at 扫描。自身尚未结算的 completion 应按 ID 重读,结算不会改变其创建时间。 最终回执仍是结算权威:关闭后从头读取全部 /calls 页,要求 complete:true,核对仅 PAID 的十进制金额总和及全部尝试次数与最终 spent_usd / calls 一致。活动列表只是观察记录,不是另一套账本。总额已包含子密钥 completion 时,不要再加一次子密钥回执金额。

错误

请同时检查 HTTP status 和 error.details.reason;下表说明预算相关错误的处理方式。已有的 model-access、parameter-validation、organization-balance 和 upstream 错误可能保留原有的 response 格式。 402 budget_reserved body 示例:
budget_exhausted 和 budget_reserved 包含准入决策时的全部四个 USD 字符串。对于这些金额字段,budget_state_unknown 只返回 cap_usd;不能将缺失的 spend 和 reservation 值视为零。

限制与保证

  • 有效期: 从 mint 校验时起最多 24 小时。到期后停止新调用;最终账目仍需获取 closed snapshot。
  • Best-effort cap: 准入预留的是估算售价。实际支出可能因在途调用的估算误差而超过 cap_usd。请在自己的 authorization hold 中预留余量。
  • 实时值与最终值: Open 和 finalizing 状态的数值可能变化。只有 status: closed 提供权威且不可变的 snapshot;其 receipt 标记为 complete: true。Snapshot 覆盖已记录的结算,因此从未记录或在 snapshot 之后才到达的结算可能不包含在最终金额中。
  • 计费: 父密钥所属的 organization 仍按原有方式计费,并继续受现有余额和访问限制约束。预算子密钥不会为 wallet 注资,也不会将终端用户的资金转入 Sunra;终端用户的授权和账目由您的应用管理。