# CallAI 订阅开放 API v1 Base URL:`https://redeem.callai.one/api/open/v1`(兼容入口)或 `https://protocol.callai.one/api/open/v1` 不会使用 API 的用户可直接打开 `https://protocol.callai.one`,填写协议 CDK、Session 和支付卡,再选择套餐与地区。网页复用同一接口、次数与订单记录。 接口采用 JSON over HTTPS。除本文档外全部使用 POST;不接受 URL Query。 这是订阅代办接口,不是模型推理接口。内部复用现有订阅执行流程,包括官方支付页面和安全验证。 ## 开放开关 默认关闭。在管理员后台「自助兑换 → 设置 → 订阅开放 API」勾选「开放订阅 API」并保存后,才接受新 API 订单。正常执行同时受官方付款总开关与兑换总开关控制。 关闭 API 开关只停止新的 API 订单;已受理订单、查询、同单幂等重放继续可用,普通自助兑换不受此开关影响。文档始终可访问。首次部署保持关闭,由管理员手动决定开放时间。 ## API 专用 CDK 在管理员后台「自助兑换 → CDK 管理 → 生成 CDK」选择「开放 API 订阅 · 多次使用」,填写每个 CDK 的使用次数。 - 同一个 CDK 可用于 Go、Plus、Pro 5x、Pro 20x、Pro Max,不绑定套餐。 - 每笔订单受理时预占 1 次;付款明确成功后结算 1 次,取消自动续费结果不影响结算。 - 明确失败且没有待核验付款/资金时释放次数,失败的 API 订单不再重新执行。 - 付款结果不明、人工验证中仍占用次数。不要更换订单号重复付款。 - 每个 CDK 最多同时保留 5 笔处理中订单;执行并发仍受平台总并发控制。 - CDK 次数只是本服务的使用次数。订阅费用从调用方提交的银行卡扣除;不会从平台卡池取卡,也不代为开卡、补款。 - 禁用/到期阻止新订单;原订单继续执行,原 CDK 仍可查单。恢复不重置次数或有效期。 - 普通单次兑换码不能作为 API CDK;API CDK 不能在普通兑换页面直接开通。 ## 认证与幂等 ```http Content-Type: application/json X-API-Key: API-SUB-你的完整CDK Idempotency-Key: shop-20261011-order0001 ``` `X-API-Key` 直接使用完整 API CDK,只保存在调用方服务端。 没有另发 Secret,不使用卡台的 HMAC 签名,也不能直接替换卡台域名后调用。 创建订单必须提供 `Idempotency-Key`(8–128 位)及 `client_order_no`(1–128 位),允许字母、数字、`_ . : -`。 两者均在当前 CDK 内唯一。重放时必须保留原订单号、幂等键、请求内容;JSON 字段顺序不影响去重。 变更 Session、卡片、地区、金额或套餐时不视为同一请求,会拒绝冲突。 网络超时先查原单;未查到可以原样重放。不要随机生成新订单号重付。 明确返回 `status=failed`、`usage_status=released` 后,才可修正资料并使用新的订单号重新提交。 响应: ```json {"code":0,"msg":"ok","data":{}} ``` `code=0` 仅表示接口调用成功。订阅是否成功以 `data.status` 为准。 错误时 `code` 为稳定字符串、`msg` 为说明、`data=null`,同时返回相应 HTTP 状态。 所有响应 `Cache-Control: no-store`,不会返回账号 Session、完整卡资料或供应商凭据。 ## 接口一览 | 接口 | 请求体 | 用途 | |---|---|---| | `getSubscriptionCatalog` | `{}` | 可用套餐、已知地区/币种及并发上限 | | `getAccountBalance` | `{}` | 查询 CDK 总次数、已用、预占、剩余 | | `createSubscription` | 见下文 | 受理一笔订阅;返回 202,新任务异步执行 | | `getSubscription` | `{"orderId":"123"}` | 查询本 CDK 的订单 | | `getSubscriptionList` | `{"page":1,"page_size":20}` | 本 CDK 的订单列表,最多 100 条/页 | `getSubscription` 也接受 `task_no` 或 `client_order_no`,三者只能提交一个。 查单只读取本地已记录结果,不触发新的付款请求。建议每 5 秒查询一次,收到 429 后退避。 默认限流:每 IP 180 次/分钟,每 CDK 120 次/分钟,创建请求另限 10 次/分钟(含重放)。 请求体上限 128 KiB。 ## 创建订阅 ```json { "client_order_no":"shop-0001", "plan_type":"plus", "country":"PH", "currency":"PHP", "card":"卡号----12/29----CVC", "session_json":{ "user":{"email":"buyer@example.test"}, "account":{"id":"目标个人空间ID"}, "accessToken":"目标账号真实值", "sessionToken":"目标账号真实值", "expires":"目标账号原始有效期" }, "authorized":true } ``` 上例是字段说明,不能直接执行。 | 字段 | 说明 | |---|---| | `plan_type` | `go`、`plus`、`pro_5x`、`pro_20x`、`pro_max`,月付 | | `country` | 两位开通地区代码,由调用方指定,例如 PH、US、CL | | `currency` | 对应币种,例如 PHP、USD、CLP;已知国家可省略并使用目录默认币种,其他国家必须显式提供 | | `max_amount` | 可选,当前币种的最高授权扣款额,十进制字符串;传入时超过上限不会付款。不传时不设置金额上限,调用方应自行确认价格并授权实际订阅扣款。协议网页不传此字段 | | `card` | 只需卡号、有效期、CVC,以 **4 个横杠**分隔;账单资料由现有付款流程自动生成 | | `session_json` | 完整 Session 对象或包含该对象的 JSON 字符串;必须含有效 AT、SessionToken、邮箱及正确个人空间 | | `authorized` | 必须是 `true`,表示已取得该账号订阅与所提交银行卡的付款授权 | 卡片支持三种等价写法: ```text 卡号----MM/YY----CVC 卡号----MM/YYYY----CVC 卡号----MM----YYYY----CVC ``` 不接受卡台卡 ID,不需要提供账单地址、卡台密钥或代理。地区代理由服务端选择。 账号资格在后台付款前核验;目前支持无有效个人订阅的账号新开订阅,不支持覆盖有效订阅、升档或 Team 空间。 服务保留有限的网络恢复与验证码重试;同一业务请求始终查询原订单,不能根据 HTTP 超时另建付款。 ## 查询次数 ```json { "code":0,"msg":"ok","data":{ "total":100,"used":20,"reserved":2,"remaining":78, "status":"available","expires_at":null } } ``` `remaining = total - used - reserved`。没有另外的钱包金额。 ## 订单结果 ```json { "code":0,"msg":"ok","data":{ "orderId":"123","task_no":"123","client_order_no":"shop-0001", "plan_type":"plus","targetEmail":"buyer@example.test", "status":"succeeded","usage_status":"settled", "subscription_succeeded":true,"subscriptionCancelled":true, "action_required":null,"error_code":"","message":"", "created_at":"2026-10-11T01:00:00+00:00", "updated_at":"2026-10-11T01:02:00+00:00" } } ``` | `status` | 含义 | 次数 | |---|---|---| | `pending` | 排队中 | `reserved` 预占 | | `processing` | 正在开通、验证或核验原付款 | `reserved` 预占 | | `succeeded` | 付款已明确成功 | `settled` 已使用 | | `failed` | 已结束且明确未成功 | `released` 已释放 | 订单结果额外包含 `country`、`currency`、`timing`。`timing.elapsed_seconds` 为从受理到付款确认的开通用时,处理中为已等待时长;不包含取消续费等待。 `subscriptionCancelled`:`true` 已取消续费;`false` 本次取消失败;`null` 尚无明确结果。 成功付款后可能稍晚更新取消结果,需查原单查看,不会因此重复扣 CDK 次数。 套餐到账可能有短暂延迟,成功标准以已确认付款为准。 ## 人工验证 需要人工完成时返回: ```json { "status":"processing", "action_required":"verification", "verification_url":"https://redeem.callai.one/#verification=本订单临时令牌" } ``` API 调用方可把完整 `verification_url` 交给对应客户,在浏览器打开并完成安全验证,随后继续查询原订单。协议网页则直接在本页接续同一笔付款的验证,无需跳转到普通兑换首页。 链接有效 24 小时,到期重新查单获取。链接仅可查看与验证这一笔订单,不能消耗 CDK 剩余次数或访问其他订单。 不会向客户暴露 API CDK。 `action_required=review` / `error_code=result_pending_review` 表示付款结果仍不确定,应继续查询并联系平台核验,不要新建同账号付款。 ## Python 调用示例 ```python import json import os import requests base = "https://redeem.callai.one/api/open/v1" headers = {"X-API-Key": os.environ["CALLAI_CDK"]} # order.json 放调用方已确认的真实请求资料,不写到公开仓库或日志。 with open("order.json", encoding="utf-8") as f: order = json.load(f) headers["Idempotency-Key"] = "shop-20261011-order0001" # 为此笔业务固定保存 r = requests.post(base + "/createSubscription", headers=headers, json=order, timeout=30) r.raise_for_status() result = r.json() if result["code"] != 0: raise RuntimeError(result["msg"]) order_id = result["data"]["orderId"] # 调用方按至少 5 秒间隔查询,遇 429 退避;不要用新订单号处理超时。 r = requests.post(base + "/getSubscription", headers=headers, json={"orderId": order_id}, timeout=15) r.raise_for_status() print(r.json()["data"]["status"]) ``` 常见错误:`api_disabled`(403,未开放接单)、`unauthorized`(401)、`not_found`(404)、`rate_limited`(429)、`invalid_request`(400,含次数不足/参数冲突)、`temporarily_unavailable`(503)。停用、过期及次数耗尽的 CDK 仍可查询历史订单。