# 副脑中转站 Gateway API Canonical origin: https://api.funaokeji.com Canonical OpenAPI: https://api.funaokeji.com/openapi.json Human docs: https://api.funaokeji.com/docs Identity: immutable OneAuth subject + verified mainland-China phone; a supplied recovery email remains pending until separately verified. Isolation: Gateway project, credits, orders, usage, ledger, business keys, and project-derived shopping metadata are tenant isolated. Pricing: CNY; 100..1000000 fen in 100-fen steps; 10 credits per yuan; 1 credit = CNY 0.10. Charging: billable operations reserve before forwarding, settle confirmed success, release confirmed failure, and retain uncertain outcomes as manual_review. Never blindly retry manual_review. Operation price index: - POST /v1/agent/run | operation=agent.run | scope=agent:run | credits=5 | CNY=0.50 - POST /v1/models/chat | operation=model.chat | scope=models:invoke | credits=3 | CNY=0.30 - POST /v1/shopping/search | operation=shopping.search | scope=shopping:search | credits=2 | CNY=0.20 - POST /v1/zhentiao/compare | operation=zhentiao.compare | scope=zhentiao:read | credits=3 | CNY=0.30 - POST /v1/zhentiao/filter | operation=zhentiao.filter | scope=zhentiao:read | credits=2 | CNY=0.20 - POST /v1/zhentiao/links | operation=zhentiao.links | scope=zhentiao:link | credits=1 | CNY=0.10 - POST /v1/zhentiao/prepurchase-review | operation=zhentiao.prepurchase_review | scope=zhentiao:read | credits=1 | CNY=0.10 - POST /v1/zhentiao/recommend | operation=zhentiao.recommend | scope=zhentiao:read | credits=3 | CNY=0.30 - POST /v1/zhentiao/search | operation=zhentiao.search | scope=zhentiao:read | credits=2 | CNY=0.20 ## POST /v1/auth/send-code | requestGatewaySmsCode Summary: 请求 Gateway 短信验证码 Purpose: 为大陆手机号创建一次性 6 位验证 challenge;响应绝不回显验证码。 When: 注册前或重新验证手机号时调用;先保存 challengeId,再等待用户持有的短信码。 Authentication: 无需登录;浏览器必须满足精确同源校验。 Origin: 浏览器写请求只接受当前 Gateway 精确 Origin;不得跨域调用。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Origin | required=true | example=https://api.funaokeji.com | 必须与当前 Gateway origin 精确一致。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Origin | string | 必填 | {"const":"https://api.funaokeji.com","format":"uri"} | 浏览器写请求必须精确等于当前 Gateway origin;canonical 为 https://api.funaokeji.com。 Request fields: - phone | string | 必填 | {"pattern":"^1[3-9][0-9]{9}$"} | 中国大陆手机号,格式为 1[3-9] 后接 9 位数字。 Request example: {"phone":"13800000000"} Success: HTTP 202 | Success Success example: {"challengeId":"gvc_example","expiresInSeconds":300,"resendAfterSeconds":60} Success fields: - challengeId | string | 必填 | {"pattern":"^gvc_[A-Za-z0-9]+$"} | 短信验证 challenge 标识,绑定手机号、过期时间与单次消费状态。 - expiresInSeconds | integer | 必填 | {"const":300} | challenge 自创建起的有效秒数。 - resendAfterSeconds | integer | 必填 | {"const":60} | 再次申请短信 challenge 前的最短等待秒数。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 403 ORIGIN_INVALID | 浏览器 Origin 不是当前 Gateway 精确 Origin。 | retry=回到 canonical Gateway 页面重新发起。 - HTTP 400 PHONE_INVALID | 手机号或 JSON 字段无效。 | retry=修正后重试。 - HTTP 429 RATE_LIMITED | 请求方或手机号仍在限流/重发冷却窗口。 | retry=等待窗口后再请求。 - HTTP 503 SMS_DELIVERY_UNAVAILABLE | 短信适配器未启用或投递失败,challenge 已失效。 | retry=稍后重新申请新 challenge。 - HTTP 408 REQUEST_TIMEOUT | 请求体未在截止时间内读完。 | retry=可在确认服务可达后使用新请求重试。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体超过服务端上限。 | retry=缩小请求体后再发;原样重试无效。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host;不要自动跟随未知跳转。 Retry: 只有明确投递失败或超时后才申请新 challenge;旧 challenge 可能已失效。 Idempotency: 不使用 Idempotency-Key;重发会使旧 challenge 失效。 Runtime boundary: 真实短信送达与生产 OneAuth 为 NOT_RUN;本地 fake SMS 仅验收 seam。 ## POST /v1/auth/register | registerGatewayAccount Summary: 验证短信并创建 Gateway 账户 Purpose: 原子消费 challenge,创建 OneAuth 映射、Gateway account、personal project 与登录会话。 When: 用户已收到短信码并同意创建 Gateway 独立项目时调用;恢复邮箱初始保持待验证。 Authentication: 无需登录;浏览器必须满足精确同源校验。 Origin: 浏览器写请求只接受当前 Gateway 精确 Origin;不得跨域调用。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Origin | required=true | example=https://api.funaokeji.com | 必须与当前 Gateway origin 精确一致。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Origin | string | 必填 | {"const":"https://api.funaokeji.com","format":"uri"} | 浏览器写请求必须精确等于当前 Gateway origin;canonical 为 https://api.funaokeji.com。 Request fields: - phone | string | 必填 | {"pattern":"^1[3-9][0-9]{9}$"} | 中国大陆手机号,格式为 1[3-9] 后接 9 位数字。 - verificationCode | string | 必填 | {"pattern":"^[0-9]{6}$"} | 用户持有的 6 位短信验证码;不得记录或回显。 - challengeId | string | 必填 | {"pattern":"^gvc_[A-Za-z0-9]+$"} | 短信验证 challenge 标识,绑定手机号、过期时间与单次消费状态。 - recoveryEmail | string | 必填 | {"format":"email","maxLength":254} | Stored as pending and cannot authenticate or reserve the address until separately verified. - password | string | 必填 | {"format":"password","maxLength":128,"minLength":12} | 用户持有的 12–128 字符密码;服务端只保存 scrypt 摘要。 - next | string | 可选 | {"enum":["/console"]} | 成功认证后的 allowlisted Gateway 控制台路径。 Request example: {"challengeId":"gvc_example","next":"/console","password":"<12-128-character-password>","phone":"13800000000","recoveryEmail":"person@example.invalid","verificationCode":"<6位短信验证码>"} Success: HTTP 201 | Success Success example: {"account":{"accountId":"acct_example","oneAuthSubject":"oneauth_subject_example","phoneMasked":"138****0000","recoveryEmailMasked":"p***@example.invalid","recoveryEmailState":"pending_verification"},"csrfToken":"","project":{"projectId":"proj_example"},"redirectTo":"/console","session":{"expiresAt":"2026-09-03T12:00:00+00:00"}} Success fields: - account | object | 必填 | {"additionalProperties":false} | 当前 Gateway 账户;只包含脱敏身份和公开账户字段。 - account.accountId | string | 必填 | 无附加约束 | 服务端生成的 Gateway 账户标识。 - account.oneAuthSubject | string | 必填 | 无附加约束 | 已验证身份对应的不可变 OneAuth subject。 - account.phoneMasked | string | 必填 | 无附加约束 | 脱敏手机号;不可用于认证。 - account.recoveryEmailMasked | string | 必填 | 无附加约束 | 脱敏恢复邮箱;不可用于认证。 - account.recoveryEmailState | string | 必填 | {"enum":["pending_verification","verified"]} | 恢复邮箱处于 pending_verification 或 verified。 - project | object | 必填 | {"additionalProperties":false} | 当前 Gateway personal project;credits、订单、Key 与缓存均按此隔离。 - project.projectId | string | 必填 | 无附加约束 | 服务端从认证主体取得的项目标识;不得由业务请求体覆盖。 - session | object | 必填 | {"additionalProperties":false} | 当前 Gateway 会话公开元数据,不含 Cookie 明文。 - session.expiresAt | string | 必填 | {"format":"date-time"} | 资源或会话过期时间;永久资源可为 null。 - csrfToken | string | 必填 | 无附加约束 | 当前 Cookie 会话绑定的 CSRF token;只用于同源写请求。 - redirectTo | string | 必填 | {"enum":["/console","/gateway/console"]} | 服务端确认的认证后 Gateway 控制台路径。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 403 ORIGIN_INVALID | 浏览器 Origin 不是当前 Gateway 精确 Origin。 | retry=回到 canonical Gateway 页面重新发起。 - HTTP 400 VERIFICATION_FAILED | challenge、验证码、手机号、邮箱、密码或 next 无效。 | retry=重新核对;challenge 失效时先申请新码。 - HTTP 409 ACCOUNT_ALREADY_EXISTS | 该已验证身份已存在 Gateway 账户。 | retry=改走登录或官方恢复。 - HTTP 409 ACCOUNT_UNAVAILABLE | 账户创建与唯一约束发生冲突。 | retry=先尝试登录确认状态,再走官方恢复。 - HTTP 429 RATE_LIMITED | 注册尝试超过固定窗口。 | retry=等待窗口后再试。 - HTTP 408 REQUEST_TIMEOUT | 请求体未在截止时间内读完。 | retry=可在确认服务可达后使用新请求重试。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体超过服务端上限。 | retry=缩小请求体后再发;原样重试无效。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host;不要自动跟随未知跳转。 - HTTP 400 PHONE_INVALID | phone 不是有效的中国大陆手机号。 | retry=修正手机号后申请或使用对应 challenge。 - HTTP 400 EMAIL_INVALID | recoveryEmail 格式无效。 | retry=提供有效邮箱格式;该邮箱仍需另行验证。 - HTTP 400 PASSWORD_INVALID | password 长度不在 12 到 128 个字符。 | retry=设置符合长度要求的新密码。 - HTTP 400 NEXT_PATH_INVALID | next 不在 Gateway 页面白名单。 | retry=省略 next 或使用公开允许的站内路径。 - HTTP 409 VERIFICATION_CONFLICT | challenge 在原子消费时发生并发状态变化。 | retry=先尝试登录确认结果;不要重复消费同一验证码。 Retry: 不要盲目重复验证码消费;收到不确定网络错误时先尝试登录确认状态。 Idempotency: 不使用 Idempotency-Key;challenge 只能成功消费一次。 Runtime boundary: 生产 OneAuth、真实短信与正式账户迁移为 NOT_RUN。 ## POST /v1/auth/login | loginGatewayAccount Summary: 登录 Gateway 并轮换会话 Purpose: 使用已验证手机号或已单独验证的恢复邮箱登录,并签发新 HttpOnly 会话。 When: 已有 Gateway 账户且需要进入控制台或刷新失效会话时调用。 Authentication: 无需登录;浏览器必须满足精确同源校验。 Origin: 浏览器写请求只接受当前 Gateway 精确 Origin;不得跨域调用。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Origin | required=true | example=https://api.funaokeji.com | 必须与当前 Gateway origin 精确一致。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Origin | string | 必填 | {"const":"https://api.funaokeji.com","format":"uri"} | 浏览器写请求必须精确等于当前 Gateway origin;canonical 为 https://api.funaokeji.com。 Request fields: - identifier | string | 必填 | 无附加约束 | Verified mainland-China phone or verified recovery email - password | string | 必填 | {"format":"password","maxLength":128,"minLength":12} | 用户持有的 12–128 字符密码;服务端只保存 scrypt 摘要。 - next | string | 可选 | {"enum":["/console"]} | 成功认证后的 allowlisted Gateway 控制台路径。 Request example: {"identifier":"13800000000","next":"/console","password":"<12-128-character-password>"} Success: HTTP 200 | Success Success example: {"account":{"accountId":"acct_example","oneAuthSubject":"oneauth_subject_example","phoneMasked":"138****0000","recoveryEmailMasked":"p***@example.invalid","recoveryEmailState":"pending_verification"},"csrfToken":"","project":{"projectId":"proj_example"},"redirectTo":"/console","session":{"expiresAt":"2026-09-03T12:00:00+00:00"}} Success fields: - account | object | 必填 | {"additionalProperties":false} | 当前 Gateway 账户;只包含脱敏身份和公开账户字段。 - account.accountId | string | 必填 | 无附加约束 | 服务端生成的 Gateway 账户标识。 - account.oneAuthSubject | string | 必填 | 无附加约束 | 已验证身份对应的不可变 OneAuth subject。 - account.phoneMasked | string | 必填 | 无附加约束 | 脱敏手机号;不可用于认证。 - account.recoveryEmailMasked | string | 必填 | 无附加约束 | 脱敏恢复邮箱;不可用于认证。 - account.recoveryEmailState | string | 必填 | {"enum":["pending_verification","verified"]} | 恢复邮箱处于 pending_verification 或 verified。 - project | object | 必填 | {"additionalProperties":false} | 当前 Gateway personal project;credits、订单、Key 与缓存均按此隔离。 - project.projectId | string | 必填 | 无附加约束 | 服务端从认证主体取得的项目标识;不得由业务请求体覆盖。 - session | object | 必填 | {"additionalProperties":false} | 当前 Gateway 会话公开元数据,不含 Cookie 明文。 - session.expiresAt | string | 必填 | {"format":"date-time"} | 资源或会话过期时间;永久资源可为 null。 - csrfToken | string | 必填 | 无附加约束 | 当前 Cookie 会话绑定的 CSRF token;只用于同源写请求。 - redirectTo | string | 必填 | {"enum":["/console","/gateway/console"]} | 服务端确认的认证后 Gateway 控制台路径。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 403 ORIGIN_INVALID | 浏览器 Origin 不是当前 Gateway 精确 Origin。 | retry=回到 canonical Gateway 页面重新发起。 - HTTP 400 IDENTIFIER_INVALID | identifier、密码格式、next 或字段合同无效。 | retry=修正格式后重试。 - HTTP 401 AUTHENTICATION_FAILED | 未知/待验证身份与错误密码统一失败。 | retry=使用官方恢复;不要枚举账户。 - HTTP 429 RATE_LIMITED | 登录尝试超过固定窗口。 | retry=等待窗口后再试。 - HTTP 408 REQUEST_TIMEOUT | 请求体未在截止时间内读完。 | retry=可在确认服务可达后使用新请求重试。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体超过服务端上限。 | retry=缩小请求体后再发;原样重试无效。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host;不要自动跟随未知跳转。 - HTTP 400 PASSWORD_INVALID | password 长度不在 12 到 128 个字符。 | retry=修正密码格式后重试。 - HTTP 400 NEXT_PATH_INVALID | next 不在 Gateway 页面白名单。 | retry=省略 next 或使用公开允许的站内路径。 - HTTP 500 PASSWORD_STATE_INVALID | 账户密码摘要参数或存储状态无效。 | retry=停止重试并由运维修复账户状态。 Retry: 401 不区分身份是否存在;只在用户明确操作后重试。 Idempotency: 不使用 Idempotency-Key;成功登录会轮换会话。 Runtime boundary: 正式生产身份系统为 NOT_RUN。 ## POST /v1/auth/logout | logoutGatewayAccount Summary: 撤销当前 Gateway 会话 Purpose: 使当前服务端会话失效并清理浏览器 Cookie。 When: 用户主动退出或怀疑会话泄露时调用。 Authentication: 需要有效会话 Cookie、精确 Origin 与 session-bound CSRF。 Origin: 浏览器写请求只接受当前 Gateway 精确 Origin;不得跨域调用。 CSRF: 必需,且必须绑定当前 Cookie 会话。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Origin | required=true | example=https://api.funaokeji.com | 必须与当前 Gateway origin 精确一致。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 - Cookie | required=true | example=funao_gateway_session= | HttpOnly Gateway 会话 Cookie;不要写入日志或脚本存储。 - X-CSRF-Token | required=true | example= | 从当前会话响应取得并与 Cookie 会话绑定。 Parameters: - X-CSRF-Token | string | 必填 | {"minLength":10} | 当前 Gateway 会话绑定的 CSRF token;从登录/注册或最新 /v1/me 响应取得。 - Origin | string | 必填 | {"const":"https://api.funaokeji.com","format":"uri"} | 浏览器写请求必须精确等于当前 Gateway origin;canonical 为 https://api.funaokeji.com。 Request fields: Request example: {} Success: HTTP 200 | Success Success example: {"state":"logged_out"} Success fields: - state | string | 必填 | {"const":"logged_out"} | 资源、订单、Key 或业务扣费当前状态。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 403 ORIGIN_INVALID | 浏览器 Origin 不是当前 Gateway 精确 Origin。 | retry=回到 canonical Gateway 页面重新发起。 - HTTP 401 GATEWAY_AUTH_REQUIRED | 会话缺失或已失效。 | retry=视为已退出;无需循环重试。 - HTTP 403 CSRF_INVALID | Origin 或 CSRF 不匹配当前会话。 | retry=刷新会话上下文后重试一次。 - HTTP 429 RATE_LIMITED | 会话写操作限流。 | retry=等待窗口后重试。 - HTTP 408 REQUEST_TIMEOUT | 请求体未在截止时间内读完。 | retry=可在确认服务可达后使用新请求重试。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体超过服务端上限。 | retry=缩小请求体后再发;原样重试无效。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host;不要自动跟随未知跳转。 Retry: 成功或明确 401 后客户端都应丢弃本地会话界面状态。 Idempotency: 不使用 Idempotency-Key;重复登出可能返回 401,但不会扣费。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## GET /v1/pricing | getGatewayPricing Summary: 读取 Gateway canonical 价格 Purpose: 返回自定义充值范围、¥1=10 credits、9 类业务操作固定价格与扣费策略。 When: 生成客户端价格展示或调用前预算时读取;不要硬编码另一份价格表。 Authentication: 无需登录;仅公开读取。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 Request body: none Success: HTTP 200 | Canonical pricing Success example: {"amountUnit":"fen","chargePolicy":{"idempotencyConflict":"Reusing an Idempotency-Key for a different request returns HTTP 409.","idempotentReplay":"The same Idempotency-Key and request fingerprint replays the stored result without a second charge.","insufficientCredits":"Insufficient available credits returns HTTP 402 before provider forwarding.","manualReview":"An uncertain forwarding outcome stays reserved for manual review; automatic retry is disabled.","release":"A confirmed pre-forward or adapter failure releases the reservation.","reserve":"Before forwarding, the fixed operation credits are reserved from the current Gateway project.","settle":"A confirmed provider result settles the reservation exactly once."},"creditsPerYuan":10,"currency":"CNY","maxAmountFen":1000000,"minAmountFen":100,"operations":[{"cnyFen":50,"cnyYuan":"0.50","credits":5,"operation":"agent.run","path":"/v1/agent/run","scope":"agent:run"},{"cnyFen":30,"cnyYuan":"0.30","credits":3,"operation":"model.chat","path":"/v1/models/chat","scope":"models:invoke"},{"cnyFen":20,"cnyYuan":"0.20","credits":2,"operation":"shopping.search","path":"/v1/shopping/search","scope":"shopping:search"},{"cnyFen":30,"cnyYuan":"0.30","credits":3,"operation":"zhentiao.compare","path":"/v1/zhentiao/compare","scope":"zhentiao:read"},{"cnyFen":20,"cnyYuan":"0.20","credits":2,"operation":"zhentiao.filter","path":"/v1/zhentiao/filter","scope":"zhentiao:read"},{"cnyFen":10,"cnyYuan":"0.10","credits":1,"operation":"zhentiao.links","path":"/v1/zhentiao/links","scope":"zhentiao:link"},{"cnyFen":10,"cnyYuan":"0.10","credits":1,"operation":"zhentiao.prepurchase_review","path":"/v1/zhentiao/prepurchase-review","scope":"zhentiao:read"},{"cnyFen":30,"cnyYuan":"0.30","credits":3,"operation":"zhentiao.recommend","path":"/v1/zhentiao/recommend","scope":"zhentiao:read"},{"cnyFen":20,"cnyYuan":"0.20","credits":2,"operation":"zhentiao.search","path":"/v1/zhentiao/search","scope":"zhentiao:read"}],"paymentMode":"local-simulated","pricingVersion":"gateway-custom-cny-10credits-v1","productionPayment":"NOT_RUN","stepAmountFen":100,"yuanPerCredit":"0.10"} Success fields: - currency | string | 必填 | {"const":"CNY"} | 价格币种;当前固定为 CNY。 - amountUnit | string | 必填 | {"const":"fen"} | amountUnit 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - minAmountFen | integer | 必填 | {"const":100} | 允许创建订单的最小人民币分金额。 - maxAmountFen | integer | 必填 | {"const":1000000} | 允许创建订单的最大人民币分金额。 - stepAmountFen | integer | 必填 | {"const":100} | 充值金额允许的人民币分步长。 - creditsPerYuan | integer | 必填 | {"const":10} | 服务端价格版本规定的每人民币元 credits 数。 - yuanPerCredit | string | 必填 | {"const":"0.10"} | 按当前本地价格规则折算的每 credit 人民币元字符串。 - pricingVersion | string | 必填 | {"const":"gateway-custom-cny-10credits-v1"} | 服务端订单价格快照版本。 - paymentMode | string | 必填 | {"enum":["disabled","local-simulated"]} | 当前充值能力模式;local-simulated 不是真实支付。 - productionPayment | string | 必填 | {"const":"NOT_RUN"} | 真实支付运行状态;当前明确为 NOT_RUN。 - operations | array | 必填 | {"maxItems":9,"minItems":9} | 9 个可计费业务操作及固定价格列表。 - operations[].operation | string | 必填 | 无附加约束 | 固定业务操作标识。 - operations[].path | string | 必填 | 无附加约束 | 公开 canonical API 路径。 - operations[].scope | string | 必填 | 无附加约束 | 调用业务操作所需的最小 Key scope。 - operations[].credits | integer | 必填 | {"enum":[1,2,3,5]} | 业务操作扣费数量,或账户可用/预留 credits 结构。 - operations[].cnyFen | integer | 必填 | {"enum":[10,20,30,50]} | cnyFen 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - operations[].cnyYuan | string | 必填 | {"enum":["0.10","0.20","0.30","0.50"]} | cnyYuan 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - chargePolicy | object | 必填 | {"additionalProperties":{"description":"chargePolicyValue 的公开合同字段;类型、必填性与取值限制以本 schema 为准。","type":"string"}} | reserve、settle、release、manual_review 与幂等重放规则。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 500 INTERNAL_ERROR | 服务端未能生成公开响应。 | retry=指数退避;不要携带或记录秘密。 Retry: 安全 GET 可指数退避重试。 Idempotency: 不需要 Idempotency-Key。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## GET /v1/plans | getDeprecatedGatewayPlansAlias Summary: 读取已弃用价格兼容别名 Purpose: 为旧客户端返回 deprecated 标记与 canonical /v1/pricing 内容;不存在固定套餐。 When: 仅迁移旧客户端时使用;新实现直接调用 /v1/pricing。 Authentication: 无需登录;仅公开读取。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 Request body: none Success: HTTP 200 | Deprecated alias Success example: {"canonical":"/v1/pricing","deprecated":true,"pricing":{"amountUnit":"fen","chargePolicy":{"idempotencyConflict":"Reusing an Idempotency-Key for a different request returns HTTP 409.","idempotentReplay":"The same Idempotency-Key and request fingerprint replays the stored result without a second charge.","insufficientCredits":"Insufficient available credits returns HTTP 402 before provider forwarding.","manualReview":"An uncertain forwarding outcome stays reserved for manual review; automatic retry is disabled.","release":"A confirmed pre-forward or adapter failure releases the reservation.","reserve":"Before forwarding, the fixed operation credits are reserved from the current Gateway project.","settle":"A confirmed provider result settles the reservation exactly once."},"creditsPerYuan":10,"currency":"CNY","maxAmountFen":1000000,"minAmountFen":100,"operations":[{"cnyFen":50,"cnyYuan":"0.50","credits":5,"operation":"agent.run","path":"/v1/agent/run","scope":"agent:run"},{"cnyFen":30,"cnyYuan":"0.30","credits":3,"operation":"model.chat","path":"/v1/models/chat","scope":"models:invoke"},{"cnyFen":20,"cnyYuan":"0.20","credits":2,"operation":"shopping.search","path":"/v1/shopping/search","scope":"shopping:search"},{"cnyFen":30,"cnyYuan":"0.30","credits":3,"operation":"zhentiao.compare","path":"/v1/zhentiao/compare","scope":"zhentiao:read"},{"cnyFen":20,"cnyYuan":"0.20","credits":2,"operation":"zhentiao.filter","path":"/v1/zhentiao/filter","scope":"zhentiao:read"},{"cnyFen":10,"cnyYuan":"0.10","credits":1,"operation":"zhentiao.links","path":"/v1/zhentiao/links","scope":"zhentiao:link"},{"cnyFen":10,"cnyYuan":"0.10","credits":1,"operation":"zhentiao.prepurchase_review","path":"/v1/zhentiao/prepurchase-review","scope":"zhentiao:read"},{"cnyFen":30,"cnyYuan":"0.30","credits":3,"operation":"zhentiao.recommend","path":"/v1/zhentiao/recommend","scope":"zhentiao:read"},{"cnyFen":20,"cnyYuan":"0.20","credits":2,"operation":"zhentiao.search","path":"/v1/zhentiao/search","scope":"zhentiao:read"}],"paymentMode":"local-simulated","pricingVersion":"gateway-custom-cny-10credits-v1","productionPayment":"NOT_RUN","stepAmountFen":100,"yuanPerCredit":"0.10"}} Success fields: - deprecated | boolean | 必填 | {"const":true} | 是否为只保留兼容性的旧入口。 - canonical | string | 必填 | {"enum":["/v1/pricing","/gateway/api/pricing"]} | canonical 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - pricing | object | 必填 | {"additionalProperties":false} | canonical Gateway 价格合同。 - pricing.currency | string | 必填 | {"const":"CNY"} | 价格币种;当前固定为 CNY。 - pricing.amountUnit | string | 必填 | {"const":"fen"} | amountUnit 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - pricing.minAmountFen | integer | 必填 | {"const":100} | 允许创建订单的最小人民币分金额。 - pricing.maxAmountFen | integer | 必填 | {"const":1000000} | 允许创建订单的最大人民币分金额。 - pricing.stepAmountFen | integer | 必填 | {"const":100} | 充值金额允许的人民币分步长。 - pricing.creditsPerYuan | integer | 必填 | {"const":10} | 服务端价格版本规定的每人民币元 credits 数。 - pricing.yuanPerCredit | string | 必填 | {"const":"0.10"} | 按当前本地价格规则折算的每 credit 人民币元字符串。 - pricing.pricingVersion | string | 必填 | {"const":"gateway-custom-cny-10credits-v1"} | 服务端订单价格快照版本。 - pricing.paymentMode | string | 必填 | {"enum":["disabled","local-simulated"]} | 当前充值能力模式;local-simulated 不是真实支付。 - pricing.productionPayment | string | 必填 | {"const":"NOT_RUN"} | 真实支付运行状态;当前明确为 NOT_RUN。 - pricing.operations | array | 必填 | {"maxItems":9,"minItems":9} | 9 个可计费业务操作及固定价格列表。 - pricing.operations[].operation | string | 必填 | 无附加约束 | 固定业务操作标识。 - pricing.operations[].path | string | 必填 | 无附加约束 | 公开 canonical API 路径。 - pricing.operations[].scope | string | 必填 | 无附加约束 | 调用业务操作所需的最小 Key scope。 - pricing.operations[].credits | integer | 必填 | {"enum":[1,2,3,5]} | 业务操作扣费数量,或账户可用/预留 credits 结构。 - pricing.operations[].cnyFen | integer | 必填 | {"enum":[10,20,30,50]} | cnyFen 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - pricing.operations[].cnyYuan | string | 必填 | {"enum":["0.10","0.20","0.30","0.50"]} | cnyYuan 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - pricing.chargePolicy | object | 必填 | {"additionalProperties":{"description":"chargePolicyValue 的公开合同字段;类型、必填性与取值限制以本 schema 为准。","type":"string"}} | reserve、settle、release、manual_review 与幂等重放规则。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 500 INTERNAL_ERROR | 服务端未能生成公开响应。 | retry=指数退避;不要携带或记录秘密。 Retry: 安全 GET 可重试,但应尽快迁移 canonical 路径。 Idempotency: 不需要 Idempotency-Key。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## GET /v1/me | getGatewayAccount Summary: 读取当前 Gateway 项目摘要 Purpose: 返回 masked identity、当前 personal project、credits、订单、Key 元数据、会话与新 CSRF。 When: 控制台启动、刷新余额或取得当前 CSRF 时调用。 Authentication: 需要有效 Gateway HttpOnly 会话 Cookie。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Cookie | required=true | example=funao_gateway_session= | HttpOnly Gateway 会话 Cookie;不要写入日志或脚本存储。 Request body: none Success: HTTP 200 | Current account Success example: {"account":{"accountId":"acct_example","name":"个人 Gateway 账户","oneAuthSubject":"oneauth_subject_example","phoneMasked":"138****0000","recoveryEmailMasked":"p***@example.invalid","recoveryEmailState":"pending_verification"},"apiKeys":[],"credits":{"available":230,"reserved":0},"csrfToken":"","latestOrder":null,"project":{"name":"个人项目","projectId":"proj_example"},"recentOrders":[],"session":{"expiresAt":"2026-09-03T12:00:00+00:00"}} Success fields: - account | object | 必填 | {"additionalProperties":false} | 当前 Gateway 账户;只包含脱敏身份和公开账户字段。 - account.accountId | string | 必填 | 无附加约束 | 服务端生成的 Gateway 账户标识。 - account.name | string | 必填 | 无附加约束 | 当前 Gateway 账户或项目的显示名称。 - account.oneAuthSubject | string | 必填 | 无附加约束 | 已验证身份对应的不可变 OneAuth subject。 - account.phoneMasked | string | 必填 | 无附加约束 | 脱敏手机号;不可用于认证。 - account.recoveryEmailMasked | string | 必填 | 无附加约束 | 脱敏恢复邮箱;不可用于认证。 - account.recoveryEmailState | string | 必填 | {"enum":["pending_verification","verified"]} | 恢复邮箱处于 pending_verification 或 verified。 - project | object | 必填 | {"additionalProperties":false} | 当前 Gateway personal project;credits、订单、Key 与缓存均按此隔离。 - project.projectId | string | 必填 | 无附加约束 | 服务端从认证主体取得的项目标识;不得由业务请求体覆盖。 - project.name | string | 必填 | 无附加约束 | 当前 Gateway 账户或项目的显示名称。 - credits | object | 必填 | {"additionalProperties":false} | 业务操作扣费数量,或账户可用/预留 credits 结构。 - credits.available | integer | 必填 | {"minimum":0} | available 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - credits.reserved | integer | 必填 | {"minimum":0} | reserved 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - latestOrder | object | null | 必填 | 无附加约束 | 当前项目最近订单;没有订单时为 null。 - latestOrder.orderId | string | 必填 | 无附加约束 | 当前项目所属充值订单标识。 - latestOrder.amountFen | integer | 必填 | {"maximum":1000000,"minimum":100} | 充值金额,单位为人民币分;必须是整数元范围内的 100 倍数。 - latestOrder.creditAmount | integer | 必填 | {"maximum":100000,"minimum":10} | 按服务端价格快照计算的 credits 数量。 - latestOrder.currency | string | 必填 | {"const":"CNY"} | 价格币种;当前固定为 CNY。 - latestOrder.creditsPerYuan | integer | 必填 | {"const":10} | 服务端价格版本规定的每人民币元 credits 数。 - latestOrder.yuanPerCredit | string | 必填 | {"const":"0.10"} | 按当前本地价格规则折算的每 credit 人民币元字符串。 - latestOrder.pricingVersion | string | 必填 | {"const":"gateway-custom-cny-10credits-v1"} | 服务端订单价格快照版本。 - latestOrder.state | string | 必填 | {"enum":["pending","simulated_paid","credited"]} | 资源、订单、Key 或业务扣费当前状态。 - latestOrder.paymentMode | string | 必填 | {"const":"local-simulated"} | 当前充值能力模式;local-simulated 不是真实支付。 - latestOrder.createdAt | string | 必填 | {"format":"date-time"} | 服务端创建时间,含时区的 ISO-8601 时间。 - latestOrder.simulatedPaidAt | string | null | 必填 | 无附加约束 | 本地模拟确认发生时间;未确认时为 null。 - latestOrder.creditedAt | string | null | 必填 | 无附加约束 | credits 实际入账时间;未入账时为 null。 - recentOrders | array | 必填 | 无附加约束 | 当前项目最近订单列表。 - recentOrders[].orderId | string | 必填 | 无附加约束 | 当前项目所属充值订单标识。 - recentOrders[].amountFen | integer | 必填 | {"maximum":1000000,"minimum":100} | 充值金额,单位为人民币分;必须是整数元范围内的 100 倍数。 - recentOrders[].creditAmount | integer | 必填 | {"maximum":100000,"minimum":10} | 按服务端价格快照计算的 credits 数量。 - recentOrders[].currency | string | 必填 | {"const":"CNY"} | 价格币种;当前固定为 CNY。 - recentOrders[].creditsPerYuan | integer | 必填 | {"const":10} | 服务端价格版本规定的每人民币元 credits 数。 - recentOrders[].yuanPerCredit | string | 必填 | {"const":"0.10"} | 按当前本地价格规则折算的每 credit 人民币元字符串。 - recentOrders[].pricingVersion | string | 必填 | {"const":"gateway-custom-cny-10credits-v1"} | 服务端订单价格快照版本。 - recentOrders[].state | string | 必填 | {"enum":["pending","simulated_paid","credited"]} | 资源、订单、Key 或业务扣费当前状态。 - recentOrders[].paymentMode | string | 必填 | {"const":"local-simulated"} | 当前充值能力模式;local-simulated 不是真实支付。 - recentOrders[].createdAt | string | 必填 | {"format":"date-time"} | 服务端创建时间,含时区的 ISO-8601 时间。 - recentOrders[].simulatedPaidAt | string | null | 必填 | 无附加约束 | 本地模拟确认发生时间;未确认时为 null。 - recentOrders[].creditedAt | string | null | 必填 | 无附加约束 | credits 实际入账时间;未入账时为 null。 - apiKeys | array | 必填 | 无附加约束 | 当前项目业务 Key 的元数据列表,不含明文 Key。 - apiKeys[].keyId | string | 必填 | 无附加约束 | 项目级业务 Key 元数据标识,不是明文 Key。 - apiKeys[].displayPrefix | string | 必填 | 无附加约束 | 业务 Key 的安全展示前缀与尾部摘要,不是可用凭证。 - apiKeys[].scopes | array | 必填 | {"minItems":1,"uniqueItems":true} | 业务 Key 被授予的固定 scope 集合。 - apiKeys[].state | string | 必填 | {"enum":["active","revoked","expired"]} | 资源、订单、Key 或业务扣费当前状态。 - apiKeys[].createdAt | string | 必填 | {"format":"date-time"} | 服务端创建时间,含时区的 ISO-8601 时间。 - apiKeys[].revokedAt | string | null | 必填 | 无附加约束 | 业务 Key 撤销时间;仍有效时为 null。 - apiKeys[].expiresAt | string | null | 必填 | 无附加约束 | 资源或会话过期时间;永久资源可为 null。 - apiKeys[].rotatedFromKeyId | string | null | 必填 | 无附加约束 | 轮换来源 Key 标识;非轮换创建时为 null。 - session | object | 必填 | {"additionalProperties":false} | 当前 Gateway 会话公开元数据,不含 Cookie 明文。 - session.expiresAt | string | 必填 | {"format":"date-time"} | 资源或会话过期时间;永久资源可为 null。 - csrfToken | string | 必填 | 无附加约束 | 当前 Cookie 会话绑定的 CSRF token;只用于同源写请求。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 401 GATEWAY_AUTH_REQUIRED | 会话缺失、失效、过期或已撤销。 | retry=重新登录后再读。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 500 INTERNAL_ERROR | 服务端未能生成公开响应。 | retry=指数退避;不要携带或记录秘密。 Retry: 安全 GET 可在重新登录后重试;每次成功响应都应替换旧 CSRF。 Idempotency: 不需要 Idempotency-Key。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## GET /v1/keys | listGatewayBusinessKeys Summary: 列出当前项目业务 Key 元数据 Purpose: 只返回 keyId、前缀、scope 与生命周期;永不返回历史明文 Key。 When: 审计、撤销或展示当前项目 Key 时调用。 Authentication: 需要有效 Gateway HttpOnly 会话 Cookie。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Cookie | required=true | example=funao_gateway_session= | HttpOnly Gateway 会话 Cookie;不要写入日志或脚本存储。 Request body: none Success: HTTP 200 | Key metadata Success example: {"items":[]} Success fields: - items | array | 必填 | 无附加约束 | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - items[].keyId | string | 必填 | 无附加约束 | 项目级业务 Key 元数据标识,不是明文 Key。 - items[].displayPrefix | string | 必填 | 无附加约束 | 业务 Key 的安全展示前缀与尾部摘要,不是可用凭证。 - items[].scopes | array | 必填 | {"minItems":1,"uniqueItems":true} | 业务 Key 被授予的固定 scope 集合。 - items[].state | string | 必填 | {"enum":["active","revoked","expired"]} | 资源、订单、Key 或业务扣费当前状态。 - items[].createdAt | string | 必填 | {"format":"date-time"} | 服务端创建时间,含时区的 ISO-8601 时间。 - items[].revokedAt | string | null | 必填 | 无附加约束 | 业务 Key 撤销时间;仍有效时为 null。 - items[].expiresAt | string | null | 必填 | 无附加约束 | 资源或会话过期时间;永久资源可为 null。 - items[].rotatedFromKeyId | string | null | 必填 | 无附加约束 | 轮换来源 Key 标识;非轮换创建时为 null。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 401 GATEWAY_AUTH_REQUIRED | 会话缺失、失效、过期或已撤销。 | retry=重新登录后再读。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 500 INTERNAL_ERROR | 服务端未能生成公开响应。 | retry=指数退避;不要携带或记录秘密。 Retry: 安全 GET 可在重新登录后重试。 Idempotency: 不需要 Idempotency-Key。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## POST /v1/keys | createGatewayBusinessKey Summary: 创建项目级业务 Key Purpose: 按最小 scope 创建 Key;明文仅在本次成功响应显示一次。 When: 需要新集成凭证或轮换旧 Key 时调用;调用方必须立即安全接收一次性明文。 Authentication: 需要有效会话 Cookie、精确 Origin 与 session-bound CSRF。 Origin: 浏览器写请求只接受当前 Gateway 精确 Origin;不得跨域调用。 CSRF: 必需,且必须绑定当前 Cookie 会话。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Origin | required=true | example=https://api.funaokeji.com | 必须与当前 Gateway origin 精确一致。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 - Cookie | required=true | example=funao_gateway_session= | HttpOnly Gateway 会话 Cookie;不要写入日志或脚本存储。 - X-CSRF-Token | required=true | example= | 从当前会话响应取得并与 Cookie 会话绑定。 Parameters: - X-CSRF-Token | string | 必填 | {"minLength":10} | 当前 Gateway 会话绑定的 CSRF token;从登录/注册或最新 /v1/me 响应取得。 - Origin | string | 必填 | {"const":"https://api.funaokeji.com","format":"uri"} | 浏览器写请求必须精确等于当前 Gateway origin;canonical 为 https://api.funaokeji.com。 Request fields: - scopes | array | 必填 | {"minItems":1,"uniqueItems":true} | 业务 Key 被授予的固定 scope 集合。 Request example: {"scopes":["models:invoke"]} Success: HTTP 201 | Success Success example: {"apiKey":"","displayPrefix":"fk_example...0000","expiresAt":null,"keyId":"key_example","rotatedFromKeyId":null,"scopes":["models:invoke"],"shownOnce":true,"state":"active"} Success fields: - keyId | string | 必填 | 无附加约束 | 项目级业务 Key 元数据标识,不是明文 Key。 - apiKey | string | 必填 | 无附加约束 | 新创建业务 Key 的一次性明文;响应后无法再次读取。 - displayPrefix | string | 必填 | 无附加约束 | 业务 Key 的安全展示前缀与尾部摘要,不是可用凭证。 - scopes | array | 必填 | {"minItems":1,"uniqueItems":true} | 业务 Key 被授予的固定 scope 集合。 - state | string | 必填 | {"const":"active"} | 资源、订单、Key 或业务扣费当前状态。 - expiresAt | string | null | 必填 | 无附加约束 | 资源或会话过期时间;永久资源可为 null。 - rotatedFromKeyId | string | null | 必填 | 无附加约束 | 轮换来源 Key 标识;非轮换创建时为 null。 - shownOnce | boolean | 必填 | {"const":true} | 业务 Key 明文是否仅在当前响应显示一次;固定为 true。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 403 ORIGIN_INVALID | 浏览器 Origin 不是当前 Gateway 精确 Origin。 | retry=回到 canonical Gateway 页面重新发起。 - HTTP 400 INVALID_SCOPE | scope 列表为空、重复、类型错误或不在允许列表。 | retry=选择最小有效 scope 后重试。 - HTTP 401 GATEWAY_AUTH_REQUIRED | 会话无效。 | retry=重新登录。 - HTTP 403 CSRF_INVALID | Origin 或 CSRF 不匹配。 | retry=刷新 /v1/me 后重试。 - HTTP 429 RATE_LIMITED | Key 创建进入限流窗口。 | retry=等待窗口后再试。 - HTTP 408 REQUEST_TIMEOUT | 请求体未在截止时间内读完。 | retry=可在确认服务可达后使用新请求重试。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体超过服务端上限。 | retry=缩小请求体后再发;原样重试无效。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host;不要自动跟随未知跳转。 Retry: 若一次性明文未被安全接收,撤销该 Key 并创建新 Key;不要请求回显。 Idempotency: 不使用 Idempotency-Key;每次成功会创建新 Key。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## POST /v1/keys/{keyId}/revoke | revokeGatewayBusinessKey Summary: 撤销当前项目业务 Key Purpose: 使指定 keyId 立即不可用于业务调用;跨项目资源统一不可见。 When: 凭证轮换、泄露处置或集成下线时调用。 Authentication: 需要有效会话 Cookie、精确 Origin 与 session-bound CSRF。 Origin: 浏览器写请求只接受当前 Gateway 精确 Origin;不得跨域调用。 CSRF: 必需,且必须绑定当前 Cookie 会话。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Origin | required=true | example=https://api.funaokeji.com | 必须与当前 Gateway origin 精确一致。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 - Cookie | required=true | example=funao_gateway_session= | HttpOnly Gateway 会话 Cookie;不要写入日志或脚本存储。 - X-CSRF-Token | required=true | example= | 从当前会话响应取得并与 Cookie 会话绑定。 Parameters: - keyId | string | 必填 | {"pattern":"^key_[A-Za-z0-9]+$"} | 当前 Gateway project 所属业务 Key 标识;不是明文凭证。 - X-CSRF-Token | string | 必填 | {"minLength":10} | 当前 Gateway 会话绑定的 CSRF token;从登录/注册或最新 /v1/me 响应取得。 - Origin | string | 必填 | {"const":"https://api.funaokeji.com","format":"uri"} | 浏览器写请求必须精确等于当前 Gateway origin;canonical 为 https://api.funaokeji.com。 Request fields: Request example: {} Success: HTTP 200 | Success Success example: {"keyId":"key_example","state":"revoked"} Success fields: - keyId | string | 必填 | 无附加约束 | 项目级业务 Key 元数据标识,不是明文 Key。 - state | string | 必填 | {"const":"revoked"} | 资源、订单、Key 或业务扣费当前状态。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 403 ORIGIN_INVALID | 浏览器 Origin 不是当前 Gateway 精确 Origin。 | retry=回到 canonical Gateway 页面重新发起。 - HTTP 401 GATEWAY_AUTH_REQUIRED | 会话无效。 | retry=重新登录。 - HTTP 403 CSRF_INVALID | Origin 或 CSRF 不匹配。 | retry=刷新 /v1/me 后重试。 - HTTP 404 KEY_NOT_FOUND | Key 不存在或不属于当前项目。 | retry=核对当前项目 Key 列表;不要跨 owner 探测。 - HTTP 429 RATE_LIMITED | Key 撤销进入限流窗口。 | retry=等待窗口后再试。 - HTTP 408 REQUEST_TIMEOUT | 请求体未在截止时间内读完。 | retry=可在确认服务可达后使用新请求重试。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体超过服务端上限。 | retry=缩小请求体后再发;原样重试无效。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host;不要自动跟随未知跳转。 Retry: 若网络结果不明,先重新列出 Key 状态;不要假设撤销失败。 Idempotency: 不使用 Idempotency-Key;已撤销资源不会恢复。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## POST /v1/orders | createGatewayRechargeOrder Summary: 创建自定义充值订单 Purpose: 按整数分金额固化 CNY、credits 汇率、价格版本与项目 owner 快照。 When: 用户确认充值金额后、进入显式模拟确认前调用。 Authentication: 需要有效会话 Cookie、精确 Origin、CSRF 与 Idempotency-Key。 Origin: 浏览器写请求只接受当前 Gateway 精确 Origin;不得跨域调用。 CSRF: 必需,且必须绑定当前 Cookie 会话。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Origin | required=true | example=https://api.funaokeji.com | 必须与当前 Gateway origin 精确一致。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 - Cookie | required=true | example=funao_gateway_session= | HttpOnly Gateway 会话 Cookie;不要写入日志或脚本存储。 - X-CSRF-Token | required=true | example= | 从当前会话响应取得并与 Cookie 会话绑定。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 Parameters: - X-CSRF-Token | string | 必填 | {"minLength":10} | 当前 Gateway 会话绑定的 CSRF token;从登录/注册或最新 /v1/me 响应取得。 - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 - Origin | string | 必填 | {"const":"https://api.funaokeji.com","format":"uri"} | 浏览器写请求必须精确等于当前 Gateway origin;canonical 为 https://api.funaokeji.com。 Request fields: - amountFen | integer | 必填 | {"maximum":1000000,"minimum":100,"multipleOf":100} | 充值金额,单位为人民币分;必须是整数元范围内的 100 倍数。 Request example: {"amountFen":2300} Success: HTTP 201 | Success Success example: {"amountFen":2300,"createdAt":"2026-09-03T04:00:00+00:00","creditAmount":230,"creditedAt":null,"creditsPerYuan":10,"currency":"CNY","idempotentReplay":false,"orderId":"ord_example","paymentMode":"local-simulated","pricingVersion":"gateway-custom-cny-10credits-v1","simulatedPaidAt":null,"state":"pending","yuanPerCredit":"0.10"} Success fields: - orderId | string | 必填 | 无附加约束 | 当前项目所属充值订单标识。 - amountFen | integer | 必填 | {"maximum":1000000,"minimum":100} | 充值金额,单位为人民币分;必须是整数元范围内的 100 倍数。 - creditAmount | integer | 必填 | {"maximum":100000,"minimum":10} | 按服务端价格快照计算的 credits 数量。 - currency | string | 必填 | {"const":"CNY"} | 价格币种;当前固定为 CNY。 - creditsPerYuan | integer | 必填 | {"const":10} | 服务端价格版本规定的每人民币元 credits 数。 - yuanPerCredit | string | 必填 | {"const":"0.10"} | 按当前本地价格规则折算的每 credit 人民币元字符串。 - pricingVersion | string | 必填 | {"const":"gateway-custom-cny-10credits-v1"} | 服务端订单价格快照版本。 - state | string | 必填 | {"enum":["pending","simulated_paid","credited"]} | 资源、订单、Key 或业务扣费当前状态。 - paymentMode | string | 必填 | {"const":"local-simulated"} | 当前充值能力模式;local-simulated 不是真实支付。 - createdAt | string | 必填 | {"format":"date-time"} | 服务端创建时间,含时区的 ISO-8601 时间。 - simulatedPaidAt | string | null | 必填 | 无附加约束 | 本地模拟确认发生时间;未确认时为 null。 - creditedAt | string | null | 必填 | 无附加约束 | credits 实际入账时间;未入账时为 null。 - idempotentReplay | boolean | 必填 | 无附加约束 | 是否为相同 owner、键与请求指纹的存储结果重放。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 403 ORIGIN_INVALID | 浏览器 Origin 不是当前 Gateway 精确 Origin。 | retry=回到 canonical Gateway 页面重新发起。 - HTTP 400 RECHARGE_AMOUNT_INVALID | amountFen 不是 100..1000000 范围内的 100 倍数,或幂等键缺失。 | retry=修正金额并使用新键。 - HTTP 401 GATEWAY_AUTH_REQUIRED | 会话无效。 | retry=重新登录。 - HTTP 403 CSRF_INVALID | Origin 或 CSRF 不匹配。 | retry=刷新 /v1/me 后重试。 - HTTP 404 SIMULATED_PAYMENT_DISABLED | 当前运行态未显式开放本地模拟充值。 | retry=不要重试;等待正式支付或本地授权配置。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 409 IDEMPOTENCY_CONFLICT | 同 project 幂等键已绑定另一金额。 | retry=使用新键创建不同金额订单。 - HTTP 429 RATE_LIMITED | 订单创建限流。 | retry=等待窗口后重试。 - HTTP 408 REQUEST_TIMEOUT | 请求体未在截止时间内读完。 | retry=可在确认服务可达后使用新请求重试。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体超过服务端上限。 | retry=缩小请求体后再发;原样重试无效。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host;不要自动跟随未知跳转。 Retry: 相同键与相同金额可安全重放;不要在不确定时换键。 Idempotency: project + Idempotency-Key + 规范金额绑定;相同请求重放同一订单,不重复创建。 Runtime boundary: 真实支付、退款、发票与生产账务为 NOT_RUN;当前仅 local-simulated。 ## POST /v1/orders/{orderId}/confirm | confirmGatewayRechargeOrder Summary: 显式确认本地模拟充值 Purpose: 对当前项目订单执行 exactly-once simulated credit,写入 entitlement、credit lot 与 ledger。 When: 仅本地验收时,在用户明确确认模拟付款后调用;不能作为真实付款证据。 Authentication: 需要有效会话 Cookie、精确 Origin 与 session-bound CSRF。 Origin: 浏览器写请求只接受当前 Gateway 精确 Origin;不得跨域调用。 CSRF: 必需,且必须绑定当前 Cookie 会话。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Origin | required=true | example=https://api.funaokeji.com | 必须与当前 Gateway origin 精确一致。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 - Cookie | required=true | example=funao_gateway_session= | HttpOnly Gateway 会话 Cookie;不要写入日志或脚本存储。 - X-CSRF-Token | required=true | example= | 从当前会话响应取得并与 Cookie 会话绑定。 Parameters: - orderId | string | 必填 | {"pattern":"^ord_[A-Za-z0-9]+$"} | 当前 Gateway project 所属的充值订单标识;跨 owner 与不存在统一 404。 - X-CSRF-Token | string | 必填 | {"minLength":10} | 当前 Gateway 会话绑定的 CSRF token;从登录/注册或最新 /v1/me 响应取得。 - Origin | string | 必填 | {"const":"https://api.funaokeji.com","format":"uri"} | 浏览器写请求必须精确等于当前 Gateway origin;canonical 为 https://api.funaokeji.com。 Request fields: Request example: {} Success: HTTP 200 | Success Success example: {"amountFen":2300,"createdAt":"2026-09-03T04:00:00+00:00","creditAmount":230,"creditKind":"simulated_prepaid","creditLotId":"lot_example","creditedAmount":230,"creditedAt":"2026-09-03T04:01:00+00:00","creditsPerYuan":10,"currency":"CNY","idempotentReplay":false,"orderId":"ord_example","paymentMode":"local-simulated","pricingVersion":"gateway-custom-cny-10credits-v1","simulatedPaidAt":"2026-09-03T04:01:00+00:00","state":"credited","yuanPerCredit":"0.10"} Success fields: - orderId | string | 必填 | 无附加约束 | 当前项目所属充值订单标识。 - amountFen | integer | 必填 | {"maximum":1000000,"minimum":100} | 充值金额,单位为人民币分;必须是整数元范围内的 100 倍数。 - creditAmount | integer | 必填 | {"maximum":100000,"minimum":10} | 按服务端价格快照计算的 credits 数量。 - currency | string | 必填 | {"const":"CNY"} | 价格币种;当前固定为 CNY。 - creditsPerYuan | integer | 必填 | {"const":10} | 服务端价格版本规定的每人民币元 credits 数。 - yuanPerCredit | string | 必填 | {"const":"0.10"} | 按当前本地价格规则折算的每 credit 人民币元字符串。 - pricingVersion | string | 必填 | {"const":"gateway-custom-cny-10credits-v1"} | 服务端订单价格快照版本。 - state | string | 必填 | {"enum":["pending","simulated_paid","credited"]} | 资源、订单、Key 或业务扣费当前状态。 - paymentMode | string | 必填 | {"const":"local-simulated"} | 当前充值能力模式;local-simulated 不是真实支付。 - createdAt | string | 必填 | {"format":"date-time"} | 服务端创建时间,含时区的 ISO-8601 时间。 - simulatedPaidAt | string | null | 必填 | 无附加约束 | 本地模拟确认发生时间;未确认时为 null。 - creditedAt | string | null | 必填 | 无附加约束 | credits 实际入账时间;未入账时为 null。 - creditLotId | string | null | 必填 | 无附加约束 | 入账后生成的项目级 credit lot 标识;未生成时为 null。 - creditedAmount | integer | 必填 | {"minimum":1} | 本次 exactly-once 入账的 credits 数量。 - creditKind | string | 必填 | {"const":"simulated_prepaid"} | credit lot 来源类型;local-simulated 固定为 simulated_prepaid。 - idempotentReplay | boolean | 必填 | 无附加约束 | 是否为相同 owner、键与请求指纹的存储结果重放。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 403 ORIGIN_INVALID | 浏览器 Origin 不是当前 Gateway 精确 Origin。 | retry=回到 canonical Gateway 页面重新发起。 - HTTP 401 GATEWAY_AUTH_REQUIRED | 会话无效。 | retry=重新登录。 - HTTP 403 CSRF_INVALID | Origin 或 CSRF 不匹配。 | retry=刷新 /v1/me 后重试。 - HTTP 404 SIMULATED_PAYMENT_DISABLED | 当前运行态未显式开放本地模拟充值。 | retry=不要重试;等待正式支付或本地授权配置。 - HTTP 404 ORDER_NOT_FOUND | 订单不存在或不属于当前项目。 | retry=核对当前项目 recentOrders。 - HTTP 409 ORDER_NOT_PAYABLE | 订单当前状态不允许确认。 | retry=重新读取订单状态,不要盲目重复。 - HTTP 409 ORDER_CONFIRM_CONFLICT | 并发确认未取得唯一状态转换。 | retry=重新读取订单状态并核对 credits。 - HTTP 409 ORDER_CREDIT_CONFLICT | 入账状态转换发生并发冲突。 | retry=先读取 /v1/me 对账,禁止再次模拟付款。 - HTTP 429 RATE_LIMITED | 确认操作限流。 | retry=等待窗口后再查状态。 - HTTP 408 REQUEST_TIMEOUT | 请求体未在截止时间内读完。 | retry=可在确认服务可达后使用新请求重试。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体超过服务端上限。 | retry=缩小请求体后再发;原样重试无效。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host;不要自动跟随未知跳转。 Retry: 结果不明时先读取 /v1/me;同一订单并发确认也只入账一次。 Idempotency: 不使用客户端 Idempotency-Key;orderId 自身是 exactly-once 幂等边界。 Runtime boundary: 仅 local-simulated;真实支付确认与生产对账为 NOT_RUN。 ## GET /openapi.json | getGatewayOpenApi Summary: 下载 OpenAPI 3.1 契约 Purpose: 返回 24 个公开操作、schema、示例、逐操作错误、认证与扣费扩展。 When: 生成 SDK、静态校验或核对客户端实现时使用。 Authentication: 无需登录;仅公开读取。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 Request body: none Success: HTTP 200 | OpenAPI document Success example: {"info":{"title":"副脑中转站 Gateway API","version":"2026-09-03"},"openapi":"3.1.0"} Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 500 INTERNAL_ERROR | 服务端未能生成公开响应。 | retry=指数退避;不要携带或记录秘密。 Retry: 安全 GET 可重试。 Idempotency: 不需要 Idempotency-Key。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## GET /llms.txt | getGatewayLlmsText Summary: 读取 AI 客户端契约摘要 Purpose: 按 24 个操作给出用途、认证、字段、示例、响应、错误、重试、幂等与价格。 When: 让 AI 编码客户端在不解析 HTML 时取得足够合同上下文。 Authentication: 无需登录;仅公开读取。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 Request body: none Success: HTTP 200 | Plain-text contract Success example: "# 副脑中转站 Gateway API\n..." Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 500 INTERNAL_ERROR | 服务端未能生成公开响应。 | retry=指数退避;不要携带或记录秘密。 Retry: 安全 GET 可重试。 Idempotency: 不需要 Idempotency-Key。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## GET /docs | getGatewayHtmlDocs Summary: 阅读人类版 Gateway API 文档 Purpose: 渲染与 OpenAPI 同源的逐操作用途、字段、示例、错误和扣费信息。 When: 人工接入、排障和评审契约时使用。 Authentication: 无需登录;仅公开读取。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 不扣费;本操作不预留或结算 Gateway credits。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 Request body: none Success: HTTP 200 | HTML documentation Success example: "..." Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 500 INTERNAL_ERROR | 服务端未能生成公开响应。 | retry=指数退避;不要携带或记录秘密。 Retry: 安全 GET 可重试。 Idempotency: 不需要 Idempotency-Key。 Runtime boundary: 无额外运行边界;全局 NOT_RUN 仍适用。 ## POST /v1/models/chat | invokeModelChat Summary: 调用模型对话 Purpose: 向固定模型 provider 提交 prompt,返回本地候选或已配置 provider 的公开输出。 When: 需要单轮文本生成且已准备 models:invoke Key 时使用。 Authentication: 需要具备本操作 scope 的 project-scoped Bearer 业务 Key。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 固定 3 credits(按当前本地规则折合 ¥0.30):转发前 reserve,成功 settle,确定失败 release,不确定结果 manual_review。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 - Authorization | required=true | example=Bearer | 项目所属、具备所需 scope 的 Gateway 业务 Key。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 Request fields: - provider | string | 可选 | {"enum":["alibaba-cloud","deepseek","doubao"]} | 固定 allowlist 中的 provider 名称。 - model | string | 可选 | 无附加约束 | 固定 provider 下的模型名;省略时使用服务端默认。 - prompt | string | 必填 | {"minLength":1} | 要交给固定模型适配器的非空文本。 Request example: {"model":"mock-default","prompt":"你好,请概括这段文本。","provider":"deepseek"} Success: HTTP 200 | Provider result confirmed and credits settled Success example: {"chargedCredits":3,"data":{"model":"mock-default","output":"本地模拟输出","provider":"deepseek"},"operation":"model.chat","status":"settled","usage":{"inputUnits":12,"outputUnits":8,"totalUnits":20}} Success fields: - status | string | 必填 | {"const":"settled"} | 业务结果、复核项或资源当前稳定状态。 - operation | string | 必填 | {"const":"model.chat"} | 固定业务操作标识。 - chargedCredits | integer | 必填 | {"const":3} | chargedCredits 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - data | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开结果对象;具体字段由 operation 决定。 - data.provider | string | 必填 | {"enum":["alibaba-cloud","deepseek","doubao"]} | 固定 allowlist 中的 provider 名称。 - data.model | string | 必填 | {"minLength":1} | 固定 provider 下的模型名;省略时使用服务端默认。 - data.output | string | 必填 | 无附加约束 | 模型适配器公开输出文本。 - usage | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开计量对象,不含内部成本或凭证。 - usage.inputUnits | integer | 必填 | {"minimum":0} | 模型适配器报告的输入计量单位;不得视作人民币金额。 - usage.outputUnits | integer | 必填 | {"minimum":0} | 模型适配器报告的输出计量单位;不得视作人民币金额。 - usage.totalUnits | integer | 必填 | {"minimum":0} | provider 报告的总用量单位;本地适配器取 inputUnits 与 outputUnits 之和。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 401 UNAUTHORIZED | Bearer Key 缺失、无效或已撤销。 | retry=换用当前项目有效 Key。 - HTTP 401 KEY_EXPIRED | Bearer Key 已过期。 | retry=创建具备最小 scope 的新 Key。 - HTTP 402 INSUFFICIENT_PAID_CREDITS | 当前项目可用 credits 不足,未转发供应商。 | retry=充值后可用同一业务意图重新请求。 - HTTP 403 FORBIDDEN | Key 不具备本操作所需 scope。 | retry=创建最小所需 scope 的新 Key。 - HTTP 408 REQUEST_TIMEOUT | 请求体读取超时,供应商未确认转发。 | retry=使用新幂等键重试。 - HTTP 409 IDEMPOTENCY_CONFLICT | 幂等键已绑定不同 operation、请求指纹或旧隔离版本。 | retry=生成新幂等键;不要覆盖旧键。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体过大,供应商未转发。 | retry=缩小请求体并使用新幂等键。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 429 RATE_LIMITED | 当前项目或凭证进入固定限流窗口。 | retry=等待响应窗口后再试。 - HTTP 502 ADAPTER_FAILURE | 适配器在确认成功前失败,已释放预留 credits。 | retry=修复适配器或请求后使用新幂等键。 - HTTP 502 PROVIDER_CONTRACT_INVALID | 供应商拒绝请求或成功响应不符合公开合同。 | retry=若返回 released 可修正后重试;否则按 manual_review 处理。 - HTTP 503 PROVIDER_UNAVAILABLE | 真实 provider 未启用、凭据缺失、限流或暂时不可用。 | retry=指数退避;先确认不是 manual_review。 - HTTP 400 PROVIDER_NOT_ALLOWED | provider 不在当前模型适配器集合。 | retry=改用已发布 provider。 - HTTP 400 INVALID_MODEL | model 必须是字符串。 | retry=传字符串 model 或省略以使用默认值。 - HTTP 400 INVALID_PROMPT | prompt 缺失、不是字符串或去空白后为空。 | retry=提供非空 prompt。 - HTTP 400 MODEL_NOT_ALLOWED | model 不在已配置 provider 的别名白名单。 | retry=改用该 provider 已发布的 model 名称。 - HTTP 413 PROMPT_TOO_LARGE | prompt 超过已配置 provider 的字符上限。 | retry=缩短 prompt 后使用新幂等键。 - HTTP 503 PROVIDER_DISABLED | 真实模型 provider 在当前配置中关闭。 | retry=不要重试;等待运行配置显式启用。 - HTTP 503 PROVIDER_AUTH_REQUIRED | 模型 provider 凭据在调用时不可用。 | retry=由运维恢复凭据后再试。 - HTTP 503 PROVIDER_CIRCUIT_OPEN | 模型 provider 的进程内熔断器仍在冷却。 | retry=等待冷却窗口后再试。 - HTTP 503 PROVIDER_RATE_LIMITED | 模型 provider 返回限流。 | retry=按 provider 窗口退避后使用新请求。 - HTTP 503 PROVIDER_CAPACITY_EXHAUSTED | 模型 provider 传输并发容量暂时用尽,尚未转发。 | retry=等待短暂退避后使用新请求。 - HTTP 502 PROVIDER_REQUEST_REJECTED | 模型 provider 明确拒绝请求。 | retry=修正 provider 可接受的请求后使用新幂等键。 Retry: 同键同规范请求可安全重放且不二次扣费;202 manual_review 时禁止自动重试。 Idempotency: Idempotency-Key 按 project + operation + 规范请求指纹绑定;改请求返回 409。 Runtime boundary: 真实 provider 与生产流量为 NOT_RUN;默认 provider-disabled 或 local-mock。 ## POST /v1/shopping/search | searchShopping Summary: 搜索购物候选 Purpose: 通过真挑 facade 搜索当前项目的购物候选;项目衍生理由只写入该项目缓存。 When: 使用 shopping:search scope 做兼容搜索时调用。 Authentication: 需要具备本操作 scope 的 project-scoped Bearer 业务 Key。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 固定 2 credits(按当前本地规则折合 ¥0.20):转发前 reserve,成功 settle,确定失败 release,不确定结果 manual_review。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 - Authorization | required=true | example=Bearer | 项目所属、具备所需 scope 的 Gateway 业务 Key。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 Request fields: - query | string | 必填 | {"minLength":1} | 当前项目本次搜索意图;可能影响 reason,不能跨项目共享。 - provider | string | 可选 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - providers | array | 可选 | {"maxItems":3,"minItems":1,"uniqueItems":true} | 搜索时使用的 1–3 个去重 provider。 - filters | object | 可选 | {"additionalProperties":false} | 搜索前允许的公开筛选条件。 - filters.maxPriceCents | integer | 可选 | {"minimum":0} | 允许的最高商品价格,单位为人民币分。 - sort | string | 可选 | {"enum":["price_asc","relevance"]} | 候选排序方式:price_asc 或 relevance。 - limit | integer | 可选 | {"maximum":3,"minimum":1} | 搜索最多返回的候选数,范围 1–3。 Request example: {"limit":1,"providers":["jd"],"query":"预算 300 元的耳机","sort":"relevance"} Success: HTTP 200 | Provider result confirmed and credits settled Success example: {"chargedCredits":2,"data":{"items":[{"availability":"unknown","currency":"CNY","highlights":["公开属性示例"],"itemRef":{"productId":"sku-example","provider":"jd"},"priceCents":1990,"reason":"基于当前项目请求生成的候选理由","testOnly":true,"title":"候选商品"}],"mode":"local-mock","query":"预算 300 元的耳机"},"operation":"shopping.search","status":"settled","usage":{"providerCalls":1,"resultCount":1}} Success fields: - status | string | 必填 | {"const":"settled"} | 业务结果、复核项或资源当前稳定状态。 - operation | string | 必填 | {"const":"shopping.search"} | 固定业务操作标识。 - chargedCredits | integer | 必填 | {"const":2} | chargedCredits 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - data | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开结果对象;具体字段由 operation 决定。 - data.query | string | 必填 | {"minLength":1} | 当前项目本次搜索意图;可能影响 reason,不能跨项目共享。 - data.items | array | 必填 | {"maxItems":3} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.items[].title | string | 必填 | {"maxLength":500,"minLength":1} | 经过公开 allowlist 与长度校验的商品标题。 - data.items[].priceCents | integer | 必填 | {"minimum":0} | 商品候选价格,单位为人民币分。 - data.items[].currency | string | 必填 | {"maxLength":8,"minLength":1} | 价格币种;当前固定为 CNY。 - data.items[].availability | string | 必填 | {"enum":["available","unavailable","unknown"]} | 候选可用性;unknown 表示仍需购买前复核。 - data.items[].highlights | array | 必填 | {"maxItems":3} | 当前项目候选的公开亮点,最多返回经过 allowlist 的短文本。 - data.items[].reason | string | 必填 | {"maxLength":500,"minLength":1} | 由当前项目查询衍生的候选理由;只允许所属项目读取。 - data.items[].testOnly | boolean | 必填 | 无附加约束 | 结果是否来自本地合同 fixture;true 表示不能当作真实平台结果。 - data.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - usage | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开计量对象,不含内部成本或凭证。 - usage.providerCalls | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作实际触发或读取的 provider 调用计数。 - usage.resultCount | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作返回的公开候选或结果数量。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 401 UNAUTHORIZED | Bearer Key 缺失、无效或已撤销。 | retry=换用当前项目有效 Key。 - HTTP 401 KEY_EXPIRED | Bearer Key 已过期。 | retry=创建具备最小 scope 的新 Key。 - HTTP 402 INSUFFICIENT_PAID_CREDITS | 当前项目可用 credits 不足,未转发供应商。 | retry=充值后可用同一业务意图重新请求。 - HTTP 403 FORBIDDEN | Key 不具备本操作所需 scope。 | retry=创建最小所需 scope 的新 Key。 - HTTP 408 REQUEST_TIMEOUT | 请求体读取超时,供应商未确认转发。 | retry=使用新幂等键重试。 - HTTP 409 IDEMPOTENCY_CONFLICT | 幂等键已绑定不同 operation、请求指纹或旧隔离版本。 | retry=生成新幂等键;不要覆盖旧键。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体过大,供应商未转发。 | retry=缩小请求体并使用新幂等键。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 429 RATE_LIMITED | 当前项目或凭证进入固定限流窗口。 | retry=等待响应窗口后再试。 - HTTP 502 ADAPTER_FAILURE | 适配器在确认成功前失败,已释放预留 credits。 | retry=修复适配器或请求后使用新幂等键。 - HTTP 502 PROVIDER_CONTRACT_INVALID | 供应商拒绝请求或成功响应不符合公开合同。 | retry=若返回 released 可修正后重试;否则按 manual_review 处理。 - HTTP 503 PROVIDER_UNAVAILABLE | 真实 provider 未启用、凭据缺失、限流或暂时不可用。 | retry=指数退避;先确认不是 manual_review。 - HTTP 400 INVALID_QUERY | query 必须是非空字符串。 | retry=提供非空 query。 - HTTP 400 PROVIDER_NOT_ALLOWED | provider 或 providers 不在固定真挑 registry。 | retry=改用公开允许的 provider。 - HTTP 400 INVALID_LIMIT | limit 必须是 1 到 3 的整数。 | retry=修正 limit。 - HTTP 400 INVALID_SORT | sort 不在 price_asc、relevance 白名单。 | retry=改用公开 sort。 - HTTP 400 INVALID_FILTERS | filters 只允许非负整数 maxPriceCents。 | retry=修正或移除 filters。 - HTTP 503 PROVIDER_DISABLED | 真实真挑 provider 在当前配置中关闭。 | retry=不要重试;等待运行配置显式启用。 - HTTP 503 PROVIDER_AUTH_REQUIRED | 真挑 provider 凭据在调用时不可用。 | retry=由运维恢复凭据后再试。 - HTTP 503 PROVIDER_RATE_LIMITED | 真挑 provider 返回限流。 | retry=按 provider 窗口退避后使用新请求。 - HTTP 503 PROVIDER_CAPACITY_EXHAUSTED | 真挑 provider 传输并发容量暂时用尽,尚未转发。 | retry=等待短暂退避后使用新请求。 - HTTP 502 PROVIDER_REQUEST_REJECTED | 真挑 provider 明确拒绝请求。 | retry=修正请求或 provider 配置后使用新幂等键。 - HTTP 502 PROVIDER_REDIRECT_FORBIDDEN | 真挑 provider 返回不允许跟随的重定向。 | retry=不要跟随;由运维修正固定 endpoint。 Retry: 同键同规范请求可安全重放且不二次扣费;202 manual_review 时禁止自动重试。 Idempotency: Idempotency-Key 按 project + operation + 规范请求指纹绑定;改请求返回 409。 Runtime boundary: 真实 provider 与生产流量为 NOT_RUN;默认 provider-disabled 或 local-mock。 ## POST /v1/zhentiao/search | searchZhentiao Summary: 搜索真挑候选 Purpose: 按 query、provider、筛选与排序生成当前项目隔离的候选集合。 When: 需要先获得 itemRef 供后续筛选、比较或推荐时调用。 Authentication: 需要具备本操作 scope 的 project-scoped Bearer 业务 Key。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 固定 2 credits(按当前本地规则折合 ¥0.20):转发前 reserve,成功 settle,确定失败 release,不确定结果 manual_review。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 - Authorization | required=true | example=Bearer | 项目所属、具备所需 scope 的 Gateway 业务 Key。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 Request fields: - query | string | 必填 | {"minLength":1} | 当前项目本次搜索意图;可能影响 reason,不能跨项目共享。 - provider | string | 可选 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - providers | array | 可选 | {"maxItems":3,"minItems":1,"uniqueItems":true} | 搜索时使用的 1–3 个去重 provider。 - filters | object | 可选 | {"additionalProperties":false} | 搜索前允许的公开筛选条件。 - filters.maxPriceCents | integer | 可选 | {"minimum":0} | 允许的最高商品价格,单位为人民币分。 - sort | string | 可选 | {"enum":["price_asc","relevance"]} | 候选排序方式:price_asc 或 relevance。 - limit | integer | 可选 | {"maximum":3,"minimum":1} | 搜索最多返回的候选数,范围 1–3。 Request example: {"filters":{"maxPriceCents":30000},"limit":1,"providers":["jd"],"query":"预算 300 元的耳机","sort":"relevance"} Success: HTTP 200 | Provider result confirmed and credits settled Success example: {"chargedCredits":2,"data":{"items":[{"availability":"unknown","currency":"CNY","highlights":["公开属性示例"],"itemRef":{"productId":"sku-example","provider":"jd"},"priceCents":1990,"reason":"基于当前项目请求生成的候选理由","testOnly":true,"title":"候选商品"}],"mode":"local-mock","query":"预算 300 元的耳机"},"operation":"zhentiao.search","status":"settled","usage":{"providerCalls":1,"resultCount":1}} Success fields: - status | string | 必填 | {"const":"settled"} | 业务结果、复核项或资源当前稳定状态。 - operation | string | 必填 | {"const":"zhentiao.search"} | 固定业务操作标识。 - chargedCredits | integer | 必填 | {"const":2} | chargedCredits 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - data | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开结果对象;具体字段由 operation 决定。 - data.query | string | 必填 | {"minLength":1} | 当前项目本次搜索意图;可能影响 reason,不能跨项目共享。 - data.items | array | 必填 | {"maxItems":3} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.items[].title | string | 必填 | {"maxLength":500,"minLength":1} | 经过公开 allowlist 与长度校验的商品标题。 - data.items[].priceCents | integer | 必填 | {"minimum":0} | 商品候选价格,单位为人民币分。 - data.items[].currency | string | 必填 | {"maxLength":8,"minLength":1} | 价格币种;当前固定为 CNY。 - data.items[].availability | string | 必填 | {"enum":["available","unavailable","unknown"]} | 候选可用性;unknown 表示仍需购买前复核。 - data.items[].highlights | array | 必填 | {"maxItems":3} | 当前项目候选的公开亮点,最多返回经过 allowlist 的短文本。 - data.items[].reason | string | 必填 | {"maxLength":500,"minLength":1} | 由当前项目查询衍生的候选理由;只允许所属项目读取。 - data.items[].testOnly | boolean | 必填 | 无附加约束 | 结果是否来自本地合同 fixture;true 表示不能当作真实平台结果。 - data.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - usage | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开计量对象,不含内部成本或凭证。 - usage.providerCalls | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作实际触发或读取的 provider 调用计数。 - usage.resultCount | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作返回的公开候选或结果数量。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 401 UNAUTHORIZED | Bearer Key 缺失、无效或已撤销。 | retry=换用当前项目有效 Key。 - HTTP 401 KEY_EXPIRED | Bearer Key 已过期。 | retry=创建具备最小 scope 的新 Key。 - HTTP 402 INSUFFICIENT_PAID_CREDITS | 当前项目可用 credits 不足,未转发供应商。 | retry=充值后可用同一业务意图重新请求。 - HTTP 403 FORBIDDEN | Key 不具备本操作所需 scope。 | retry=创建最小所需 scope 的新 Key。 - HTTP 408 REQUEST_TIMEOUT | 请求体读取超时,供应商未确认转发。 | retry=使用新幂等键重试。 - HTTP 409 IDEMPOTENCY_CONFLICT | 幂等键已绑定不同 operation、请求指纹或旧隔离版本。 | retry=生成新幂等键;不要覆盖旧键。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体过大,供应商未转发。 | retry=缩小请求体并使用新幂等键。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 429 RATE_LIMITED | 当前项目或凭证进入固定限流窗口。 | retry=等待响应窗口后再试。 - HTTP 502 ADAPTER_FAILURE | 适配器在确认成功前失败,已释放预留 credits。 | retry=修复适配器或请求后使用新幂等键。 - HTTP 502 PROVIDER_CONTRACT_INVALID | 供应商拒绝请求或成功响应不符合公开合同。 | retry=若返回 released 可修正后重试;否则按 manual_review 处理。 - HTTP 503 PROVIDER_UNAVAILABLE | 真实 provider 未启用、凭据缺失、限流或暂时不可用。 | retry=指数退避;先确认不是 manual_review。 - HTTP 400 INVALID_QUERY | query 必须是非空字符串。 | retry=提供非空 query。 - HTTP 400 PROVIDER_NOT_ALLOWED | provider 或 providers 不在固定真挑 registry。 | retry=改用公开允许的 provider。 - HTTP 400 INVALID_LIMIT | limit 必须是 1 到 3 的整数。 | retry=修正 limit。 - HTTP 400 INVALID_SORT | sort 不在 price_asc、relevance 白名单。 | retry=改用公开 sort。 - HTTP 400 INVALID_FILTERS | filters 只允许非负整数 maxPriceCents。 | retry=修正或移除 filters。 - HTTP 503 PROVIDER_DISABLED | 真实真挑 provider 在当前配置中关闭。 | retry=不要重试;等待运行配置显式启用。 - HTTP 503 PROVIDER_AUTH_REQUIRED | 真挑 provider 凭据在调用时不可用。 | retry=由运维恢复凭据后再试。 - HTTP 503 PROVIDER_RATE_LIMITED | 真挑 provider 返回限流。 | retry=按 provider 窗口退避后使用新请求。 - HTTP 503 PROVIDER_CAPACITY_EXHAUSTED | 真挑 provider 传输并发容量暂时用尽,尚未转发。 | retry=等待短暂退避后使用新请求。 - HTTP 502 PROVIDER_REQUEST_REJECTED | 真挑 provider 明确拒绝请求。 | retry=修正请求或 provider 配置后使用新幂等键。 - HTTP 502 PROVIDER_REDIRECT_FORBIDDEN | 真挑 provider 返回不允许跟随的重定向。 | retry=不要跟随;由运维修正固定 endpoint。 Retry: 同键同规范请求可安全重放且不二次扣费;202 manual_review 时禁止自动重试。 Idempotency: Idempotency-Key 按 project + operation + 规范请求指纹绑定;改请求返回 409。 Runtime boundary: 真实 provider 与生产流量为 NOT_RUN;默认 provider-disabled 或 local-mock。 ## POST /v1/zhentiao/filter | filterZhentiaoItems Summary: 筛选已搜索候选 Purpose: 只读取当前项目此前验证的 itemRef,并按最高价格条件筛选。 When: 已经通过同项目搜索取得 itemRef,需要缩小候选时调用。 Authentication: 需要具备本操作 scope 的 project-scoped Bearer 业务 Key。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 固定 2 credits(按当前本地规则折合 ¥0.20):转发前 reserve,成功 settle,确定失败 release,不确定结果 manual_review。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 - Authorization | required=true | example=Bearer | 项目所属、具备所需 scope 的 Gateway 业务 Key。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 Request fields: - itemRefs | array | 必填 | {"maxItems":3,"minItems":1} | 1–3 个商品引用;比较操作至少需要 2 个。 - itemRefs[].provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - itemRefs[].productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - criteria | object | 可选 | {"additionalProperties":false} | 筛选结果实际采用的 allowlisted 条件。 - criteria.maxPriceCents | integer | 可选 | {"minimum":0} | 允许的最高商品价格,单位为人民币分。 Request example: {"criteria":{"maxPriceCents":30000},"itemRefs":[{"productId":"sku-example","provider":"jd"}]} Success: HTTP 200 | Provider result confirmed and credits settled Success example: {"chargedCredits":2,"data":{"criteria":{"maxPriceCents":30000},"items":[{"availability":"unknown","currency":"CNY","highlights":["公开属性示例"],"itemRef":{"productId":"sku-example","provider":"jd"},"priceCents":1990,"reason":"基于当前项目请求生成的候选理由","testOnly":true,"title":"候选商品"}],"mode":"local-mock"},"operation":"zhentiao.filter","status":"settled","usage":{"providerCalls":1,"resultCount":1}} Success fields: - status | string | 必填 | {"const":"settled"} | 业务结果、复核项或资源当前稳定状态。 - operation | string | 必填 | {"const":"zhentiao.filter"} | 固定业务操作标识。 - chargedCredits | integer | 必填 | {"const":2} | chargedCredits 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - data | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开结果对象;具体字段由 operation 决定。 - data.items | array | 必填 | {"maxItems":3} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.items[].title | string | 必填 | {"maxLength":500,"minLength":1} | 经过公开 allowlist 与长度校验的商品标题。 - data.items[].priceCents | integer | 必填 | {"minimum":0} | 商品候选价格,单位为人民币分。 - data.items[].currency | string | 必填 | {"maxLength":8,"minLength":1} | 价格币种;当前固定为 CNY。 - data.items[].availability | string | 必填 | {"enum":["available","unavailable","unknown"]} | 候选可用性;unknown 表示仍需购买前复核。 - data.items[].highlights | array | 必填 | {"maxItems":3} | 当前项目候选的公开亮点,最多返回经过 allowlist 的短文本。 - data.items[].reason | string | 必填 | {"maxLength":500,"minLength":1} | 由当前项目查询衍生的候选理由;只允许所属项目读取。 - data.items[].testOnly | boolean | 必填 | 无附加约束 | 结果是否来自本地合同 fixture;true 表示不能当作真实平台结果。 - data.criteria | object | 必填 | {"additionalProperties":false} | 筛选结果实际采用的 allowlisted 条件。 - data.criteria.maxPriceCents | integer | 可选 | {"minimum":0} | 允许的最高商品价格,单位为人民币分。 - data.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - usage | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开计量对象,不含内部成本或凭证。 - usage.providerCalls | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作实际触发或读取的 provider 调用计数。 - usage.resultCount | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作返回的公开候选或结果数量。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 401 UNAUTHORIZED | Bearer Key 缺失、无效或已撤销。 | retry=换用当前项目有效 Key。 - HTTP 401 KEY_EXPIRED | Bearer Key 已过期。 | retry=创建具备最小 scope 的新 Key。 - HTTP 402 INSUFFICIENT_PAID_CREDITS | 当前项目可用 credits 不足,未转发供应商。 | retry=充值后可用同一业务意图重新请求。 - HTTP 403 FORBIDDEN | Key 不具备本操作所需 scope。 | retry=创建最小所需 scope 的新 Key。 - HTTP 408 REQUEST_TIMEOUT | 请求体读取超时,供应商未确认转发。 | retry=使用新幂等键重试。 - HTTP 409 IDEMPOTENCY_CONFLICT | 幂等键已绑定不同 operation、请求指纹或旧隔离版本。 | retry=生成新幂等键;不要覆盖旧键。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体过大,供应商未转发。 | retry=缩小请求体并使用新幂等键。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 429 RATE_LIMITED | 当前项目或凭证进入固定限流窗口。 | retry=等待响应窗口后再试。 - HTTP 502 ADAPTER_FAILURE | 适配器在确认成功前失败,已释放预留 credits。 | retry=修复适配器或请求后使用新幂等键。 - HTTP 502 PROVIDER_CONTRACT_INVALID | 供应商拒绝请求或成功响应不符合公开合同。 | retry=若返回 released 可修正后重试;否则按 manual_review 处理。 - HTTP 503 PROVIDER_UNAVAILABLE | 真实 provider 未启用、凭据缺失、限流或暂时不可用。 | retry=指数退避;先确认不是 manual_review。 - HTTP 400 INVALID_ITEM_REFS | itemRefs 必须包含 1 到 3 项。 | retry=传入当前项目搜索返回的 itemRef。 - HTTP 400 INVALID_ITEM_REF | itemRef 必须只含有效 provider 与非空 productId。 | retry=使用未改写的搜索结果 itemRef。 - HTTP 400 INVALID_FILTERS | criteria 只允许非负整数 maxPriceCents。 | retry=修正或移除 criteria。 - HTTP 409 PROVIDER_CAPABILITY_UNSUPPORTED | 真实真挑详情只能读取当前项目已有的已验证搜索快照。 | retry=先在同一项目搜索并使用返回的 itemRef。 Retry: 同键同规范请求可安全重放且不二次扣费;202 manual_review 时禁止自动重试。 Idempotency: Idempotency-Key 按 project + operation + 规范请求指纹绑定;改请求返回 409。 Runtime boundary: 真实 provider 与生产流量为 NOT_RUN;默认 provider-disabled 或 local-mock。 ## POST /v1/zhentiao/compare | compareZhentiaoItems Summary: 比较已搜索候选 Purpose: 读取当前项目 2–3 个 itemRef,并返回价格、可用性与 highlights 比较维度。 When: 同项目已有多个候选并需要并排比较时调用。 Authentication: 需要具备本操作 scope 的 project-scoped Bearer 业务 Key。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 固定 3 credits(按当前本地规则折合 ¥0.30):转发前 reserve,成功 settle,确定失败 release,不确定结果 manual_review。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 - Authorization | required=true | example=Bearer | 项目所属、具备所需 scope 的 Gateway 业务 Key。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 Request fields: - itemRefs | array | 必填 | {"maxItems":3,"minItems":2} | 1–3 个商品引用;比较操作至少需要 2 个。 - itemRefs[].provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - itemRefs[].productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 Request example: {"itemRefs":[{"productId":"sku-a","provider":"jd"},{"productId":"sku-b","provider":"douyin"}]} Success: HTTP 200 | Provider result confirmed and credits settled Success example: {"chargedCredits":3,"data":{"dimensions":["priceCents","availability","highlights"],"items":[{"availability":"unknown","currency":"CNY","highlights":["公开属性示例"],"itemRef":{"productId":"sku-a","provider":"jd"},"priceCents":1990,"reason":"基于当前项目请求生成的候选理由","testOnly":true,"title":"候选商品 A"},{"availability":"unknown","currency":"CNY","highlights":["公开属性示例"],"itemRef":{"productId":"sku-b","provider":"douyin"},"priceCents":1990,"reason":"基于当前项目请求生成的候选理由","testOnly":true,"title":"候选商品 B"}],"mode":"local-mock"},"operation":"zhentiao.compare","status":"settled","usage":{"providerCalls":2,"resultCount":2}} Success fields: - status | string | 必填 | {"const":"settled"} | 业务结果、复核项或资源当前稳定状态。 - operation | string | 必填 | {"const":"zhentiao.compare"} | 固定业务操作标识。 - chargedCredits | integer | 必填 | {"const":3} | chargedCredits 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - data | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开结果对象;具体字段由 operation 决定。 - data.items | array | 必填 | {"maxItems":3,"minItems":2} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.items[].title | string | 必填 | {"maxLength":500,"minLength":1} | 经过公开 allowlist 与长度校验的商品标题。 - data.items[].priceCents | integer | 必填 | {"minimum":0} | 商品候选价格,单位为人民币分。 - data.items[].currency | string | 必填 | {"maxLength":8,"minLength":1} | 价格币种;当前固定为 CNY。 - data.items[].availability | string | 必填 | {"enum":["available","unavailable","unknown"]} | 候选可用性;unknown 表示仍需购买前复核。 - data.items[].highlights | array | 必填 | {"maxItems":3} | 当前项目候选的公开亮点,最多返回经过 allowlist 的短文本。 - data.items[].reason | string | 必填 | {"maxLength":500,"minLength":1} | 由当前项目查询衍生的候选理由;只允许所属项目读取。 - data.items[].testOnly | boolean | 必填 | 无附加约束 | 结果是否来自本地合同 fixture;true 表示不能当作真实平台结果。 - data.dimensions | array | 必填 | 无附加约束 | 比较响应实际使用的公开维度列表。 - data.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - usage | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开计量对象,不含内部成本或凭证。 - usage.providerCalls | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作实际触发或读取的 provider 调用计数。 - usage.resultCount | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作返回的公开候选或结果数量。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 401 UNAUTHORIZED | Bearer Key 缺失、无效或已撤销。 | retry=换用当前项目有效 Key。 - HTTP 401 KEY_EXPIRED | Bearer Key 已过期。 | retry=创建具备最小 scope 的新 Key。 - HTTP 402 INSUFFICIENT_PAID_CREDITS | 当前项目可用 credits 不足,未转发供应商。 | retry=充值后可用同一业务意图重新请求。 - HTTP 403 FORBIDDEN | Key 不具备本操作所需 scope。 | retry=创建最小所需 scope 的新 Key。 - HTTP 408 REQUEST_TIMEOUT | 请求体读取超时,供应商未确认转发。 | retry=使用新幂等键重试。 - HTTP 409 IDEMPOTENCY_CONFLICT | 幂等键已绑定不同 operation、请求指纹或旧隔离版本。 | retry=生成新幂等键;不要覆盖旧键。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体过大,供应商未转发。 | retry=缩小请求体并使用新幂等键。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 429 RATE_LIMITED | 当前项目或凭证进入固定限流窗口。 | retry=等待响应窗口后再试。 - HTTP 502 ADAPTER_FAILURE | 适配器在确认成功前失败,已释放预留 credits。 | retry=修复适配器或请求后使用新幂等键。 - HTTP 502 PROVIDER_CONTRACT_INVALID | 供应商拒绝请求或成功响应不符合公开合同。 | retry=若返回 released 可修正后重试;否则按 manual_review 处理。 - HTTP 503 PROVIDER_UNAVAILABLE | 真实 provider 未启用、凭据缺失、限流或暂时不可用。 | retry=指数退避;先确认不是 manual_review。 - HTTP 400 INVALID_ITEM_REFS | itemRefs 必须包含 2 到 3 项。 | retry=传入 2 到 3 个当前项目 itemRef。 - HTTP 400 INVALID_ITEM_REF | itemRef 必须只含有效 provider 与非空 productId。 | retry=使用未改写的搜索结果 itemRef。 - HTTP 409 PROVIDER_CAPABILITY_UNSUPPORTED | 真实真挑详情只能读取当前项目已有的已验证搜索快照。 | retry=先在同一项目搜索并使用返回的 itemRef。 Retry: 同键同规范请求可安全重放且不二次扣费;202 manual_review 时禁止自动重试。 Idempotency: Idempotency-Key 按 project + operation + 规范请求指纹绑定;改请求返回 409。 Runtime boundary: 真实 provider 与生产流量为 NOT_RUN;默认 provider-disabled 或 local-mock。 ## POST /v1/zhentiao/recommend | recommendZhentiaoItems Summary: 排序推荐已搜索候选 Purpose: 只基于当前项目可读候选与 allowlisted preferences 生成确定性排序。 When: 同项目已有 itemRef,需按 price 或 balanced 偏好排序时调用。 Authentication: 需要具备本操作 scope 的 project-scoped Bearer 业务 Key。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 固定 3 credits(按当前本地规则折合 ¥0.30):转发前 reserve,成功 settle,确定失败 release,不确定结果 manual_review。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 - Authorization | required=true | example=Bearer | 项目所属、具备所需 scope 的 Gateway 业务 Key。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 Request fields: - itemRefs | array | 必填 | {"maxItems":3,"minItems":1} | 1–3 个商品引用;比较操作至少需要 2 个。 - itemRefs[].provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - itemRefs[].productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - preferences | object | 可选 | {"additionalProperties":false} | 推荐允许的偏好对象;当前仅 priority。 - preferences.priority | string | 可选 | {"enum":["price","balanced"]} | 推荐优先级;price 或 balanced。 Request example: {"itemRefs":[{"productId":"sku-example","provider":"jd"}],"preferences":{"priority":"balanced"}} Success: HTTP 200 | Provider result confirmed and credits settled Success example: {"chargedCredits":3,"data":{"items":[{"availability":"unknown","currency":"CNY","highlights":["公开属性示例"],"itemRef":{"productId":"sku-example","provider":"jd"},"priceCents":1990,"reason":"基于当前项目请求生成的候选理由","testOnly":true,"title":"候选商品"}],"method":"deterministic-local-rule","mode":"local-mock","preferences":{"priority":"balanced"}},"operation":"zhentiao.recommend","status":"settled","usage":{"providerCalls":1,"resultCount":1}} Success fields: - status | string | 必填 | {"const":"settled"} | 业务结果、复核项或资源当前稳定状态。 - operation | string | 必填 | {"const":"zhentiao.recommend"} | 固定业务操作标识。 - chargedCredits | integer | 必填 | {"const":3} | chargedCredits 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - data | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开结果对象;具体字段由 operation 决定。 - data.items | array | 必填 | {"maxItems":3} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.items[].title | string | 必填 | {"maxLength":500,"minLength":1} | 经过公开 allowlist 与长度校验的商品标题。 - data.items[].priceCents | integer | 必填 | {"minimum":0} | 商品候选价格,单位为人民币分。 - data.items[].currency | string | 必填 | {"maxLength":8,"minLength":1} | 价格币种;当前固定为 CNY。 - data.items[].availability | string | 必填 | {"enum":["available","unavailable","unknown"]} | 候选可用性;unknown 表示仍需购买前复核。 - data.items[].highlights | array | 必填 | {"maxItems":3} | 当前项目候选的公开亮点,最多返回经过 allowlist 的短文本。 - data.items[].reason | string | 必填 | {"maxLength":500,"minLength":1} | 由当前项目查询衍生的候选理由;只允许所属项目读取。 - data.items[].testOnly | boolean | 必填 | 无附加约束 | 结果是否来自本地合同 fixture;true 表示不能当作真实平台结果。 - data.preferences | object | 必填 | {"additionalProperties":false} | 推荐允许的偏好对象;当前仅 priority。 - data.preferences.priority | string | 必填 | {"enum":["price","balanced"]} | 推荐优先级;price 或 balanced。 - data.method | string | 必填 | {"const":"deterministic-local-rule"} | 推荐所用的公开、确定性方法标识。 - data.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - usage | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开计量对象,不含内部成本或凭证。 - usage.providerCalls | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作实际触发或读取的 provider 调用计数。 - usage.resultCount | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作返回的公开候选或结果数量。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 401 UNAUTHORIZED | Bearer Key 缺失、无效或已撤销。 | retry=换用当前项目有效 Key。 - HTTP 401 KEY_EXPIRED | Bearer Key 已过期。 | retry=创建具备最小 scope 的新 Key。 - HTTP 402 INSUFFICIENT_PAID_CREDITS | 当前项目可用 credits 不足,未转发供应商。 | retry=充值后可用同一业务意图重新请求。 - HTTP 403 FORBIDDEN | Key 不具备本操作所需 scope。 | retry=创建最小所需 scope 的新 Key。 - HTTP 408 REQUEST_TIMEOUT | 请求体读取超时,供应商未确认转发。 | retry=使用新幂等键重试。 - HTTP 409 IDEMPOTENCY_CONFLICT | 幂等键已绑定不同 operation、请求指纹或旧隔离版本。 | retry=生成新幂等键;不要覆盖旧键。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体过大,供应商未转发。 | retry=缩小请求体并使用新幂等键。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 429 RATE_LIMITED | 当前项目或凭证进入固定限流窗口。 | retry=等待响应窗口后再试。 - HTTP 502 ADAPTER_FAILURE | 适配器在确认成功前失败,已释放预留 credits。 | retry=修复适配器或请求后使用新幂等键。 - HTTP 502 PROVIDER_CONTRACT_INVALID | 供应商拒绝请求或成功响应不符合公开合同。 | retry=若返回 released 可修正后重试;否则按 manual_review 处理。 - HTTP 503 PROVIDER_UNAVAILABLE | 真实 provider 未启用、凭据缺失、限流或暂时不可用。 | retry=指数退避;先确认不是 manual_review。 - HTTP 400 INVALID_ITEM_REFS | itemRefs 必须包含 1 到 3 项。 | retry=传入当前项目搜索返回的 itemRef。 - HTTP 400 INVALID_ITEM_REF | itemRef 必须只含有效 provider 与非空 productId。 | retry=使用未改写的搜索结果 itemRef。 - HTTP 400 INVALID_PREFERENCES | preferences 只允许 price 或 balanced priority。 | retry=修正或移除 preferences。 - HTTP 409 PROVIDER_CAPABILITY_UNSUPPORTED | 真实真挑详情只能读取当前项目已有的已验证搜索快照。 | retry=先在同一项目搜索并使用返回的 itemRef。 Retry: 同键同规范请求可安全重放且不二次扣费;202 manual_review 时禁止自动重试。 Idempotency: Idempotency-Key 按 project + operation + 规范请求指纹绑定;改请求返回 409。 Runtime boundary: 真实 provider 与生产流量为 NOT_RUN;默认 provider-disabled 或 local-mock。 ## POST /v1/zhentiao/prepurchase-review | reviewZhentiaoPurchase Summary: 生成购买前复核清单 Purpose: 读取当前项目候选快照,给出价格已知项、库存/到手价未知项与能力限制。 When: 准备跳转购买前,需要提醒用户再次核对实时信息时调用。 Authentication: 需要具备本操作 scope 的 project-scoped Bearer 业务 Key。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 固定 1 credits(按当前本地规则折合 ¥0.10):转发前 reserve,成功 settle,确定失败 release,不确定结果 manual_review。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 - Authorization | required=true | example=Bearer | 项目所属、具备所需 scope 的 Gateway 业务 Key。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 Request fields: - itemRef | object | 必填 | {"additionalProperties":false} | ItemRef 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - requirements | array | 可选 | {"maxItems":5} | 购买前复核的可选短文本要求,最多 5 项。 Request example: {"itemRef":{"productId":"sku-example","provider":"jd"},"requirements":["支持七天无理由"]} Success: HTTP 200 | Provider result confirmed and credits settled Success example: {"chargedCredits":1,"data":{"checks":[{"code":"price","message":"本地样例价 1990 分","status":"known"}],"itemRef":{"productId":"sku-example","provider":"jd"},"limitations":["仅本地合同样例"],"mode":"local-mock","summary":"可作为候选,真实库存、到手价和售后仍待核对"},"operation":"zhentiao.prepurchase_review","status":"settled","usage":{"providerCalls":1,"resultCount":1}} Success fields: - status | string | 必填 | {"const":"settled"} | 业务结果、复核项或资源当前稳定状态。 - operation | string | 必填 | {"const":"zhentiao.prepurchase_review"} | 固定业务操作标识。 - chargedCredits | integer | 必填 | {"const":1} | chargedCredits 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - data | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开结果对象;具体字段由 operation 决定。 - data.itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.summary | string | 必填 | {"minLength":1} | 面向用户的购买前复核摘要。 - data.checks | array | 必填 | 无附加约束 | 购买前逐项复核结果。 - data.checks[].code | string | 必填 | {"minLength":1} | 稳定机器错误码或复核项代码。 - data.checks[].status | string | 必填 | {"enum":["known","unknown"]} | 业务结果、复核项或资源当前稳定状态。 - data.checks[].message | string | 必填 | {"minLength":1} | 面向调用者的安全说明,不应被用于推断重试策略。 - data.limitations | array | 必填 | 无附加约束 | 购买前复核仍存在的能力或运行边界。 - data.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - usage | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开计量对象,不含内部成本或凭证。 - usage.providerCalls | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作实际触发或读取的 provider 调用计数。 - usage.resultCount | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作返回的公开候选或结果数量。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 401 UNAUTHORIZED | Bearer Key 缺失、无效或已撤销。 | retry=换用当前项目有效 Key。 - HTTP 401 KEY_EXPIRED | Bearer Key 已过期。 | retry=创建具备最小 scope 的新 Key。 - HTTP 402 INSUFFICIENT_PAID_CREDITS | 当前项目可用 credits 不足,未转发供应商。 | retry=充值后可用同一业务意图重新请求。 - HTTP 403 FORBIDDEN | Key 不具备本操作所需 scope。 | retry=创建最小所需 scope 的新 Key。 - HTTP 408 REQUEST_TIMEOUT | 请求体读取超时,供应商未确认转发。 | retry=使用新幂等键重试。 - HTTP 409 IDEMPOTENCY_CONFLICT | 幂等键已绑定不同 operation、请求指纹或旧隔离版本。 | retry=生成新幂等键;不要覆盖旧键。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体过大,供应商未转发。 | retry=缩小请求体并使用新幂等键。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 429 RATE_LIMITED | 当前项目或凭证进入固定限流窗口。 | retry=等待响应窗口后再试。 - HTTP 502 ADAPTER_FAILURE | 适配器在确认成功前失败,已释放预留 credits。 | retry=修复适配器或请求后使用新幂等键。 - HTTP 502 PROVIDER_CONTRACT_INVALID | 供应商拒绝请求或成功响应不符合公开合同。 | retry=若返回 released 可修正后重试;否则按 manual_review 处理。 - HTTP 503 PROVIDER_UNAVAILABLE | 真实 provider 未启用、凭据缺失、限流或暂时不可用。 | retry=指数退避;先确认不是 manual_review。 - HTTP 400 INVALID_ITEM_REF | itemRef 必须只含有效 provider 与非空 productId。 | retry=使用未改写的搜索结果 itemRef。 - HTTP 400 INVALID_REQUIREMENTS | requirements 必须是最多 5 项的字符串数组。 | retry=修正或移除 requirements。 - HTTP 409 PROVIDER_CAPABILITY_UNSUPPORTED | 真实真挑详情只能读取当前项目已有的已验证搜索快照。 | retry=先在同一项目搜索并使用返回的 itemRef。 Retry: 同键同规范请求可安全重放且不二次扣费;202 manual_review 时禁止自动重试。 Idempotency: Idempotency-Key 按 project + operation + 规范请求指纹绑定;改请求返回 409。 Runtime boundary: 真实 provider 与生产流量为 NOT_RUN;默认 provider-disabled 或 local-mock。 ## POST /v1/zhentiao/links | generateZhentiaoLinks Summary: 生成已校验商品链接 Purpose: 为 1–3 个 itemRef 请求 allowlisted HTTPS 商品/推广链接,并附推广披露。 When: 用户明确准备打开商品页且 Key 具备 zhentiao:link scope 时调用。 Authentication: 需要具备本操作 scope 的 project-scoped Bearer 业务 Key。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 固定 1 credits(按当前本地规则折合 ¥0.10):转发前 reserve,成功 settle,确定失败 release,不确定结果 manual_review。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 - Authorization | required=true | example=Bearer | 项目所属、具备所需 scope 的 Gateway 业务 Key。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 Request fields: - itemRefs | array | 必填 | {"maxItems":3,"minItems":1} | 1–3 个商品引用;比较操作至少需要 2 个。 - itemRefs[].provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - itemRefs[].productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 Request example: {"itemRefs":[{"productId":"sku-example","provider":"jd"}]} Success: HTTP 200 | Provider result confirmed and credits settled Success example: {"chargedCredits":1,"data":{"disclosure":"部分链接可能为推广链接","items":[{"itemRef":{"productId":"sku-example","provider":"jd"},"productUrl":"https://u.jd.example/p/example"}],"mode":"local-mock"},"operation":"zhentiao.links","status":"settled","usage":{"providerCalls":1,"resultCount":1}} Success fields: - status | string | 必填 | {"const":"settled"} | 业务结果、复核项或资源当前稳定状态。 - operation | string | 必填 | {"const":"zhentiao.links"} | 固定业务操作标识。 - chargedCredits | integer | 必填 | {"const":1} | chargedCredits 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - data | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开结果对象;具体字段由 operation 决定。 - data.items | array | 必填 | {"maxItems":3,"minItems":1} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.items[].productUrl | string | 必填 | {"format":"uri","maxLength":2048,"pattern":"^https://"} | 经过 scheme、host 与端口 allowlist 验证的 HTTPS 商品链接。 - data.disclosure | string | 必填 | {"minLength":1} | 商品链接的推广关系披露;展示链接时必须一并展示。 - data.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - usage | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开计量对象,不含内部成本或凭证。 - usage.providerCalls | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作实际触发或读取的 provider 调用计数。 - usage.resultCount | integer | 必填 | {"maximum":3,"minimum":0} | 本次操作返回的公开候选或结果数量。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 401 UNAUTHORIZED | Bearer Key 缺失、无效或已撤销。 | retry=换用当前项目有效 Key。 - HTTP 401 KEY_EXPIRED | Bearer Key 已过期。 | retry=创建具备最小 scope 的新 Key。 - HTTP 402 INSUFFICIENT_PAID_CREDITS | 当前项目可用 credits 不足,未转发供应商。 | retry=充值后可用同一业务意图重新请求。 - HTTP 403 FORBIDDEN | Key 不具备本操作所需 scope。 | retry=创建最小所需 scope 的新 Key。 - HTTP 408 REQUEST_TIMEOUT | 请求体读取超时,供应商未确认转发。 | retry=使用新幂等键重试。 - HTTP 409 IDEMPOTENCY_CONFLICT | 幂等键已绑定不同 operation、请求指纹或旧隔离版本。 | retry=生成新幂等键;不要覆盖旧键。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体过大,供应商未转发。 | retry=缩小请求体并使用新幂等键。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 429 RATE_LIMITED | 当前项目或凭证进入固定限流窗口。 | retry=等待响应窗口后再试。 - HTTP 502 ADAPTER_FAILURE | 适配器在确认成功前失败,已释放预留 credits。 | retry=修复适配器或请求后使用新幂等键。 - HTTP 502 PROVIDER_CONTRACT_INVALID | 供应商拒绝请求或成功响应不符合公开合同。 | retry=若返回 released 可修正后重试;否则按 manual_review 处理。 - HTTP 503 PROVIDER_UNAVAILABLE | 真实 provider 未启用、凭据缺失、限流或暂时不可用。 | retry=指数退避;先确认不是 manual_review。 - HTTP 400 INVALID_ITEM_REFS | itemRefs 必须包含 1 到 3 项。 | retry=传入当前项目搜索返回的 itemRef。 - HTTP 400 INVALID_ITEM_REF | itemRef 必须只含有效 provider 与非空 productId。 | retry=使用未改写的搜索结果 itemRef。 - HTTP 502 PROVIDER_LINK_FORBIDDEN | provider 返回的商品链接不满足 HTTPS 与 host 白名单。 | retry=不要打开链接;由运维核对 provider。 - HTTP 503 PROVIDER_DISABLED | 真实真挑 provider 在当前配置中关闭。 | retry=不要重试;等待运行配置显式启用。 - HTTP 503 PROVIDER_AUTH_REQUIRED | 真挑 provider 凭据在调用时不可用。 | retry=由运维恢复凭据后再试。 - HTTP 503 PROVIDER_RATE_LIMITED | 真挑 provider 返回限流。 | retry=按 provider 窗口退避后使用新请求。 - HTTP 503 PROVIDER_CAPACITY_EXHAUSTED | 真挑 provider 传输并发容量暂时用尽,尚未转发。 | retry=等待短暂退避后使用新请求。 - HTTP 502 PROVIDER_REQUEST_REJECTED | 真挑 provider 明确拒绝请求。 | retry=修正请求或 provider 配置后使用新幂等键。 - HTTP 502 PROVIDER_REDIRECT_FORBIDDEN | 真挑 provider 返回不允许跟随的重定向。 | retry=不要跟随;由运维修正固定 endpoint。 Retry: 同键同规范请求可安全重放且不二次扣费;202 manual_review 时禁止自动重试。 Idempotency: Idempotency-Key 按 project + operation + 规范请求指纹绑定;改请求返回 409。 Runtime boundary: 真实 provider 与生产流量为 NOT_RUN;默认 provider-disabled 或 local-mock。 ## POST /v1/agent/run | runControlledAgent Summary: 运行受控真挑 Agent 工具 Purpose: 只允许 zhentiao.assist 与固定 search/filter/compare/recommend/prepurchase_review 子操作。 When: 需要统一 Agent 包装且已准备 agent:run scope 时调用;不能生成链接。 Authentication: 需要具备本操作 scope 的 project-scoped Bearer 业务 Key。 Origin: 使用 https://api.funaokeji.com canonical origin;loopback 前缀仅用于本地验收。 CSRF: 不需要;不要发送或复制其他会话的 CSRF 值。 Billing: 固定 5 credits(按当前本地规则折合 ¥0.50):转发前 reserve,成功 settle,确定失败 release,不确定结果 manual_review。 Headers: - Host | required=true | example=api.funaokeji.com | 必须是 Gateway canonical 主机;其他 Host fail closed。 - Accept | required=false | example=application/json | JSON 接口建议声明 application/json;文档端点按其媒体类型返回。 - Idempotency-Key | required=true | example=request-unique-id | 同 project 内绑定 operation 与规范化请求;同键改请求返回 409。 - Authorization | required=true | example=Bearer | 项目所属、具备所需 scope 的 Gateway 业务 Key。 - Content-Type | required=true | example=application/json | 请求体必须是 JSON 对象。 Parameters: - Idempotency-Key | string | 必填 | {"maxLength":128,"minLength":1} | 调用方生成的 project-scoped 唯一键;同键同规范请求重放不二次扣费,同键改请求返回 409。 Request fields: - tool | string | 必填 | {"const":"zhentiao.assist"} | 受控 Agent 工具名;固定为 zhentiao.assist。 - arguments | object | 必填 | 无附加约束 | 受控 Agent 工具参数,只允许 operation 与 payload。 - arguments[operation=search].operation | string | 必填 | {"const":"search"} | 固定业务操作标识。 - arguments[operation=search].payload | object | 必填 | {"additionalProperties":false} | payload 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - arguments[operation=search].payload.query | string | 必填 | {"minLength":1} | 当前项目本次搜索意图;可能影响 reason,不能跨项目共享。 - arguments[operation=search].payload.provider | string | 可选 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - arguments[operation=search].payload.providers | array | 可选 | {"maxItems":3,"minItems":1,"uniqueItems":true} | 搜索时使用的 1–3 个去重 provider。 - arguments[operation=search].payload.filters | object | 可选 | {"additionalProperties":false} | 搜索前允许的公开筛选条件。 - arguments[operation=search].payload.filters.maxPriceCents | integer | 可选 | {"minimum":0} | 允许的最高商品价格,单位为人民币分。 - arguments[operation=search].payload.sort | string | 可选 | {"enum":["price_asc","relevance"]} | 候选排序方式:price_asc 或 relevance。 - arguments[operation=search].payload.limit | integer | 可选 | {"maximum":3,"minimum":1} | 搜索最多返回的候选数,范围 1–3。 - arguments[operation=filter].operation | string | 必填 | {"const":"filter"} | 固定业务操作标识。 - arguments[operation=filter].payload | object | 必填 | {"additionalProperties":false} | payload 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - arguments[operation=filter].payload.itemRefs | array | 必填 | {"maxItems":3,"minItems":1} | 1–3 个商品引用;比较操作至少需要 2 个。 - arguments[operation=filter].payload.itemRefs[].provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - arguments[operation=filter].payload.itemRefs[].productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - arguments[operation=filter].payload.criteria | object | 可选 | {"additionalProperties":false} | 筛选结果实际采用的 allowlisted 条件。 - arguments[operation=filter].payload.criteria.maxPriceCents | integer | 可选 | {"minimum":0} | 允许的最高商品价格,单位为人民币分。 - arguments[operation=compare].operation | string | 必填 | {"const":"compare"} | 固定业务操作标识。 - arguments[operation=compare].payload | object | 必填 | {"additionalProperties":false} | payload 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - arguments[operation=compare].payload.itemRefs | array | 必填 | {"maxItems":3,"minItems":2} | 1–3 个商品引用;比较操作至少需要 2 个。 - arguments[operation=compare].payload.itemRefs[].provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - arguments[operation=compare].payload.itemRefs[].productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - arguments[operation=recommend].operation | string | 必填 | {"const":"recommend"} | 固定业务操作标识。 - arguments[operation=recommend].payload | object | 必填 | {"additionalProperties":false} | payload 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - arguments[operation=recommend].payload.itemRefs | array | 必填 | {"maxItems":3,"minItems":1} | 1–3 个商品引用;比较操作至少需要 2 个。 - arguments[operation=recommend].payload.itemRefs[].provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - arguments[operation=recommend].payload.itemRefs[].productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - arguments[operation=recommend].payload.preferences | object | 可选 | {"additionalProperties":false} | 推荐允许的偏好对象;当前仅 priority。 - arguments[operation=recommend].payload.preferences.priority | string | 可选 | {"enum":["price","balanced"]} | 推荐优先级;price 或 balanced。 - arguments[operation=prepurchase_review].operation | string | 必填 | {"const":"prepurchase_review"} | 固定业务操作标识。 - arguments[operation=prepurchase_review].payload | object | 必填 | {"additionalProperties":false} | payload 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - arguments[operation=prepurchase_review].payload.itemRef | object | 必填 | {"additionalProperties":false} | ItemRef 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - arguments[operation=prepurchase_review].payload.itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - arguments[operation=prepurchase_review].payload.itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - arguments[operation=prepurchase_review].payload.requirements | array | 可选 | {"maxItems":5} | 购买前复核的可选短文本要求,最多 5 项。 Request example: {"arguments":{"operation":"search","payload":{"limit":1,"providers":["jd"],"query":"预算 300 元的耳机"}},"tool":"zhentiao.assist"} Success: HTTP 200 | Provider result confirmed and credits settled Success example: {"chargedCredits":5,"data":{"result":{"operation":"search","result":{"items":[{"availability":"unknown","currency":"CNY","highlights":["公开属性示例"],"itemRef":{"productId":"sku-example","provider":"jd"},"priceCents":1990,"reason":"基于当前项目请求生成的候选理由","testOnly":true,"title":"候选商品"}],"mode":"local-mock","query":"预算 300 元的耳机"}},"tool":"zhentiao.assist"},"operation":"agent.run","status":"settled","usage":{"toolCalls":1}} Success fields: - status | string | 必填 | {"const":"settled"} | 业务结果、复核项或资源当前稳定状态。 - operation | string | 必填 | {"const":"agent.run"} | 固定业务操作标识。 - chargedCredits | integer | 必填 | {"const":5} | chargedCredits 的公开合同字段;类型、必填性与取值限制以本 schema 为准。 - data | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开结果对象;具体字段由 operation 决定。 - data.tool | string | 必填 | {"const":"zhentiao.assist"} | 受控 Agent 工具名;固定为 zhentiao.assist。 - data.result | object | 必填 | 无附加约束 | 受控 Agent 子操作的公开结果,结构由 operation 精确决定。 - data.result[operation=search].operation | string | 必填 | {"const":"search"} | 固定业务操作标识。 - data.result[operation=search].result | object | 必填 | {"additionalProperties":false} | 受控 Agent 子操作的公开结果,结构由 operation 精确决定。 - data.result[operation=search].result.query | string | 必填 | {"minLength":1} | 当前项目本次搜索意图;可能影响 reason,不能跨项目共享。 - data.result[operation=search].result.items | array | 必填 | {"maxItems":3} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.result[operation=search].result.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.result[operation=search].result.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.result[operation=search].result.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.result[operation=search].result.items[].title | string | 必填 | {"maxLength":500,"minLength":1} | 经过公开 allowlist 与长度校验的商品标题。 - data.result[operation=search].result.items[].priceCents | integer | 必填 | {"minimum":0} | 商品候选价格,单位为人民币分。 - data.result[operation=search].result.items[].currency | string | 必填 | {"maxLength":8,"minLength":1} | 价格币种;当前固定为 CNY。 - data.result[operation=search].result.items[].availability | string | 必填 | {"enum":["available","unavailable","unknown"]} | 候选可用性;unknown 表示仍需购买前复核。 - data.result[operation=search].result.items[].highlights | array | 必填 | {"maxItems":3} | 当前项目候选的公开亮点,最多返回经过 allowlist 的短文本。 - data.result[operation=search].result.items[].reason | string | 必填 | {"maxLength":500,"minLength":1} | 由当前项目查询衍生的候选理由;只允许所属项目读取。 - data.result[operation=search].result.items[].testOnly | boolean | 必填 | 无附加约束 | 结果是否来自本地合同 fixture;true 表示不能当作真实平台结果。 - data.result[operation=search].result.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - data.result[operation=filter].operation | string | 必填 | {"const":"filter"} | 固定业务操作标识。 - data.result[operation=filter].result | object | 必填 | {"additionalProperties":false} | 受控 Agent 子操作的公开结果,结构由 operation 精确决定。 - data.result[operation=filter].result.items | array | 必填 | {"maxItems":3} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.result[operation=filter].result.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.result[operation=filter].result.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.result[operation=filter].result.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.result[operation=filter].result.items[].title | string | 必填 | {"maxLength":500,"minLength":1} | 经过公开 allowlist 与长度校验的商品标题。 - data.result[operation=filter].result.items[].priceCents | integer | 必填 | {"minimum":0} | 商品候选价格,单位为人民币分。 - data.result[operation=filter].result.items[].currency | string | 必填 | {"maxLength":8,"minLength":1} | 价格币种;当前固定为 CNY。 - data.result[operation=filter].result.items[].availability | string | 必填 | {"enum":["available","unavailable","unknown"]} | 候选可用性;unknown 表示仍需购买前复核。 - data.result[operation=filter].result.items[].highlights | array | 必填 | {"maxItems":3} | 当前项目候选的公开亮点,最多返回经过 allowlist 的短文本。 - data.result[operation=filter].result.items[].reason | string | 必填 | {"maxLength":500,"minLength":1} | 由当前项目查询衍生的候选理由;只允许所属项目读取。 - data.result[operation=filter].result.items[].testOnly | boolean | 必填 | 无附加约束 | 结果是否来自本地合同 fixture;true 表示不能当作真实平台结果。 - data.result[operation=filter].result.criteria | object | 必填 | {"additionalProperties":false} | 筛选结果实际采用的 allowlisted 条件。 - data.result[operation=filter].result.criteria.maxPriceCents | integer | 可选 | {"minimum":0} | 允许的最高商品价格,单位为人民币分。 - data.result[operation=filter].result.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - data.result[operation=compare].operation | string | 必填 | {"const":"compare"} | 固定业务操作标识。 - data.result[operation=compare].result | object | 必填 | {"additionalProperties":false} | 受控 Agent 子操作的公开结果,结构由 operation 精确决定。 - data.result[operation=compare].result.items | array | 必填 | {"maxItems":3,"minItems":2} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.result[operation=compare].result.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.result[operation=compare].result.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.result[operation=compare].result.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.result[operation=compare].result.items[].title | string | 必填 | {"maxLength":500,"minLength":1} | 经过公开 allowlist 与长度校验的商品标题。 - data.result[operation=compare].result.items[].priceCents | integer | 必填 | {"minimum":0} | 商品候选价格,单位为人民币分。 - data.result[operation=compare].result.items[].currency | string | 必填 | {"maxLength":8,"minLength":1} | 价格币种;当前固定为 CNY。 - data.result[operation=compare].result.items[].availability | string | 必填 | {"enum":["available","unavailable","unknown"]} | 候选可用性;unknown 表示仍需购买前复核。 - data.result[operation=compare].result.items[].highlights | array | 必填 | {"maxItems":3} | 当前项目候选的公开亮点,最多返回经过 allowlist 的短文本。 - data.result[operation=compare].result.items[].reason | string | 必填 | {"maxLength":500,"minLength":1} | 由当前项目查询衍生的候选理由;只允许所属项目读取。 - data.result[operation=compare].result.items[].testOnly | boolean | 必填 | 无附加约束 | 结果是否来自本地合同 fixture;true 表示不能当作真实平台结果。 - data.result[operation=compare].result.dimensions | array | 必填 | 无附加约束 | 比较响应实际使用的公开维度列表。 - data.result[operation=compare].result.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - data.result[operation=recommend].operation | string | 必填 | {"const":"recommend"} | 固定业务操作标识。 - data.result[operation=recommend].result | object | 必填 | {"additionalProperties":false} | 受控 Agent 子操作的公开结果,结构由 operation 精确决定。 - data.result[operation=recommend].result.items | array | 必填 | {"maxItems":3} | 当前响应中的条目列表;其 owner 范围由当前 Gateway project 决定。 - data.result[operation=recommend].result.items[].itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.result[operation=recommend].result.items[].itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.result[operation=recommend].result.items[].itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.result[operation=recommend].result.items[].title | string | 必填 | {"maxLength":500,"minLength":1} | 经过公开 allowlist 与长度校验的商品标题。 - data.result[operation=recommend].result.items[].priceCents | integer | 必填 | {"minimum":0} | 商品候选价格,单位为人民币分。 - data.result[operation=recommend].result.items[].currency | string | 必填 | {"maxLength":8,"minLength":1} | 价格币种;当前固定为 CNY。 - data.result[operation=recommend].result.items[].availability | string | 必填 | {"enum":["available","unavailable","unknown"]} | 候选可用性;unknown 表示仍需购买前复核。 - data.result[operation=recommend].result.items[].highlights | array | 必填 | {"maxItems":3} | 当前项目候选的公开亮点,最多返回经过 allowlist 的短文本。 - data.result[operation=recommend].result.items[].reason | string | 必填 | {"maxLength":500,"minLength":1} | 由当前项目查询衍生的候选理由;只允许所属项目读取。 - data.result[operation=recommend].result.items[].testOnly | boolean | 必填 | 无附加约束 | 结果是否来自本地合同 fixture;true 表示不能当作真实平台结果。 - data.result[operation=recommend].result.preferences | object | 必填 | {"additionalProperties":false} | 推荐允许的偏好对象;当前仅 priority。 - data.result[operation=recommend].result.preferences.priority | string | 必填 | {"enum":["price","balanced"]} | 推荐优先级;price 或 balanced。 - data.result[operation=recommend].result.method | string | 必填 | {"const":"deterministic-local-rule"} | 推荐所用的公开、确定性方法标识。 - data.result[operation=recommend].result.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - data.result[operation=prepurchase_review].operation | string | 必填 | {"const":"prepurchase_review"} | 固定业务操作标识。 - data.result[operation=prepurchase_review].result | object | 必填 | {"additionalProperties":false} | 受控 Agent 子操作的公开结果,结构由 operation 精确决定。 - data.result[operation=prepurchase_review].result.itemRef | object | 必填 | {"additionalProperties":false} | 固定 provider 与其 canonical productId 组成的商品引用。 - data.result[operation=prepurchase_review].result.itemRef.provider | string | 必填 | {"enum":["douyin","jd","pinduoduo"]} | 固定 allowlist 中的 provider 名称。 - data.result[operation=prepurchase_review].result.itemRef.productId | string | 必填 | {"maxLength":500,"minLength":1} | provider 内的 canonical 商品标识;区分大小写并在验证后去除边缘空白。 - data.result[operation=prepurchase_review].result.summary | string | 必填 | {"minLength":1} | 面向用户的购买前复核摘要。 - data.result[operation=prepurchase_review].result.checks | array | 必填 | 无附加约束 | 购买前逐项复核结果。 - data.result[operation=prepurchase_review].result.checks[].code | string | 必填 | {"minLength":1} | 稳定机器错误码或复核项代码。 - data.result[operation=prepurchase_review].result.checks[].status | string | 必填 | {"enum":["known","unknown"]} | 业务结果、复核项或资源当前稳定状态。 - data.result[operation=prepurchase_review].result.checks[].message | string | 必填 | {"minLength":1} | 面向调用者的安全说明,不应被用于推断重试策略。 - data.result[operation=prepurchase_review].result.limitations | array | 必填 | 无附加约束 | 购买前复核仍存在的能力或运行边界。 - data.result[operation=prepurchase_review].result.mode | string | 必填 | {"enum":["local-mock","truepick-http"]} | 结果来源模式;local-mock 与 truepick-http 不会混用。 - usage | object | 必填 | {"additionalProperties":false} | 本次业务操作的公开计量对象,不含内部成本或凭证。 - usage.toolCalls | integer | 必填 | {"const":1} | 受控 Agent 本次执行的工具调用次数;当前固定为 1。 Errors: - HTTP 400 REQUEST_TARGET_INVALID | HTTP request-target 不是安全的 origin-form 路径。 | retry=改用以单个 / 开头且不含 authority、反斜杠、控制字符或编码分隔符的路径。 - HTTP 400 TRANSFER_ENCODING_UNSUPPORTED | 服务不接受 Transfer-Encoding 请求体。 | retry=移除 Transfer-Encoding 并发送唯一、正确的 Content-Length。 - HTTP 400 CONTENT_LENGTH_INVALID | Content-Length 重复、格式错误或超出允许位数。 | retry=发送唯一的非负十进制 Content-Length。 - HTTP 400 REQUEST_BODY_INCOMPLETE | 实际收到的请求体短于 Content-Length。 | retry=确认客户端完整发送请求体后发起新请求。 - HTTP 400 INVALID_JSON | 请求体不是 UTF-8 JSON 对象。 | retry=修正 JSON 编码与对象结构后重试。 - HTTP 400 UNKNOWN_FIELDS | 请求包含本操作合同以外的字段。 | retry=删除未知字段后重试。 - HTTP 500 INTERNAL_ERROR | 服务端未能完成公开写请求。 | retry=指数退避;幂等操作保留原键,非幂等操作先核对状态。 - HTTP 400 IDEMPOTENCY_KEY_REQUIRED | Idempotency-Key 缺失、为空或超过 128 字符。 | retry=提供有效的新幂等键。 - HTTP 401 UNAUTHORIZED | Bearer Key 缺失、无效或已撤销。 | retry=换用当前项目有效 Key。 - HTTP 401 KEY_EXPIRED | Bearer Key 已过期。 | retry=创建具备最小 scope 的新 Key。 - HTTP 402 INSUFFICIENT_PAID_CREDITS | 当前项目可用 credits 不足,未转发供应商。 | retry=充值后可用同一业务意图重新请求。 - HTTP 403 FORBIDDEN | Key 不具备本操作所需 scope。 | retry=创建最小所需 scope 的新 Key。 - HTTP 408 REQUEST_TIMEOUT | 请求体读取超时,供应商未确认转发。 | retry=使用新幂等键重试。 - HTTP 409 IDEMPOTENCY_CONFLICT | 幂等键已绑定不同 operation、请求指纹或旧隔离版本。 | retry=生成新幂等键;不要覆盖旧键。 - HTTP 413 PAYLOAD_TOO_LARGE | 请求体过大,供应商未转发。 | retry=缩小请求体并使用新幂等键。 - HTTP 421 HOST_NOT_ALLOWED | Host 不属于 Gateway 精确允许列表。 | retry=改用 canonical Host。 - HTTP 429 RATE_LIMITED | 当前项目或凭证进入固定限流窗口。 | retry=等待响应窗口后再试。 - HTTP 502 ADAPTER_FAILURE | 适配器在确认成功前失败,已释放预留 credits。 | retry=修复适配器或请求后使用新幂等键。 - HTTP 502 PROVIDER_CONTRACT_INVALID | 供应商拒绝请求或成功响应不符合公开合同。 | retry=若返回 released 可修正后重试;否则按 manual_review 处理。 - HTTP 503 PROVIDER_UNAVAILABLE | 真实 provider 未启用、凭据缺失、限流或暂时不可用。 | retry=指数退避;先确认不是 manual_review。 - HTTP 403 TOOL_NOT_ALLOWED | tool 不是唯一允许的 zhentiao.assist。 | retry=改用公开允许的 tool。 - HTTP 400 INVALID_ARGUMENTS | arguments 必须是对象。 | retry=提供 operation 与 payload 对象。 - HTTP 403 TOOL_OPERATION_NOT_ALLOWED | Agent 子操作不在固定白名单。 | retry=改用公开允许的子操作。 - HTTP 400 INVALID_QUERY | search query 必须是非空字符串。 | retry=提供非空 query。 - HTTP 400 PROVIDER_NOT_ALLOWED | provider 或 providers 不在固定真挑 registry。 | retry=改用公开允许的 provider。 - HTTP 400 INVALID_LIMIT | search limit 必须是 1 到 3 的整数。 | retry=修正 limit。 - HTTP 400 INVALID_SORT | search sort 不在白名单。 | retry=改用公开 sort。 - HTTP 400 INVALID_FILTERS | filters 或 criteria 不符合公开结构。 | retry=修正筛选条件。 - HTTP 400 INVALID_ITEM_REFS | itemRefs 数量不符合所选子操作。 | retry=使用该子操作要求的 itemRef 数量。 - HTTP 400 INVALID_ITEM_REF | itemRef 结构或内容无效。 | retry=使用未改写的搜索结果 itemRef。 - HTTP 400 INVALID_PREFERENCES | recommend preferences 不在白名单。 | retry=改用 price 或 balanced。 - HTTP 400 INVALID_REQUIREMENTS | prepurchase_review requirements 结构无效。 | retry=传最多 5 项字符串数组。 - HTTP 409 PROVIDER_CAPABILITY_UNSUPPORTED | 真实真挑详情只能读取当前项目已有的已验证搜索快照。 | retry=先在同一项目搜索并使用返回的 itemRef。 - HTTP 503 PROVIDER_DISABLED | 真实真挑 provider 在当前配置中关闭。 | retry=不要重试;等待运行配置显式启用。 - HTTP 503 PROVIDER_AUTH_REQUIRED | 真挑 provider 凭据在调用时不可用。 | retry=由运维恢复凭据后再试。 - HTTP 503 PROVIDER_RATE_LIMITED | 真挑 provider 返回限流。 | retry=按 provider 窗口退避后使用新请求。 - HTTP 503 PROVIDER_CAPACITY_EXHAUSTED | 真挑 provider 传输并发容量暂时用尽,尚未转发。 | retry=等待短暂退避后使用新请求。 - HTTP 502 PROVIDER_REQUEST_REJECTED | 真挑 provider 明确拒绝请求。 | retry=修正请求或 provider 配置后使用新幂等键。 - HTTP 502 PROVIDER_REDIRECT_FORBIDDEN | 真挑 provider 返回不允许跟随的重定向。 | retry=不要跟随;由运维修正固定 endpoint。 Retry: 同键同规范请求可安全重放且不二次扣费;202 manual_review 时禁止自动重试。 Idempotency: Idempotency-Key 按 project + operation + 规范请求指纹绑定;改请求返回 409。 Runtime boundary: 真实 provider 与生产流量为 NOT_RUN;默认 provider-disabled 或 local-mock。 Global runtime boundary: local fake SMS, local simulated payment, and fake providers are test seams only. Domains: peipao.funaokeji.com is coaching-only; api.funaokeji.com is Gateway-only. Every other Host fails closed. Local compatibility: loopback preview keeps /gateway paths; they are not the public canonical contract. NOT_RUN: real SMS delivery, production OneAuth, real payment/refunds/invoices, real providers, production deployment/DNS/certificates. Do not send phones/emails in URLs or query strings. Do not expose passwords, sessions, CSRF values, full API keys, verification codes, or provider credentials.