跳到主要内容

身份验证与作用域

platform API 使用您组织的 key 进行身份验证。它有两种形式 — 同一组织、相同 scopes、不同 runtime:

FormCredentialSent as
Server (backend)kld_sk_live_…Authorization: Bearer …X-Api-Key
Publishable (browser)kld_pk_live_…由 SDK 交换为短期 session;绝不会作为 raw bearer 发送
Authorization: Bearer kld_sk_live_…
# or
X-Api-Key: kld_sk_live_…

Server keys 是您从 backend 在每个 request 中发送的 bearer。 Publishable keys 用于浏览器:SDK 会在 runtime 将其交换为短期、 绑定 origin 的 session token,因此 publishable key 本身不会成为 page source 中长期存在的 credential。直接将 publishable key 作为 bearer 提交会被拒绝 — 请通过 SDK 使用。server key 不会获得任何 CORS grant,因此页面永远无法 读取 使用它产生的 response — 但 CORS 无法 阻止 request 离开浏览器,因此一旦 server key 被放入 page source,它就已经泄露。API 拒绝它时已经太迟。SDK 正是因为这个原因在 mount 时拒绝 kld_sk_… key:请始终将 server key 保留在 server-side。

现有 legacy kld_live_… key 会继续在两种场景中作为 direct bearer 使用。

作用域

key 携带 capability scopes;每个 route family 都需要其中一个:

ScopeRoute familyUsed by
ai/inference-api/b2b/v1/chat/*, /retrieval/*chat embed
design/inference-api/b2b/v1/design/*editor embed
mapsdesigned basemapsthe tile embed
vendor(modifier, not a route)the chat embed, on your own data

默认情况下,Pro/Enterprise key 会使用 aidesignmaps 进行 mint。 Free-plan key 仅限 maps + tile 产品;请参阅 获取 API 密钥 中的正式 plan × scope × product 表。

Effective admission = stored key × current tier。 Runtime session-exchange 会在每次 call 时重新计算 admission,因此 Pro-tier key 降级为 Free 后, 从那一刻起只能 mint tile session — 即使 stored key 中仍然 包含 aidesign 限制。rejection subcode 会 区分两种情况:

  • insufficient_scope — key 从未拥有该 capability。
  • tier_capability_not_allowed — key 曾经拥有,但 current tier 已不再允许。升级 plan 即可恢复。

stored key 中空的 allowed_products 表示所有产品(不是 没有产品)。tier 仍会将该 superset 收窄到 plan 允许的范围。

vendor — 有意请求,并且只在真正需要的地方使用

vendor 不是 route gate。它不决定 request 是否被允许;它决定 AI chat 在回答时是否可以查询您组织上传的 vendor data。 其他所有 scope 回答的是“这个 key 能否调用这个 endpoint”;vendor 回答的是“这个 key 能否代表我们的内部数据进行回答”。

因此它绝不会默认包含 — 请在 mint 时明确请求:

{ "name": "our-site-widget", "scopes": ["ai", "vendor"] }

哪个 key 携带 vendor,本身就是整个安全决策。 chat embed 是 browser widget:它会将 publishable key 交换为短期 session,因此 vendor-enabled key 必然存在于 public page 中。对于愿意展示给每位访客的数据, 例如 property list、营业时间、公开 rate,这是可以接受的。 对于任何不愿公开的信息则不合适。保护 exchange 的 origin allowlist 是 browser convention,而不是 confidentiality boundary: 能够自行设置 Origin header 的 caller 不会被它阻止。

因此:

  • 每个 surface 使用一个 key。 Marketing site、demo page 和 customer-facing app 不应共享同一个 key。只有必须基于您数据回答的 surface 才获得 vendor
  • 绝不要把 rate sheet、cost basis 或任何未公开信息放在 publishable key 后面。 如果某个回答出现在 public page 上会让您感到不合适,那么该数据就不应放入 vendor-scoped embed。
  • Session 会被限制到其 product,因此即使 parent key 持有 vendortileviewer session 也绝不会携带 vendor

如需撤销,请编辑 key 的 scopes 或 revoke 它 — 两者都会在 下一个 request 立即生效,包括已经运行中的 session。撤销不会 延迟到 session expiry。

401 与 403

二者有意区分:

  • 401 Unauthorized — key 缺失 / 无效 / revoked / expired。重新检查 key 值并确认未被 revoke。还包括 publishable key 被作为 raw bearer 发送时的 publishable_requires_session
  • 403 Forbidden — key 存在,但在此处不被允许。常见 subcodes:insufficient_scope(从未拥有)、tier_capability_not_allowed (曾经拥有,但 tier 已不再允许)、session_origin_mismatchip_not_allowed(server keys)、server_key_in_browserproduct_not_allowed

二者都采用 fail closed:没有 scopes 的 key 在任何地方都会被拒绝。

Session tokens

SDK 用 publishable key 交换得到的 session 类似:

kld_sess_{env}_{jwt}

例如 kld_sess_live_eyJhbGciOi…。runtime call 中通过 Authorization: BearerX-Api-Key 提交。默认 TTL 为 900 秒(15 分钟); server 最大值为 30 分钟。session 会被限制到 mint 时对应的 product, 每个 request 都会重新读取 parent key 的 live policy。

撤销是立即生效的;新增 grant 则不是。 两个方向有意 不对称,并采用 fail closed:

Change to the parent keyEffect on a session already in flight
Revoked or deleted下一个 request 即被拒绝
A scope removed下一个 request 即消失
Plan downgradedtier-gated capability 在下一个 request 被拒绝
Rate limit or monthly cap set to a new value下一个 request 即生效
A scope added, plan upgraded, or a limit lifted entirely不可见 — 需要 mint 新 session

session 只能相对其 parent 收窄权限,绝不能扩展到超过其 mint 时拥有的 scopes, 因此新的 grant 需要新的 exchange。session 很短(默认 15 分钟),正是为了让 这个间隔尽可能小。

完整 status table 请参阅 Errors