积分与计费
网页型智能体可以在用户确认一次业务消费后,由开发者服务端调用小雅开放 API 扣积分;业务最终失败且原扣费已经成功时,再按原订单退积分。MCP 工具如果已经声明 xiaoya/pricePoints,由平台自动确认、扣费和退款,开发者不得重复调用 /charge。
调用前准备
- Personal 余额需要
balanceScope;扣费和退款需要charge;用量汇总需要usage。 - Team 操作需要绑定 URL 中精确
team_id的 Team Token 和对应 Scope。 - Access Token 只能保存在可信服务端,通过
Authorization: Bearer <token>发送。 points是 1–1,000,000,000,000 的整数;幂等键长度为 8–64。
查询 Personal 余额
curl 'https://claw.zhenhuiai.com/api/v1/open/balance' \
--header 'Authorization: Bearer <personal-access-token>' \
--header 'Accept: application/json'{
"success": true,
"data": {
"subscription": 80,
"gift_card": 20,
"recharge": 100,
"total": 200
},
"request_id": "req_balance_01"
}subscription、gift_card、recharge 分别是套餐、礼品卡和充值积分,total 是当前总和。余额只用于展示;并发情况下只有 /charge 的原子结果有效。
扣除 Personal 积分
先在开发者数据库创建 pending 订单并保存稳定幂等键:
curl --request POST 'https://claw.zhenhuiai.com/api/v1/open/charge' \
--header 'Authorization: Bearer <personal-access-token>' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"points": 20,
"reason": "生成单图落地页",
"idempotencyKey": "order_20260830_000001"
}'{
"success": true,
"data": {
"chargedPoints": 20,
"balance": {
"subscription": 60,
"gift_card": 20,
"recharge": 100,
"total": 180
}
},
"request_id": "req_charge_01"
}| 请求字段 | 规则 |
|---|---|
points | 可信服务端按商品或订单生成的整数积分 |
reason | 1–100 字符的稳定业务说明,不放个人敏感信息 |
idempotencyKey | 8–64 字符的稳定订单键;同一业务重试必须完全相同 |
相同键、积分和原因重试会返回相同业务结果;相同键配不同参数会返回 BALANCE_IDEMPOTENCY_CONFLICT。
退回 Personal 积分
退款必须引用原扣费键,并为退款本身生成另一个稳定键:
curl --request POST 'https://claw.zhenhuiai.com/api/v1/open/refund' \
--header 'Authorization: Bearer <personal-access-token>' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"points": 20,
"reason": "生成失败退款",
"chargeIdempotencyKey": "order_20260830_000001",
"idempotencyKey": "refund_20260830_000001"
}'{
"success": true,
"data": {
"refundedPoints": 20,
"balance": {
"subscription": 80,
"gift_card": 20,
"recharge": 100,
"total": 200
}
},
"request_id": "req_refund_01"
}不得跨用户、跨智能体或跨原订单退款,累计退款不得超过原扣费。只有确认原扣费成功且业务最终失败时才退款。
查询 Personal 用量
curl 'https://claw.zhenhuiai.com/api/v1/open/usage' \
--header 'Authorization: Bearer <personal-access-token>'{
"success": true,
"data": {
"chargedPoints": 100,
"refundedPoints": 20,
"netPoints": 80,
"modelUsage": {
"requestCount": 3,
"inputTokens": 1200,
"outputTokens": 360,
"cacheReadTokens": 0,
"cacheWriteTokens": 0,
"imageCount": 0,
"chargedPoints": 12
}
},
"request_id": "req_usage_01"
}/usage 仅接受 Personal Token;Team 概览不是相同粒度的替代接口。
创建者赞助的公开会话
已发布智能体的创建者可以使用带 model Scope 的 Personal-bound Token 创建最多一小时有效的短期赞助会话;Team-bound Token 不得静默转为个人扣费:
curl --request POST 'https://claw.zhenhuiai.com/api/v1/open/public-billing-sessions' \
--header 'Authorization: Bearer <personal-creator-access-token>' \
--header 'Content-Type: application/json' \
--data '{"expires_in_seconds":900,"max_points":1000,"max_calls":100}'返回的短期 accessToken 只能保存在业务服务端会话中,用于调用模型或 TTS 网关,不得发给浏览器。max_points 与 max_calls 由两类网关共享并在调用供应商前原子预留;过期、撤销或任一预算用尽后都拒绝新调用。结束时调用 DELETE /api/v1/open/public-billing-sessions/{id} 撤销。创建者长期 Token、短期赞助 Token 和完整输入都不得写入日志或模型上下文。
Team 余额、扣费与退款
curl 'https://claw.zhenhuiai.com/api/v1/open/teams/team_01/balance' \
--header 'Authorization: Bearer <team-access-token>'{
"success": true,
"data": {
"teamId": "team_01",
"memberId": "member_01",
"role": "member",
"balancePoints": 860,
"balancePointsDecimal": "860",
"walletBalancePoints": 12500,
"quotaLimit": 1000,
"quotaUsed": 140,
"quotaRemaining": 860
},
"request_id": "req_team_balance_01"
}Team 扣费请求没有 reason 字段:
curl --request POST 'https://claw.zhenhuiai.com/api/v1/open/teams/team_01/charge' \
--header 'Authorization: Bearer <team-access-token>' \
--header 'Content-Type: application/json' \
--data '{"points":20,"idempotencyKey":"team_order_20260830_0001"}'{
"success": true,
"data": {
"teamId": "team_01",
"chargeLedgerId": "ledger_01",
"chargedPoints": 20,
"chargedPointsDecimal": "20",
"balancePoints": 840,
"balancePointsDecimal": "840",
"walletBalancePoints": 12480,
"quotaUsed": 160
},
"request_id": "req_team_charge_01"
}curl --request POST 'https://claw.zhenhuiai.com/api/v1/open/teams/team_01/refund' \
--header 'Authorization: Bearer <team-access-token>' \
--header 'Content-Type: application/json' \
--data '{
"points":20,
"chargeIdempotencyKey":"team_order_20260830_0001",
"idempotencyKey":"team_refund_20260830_0001"
}'{
"success": true,
"data": {
"teamId": "team_01",
"refundLedgerId": "ledger_02",
"requestedPoints": 20,
"requestedPointsDecimal": "20",
"refundedPoints": 20,
"refundedPointsDecimal": "20",
"unrecoveredPoints": 0,
"unrecoveredPointsDecimal": "0",
"balancePoints": 860,
"balancePointsDecimal": "860",
"walletBalancePoints": 12500,
"quotaUsed": 140
},
"request_id": "req_team_refund_01"
}业务层应以 refundedPoints 判断实际退款数量;unrecoveredPoints 表示因原积分来源状态等原因未恢复的积分。
Node.js 服务端示例
下载 Skill 后可复用 assets/example-mcp/src/xiaoya-open-api.mjs:
import { XiaoyaOpenApiClient } from './xiaoya-open-api.mjs';
const client = new XiaoyaOpenApiClient({
platformBaseUrl: process.env.XIAOYA_BASE_URL,
accessToken: process.env.XIAOYA_ACCESS_TOKEN
});
await client.balance();
await client.charge({
points: 20,
reason: '生成单图落地页',
idempotencyKey: 'order_20260830_000001'
});
await client.refund({
points: 20,
reason: '生成失败退款',
chargeIdempotencyKey: 'order_20260830_000001',
idempotencyKey: 'refund_20260830_000001'
});
await client.teamBalance('team_01');
await client.teamCharge('team_01', { points: 20, idempotencyKey: 'team_order_20260830_0001' });
await client.teamRefund('team_01', {
points: 20,
chargeIdempotencyKey: 'team_order_20260830_0001',
idempotencyKey: 'team_refund_20260830_0001'
});客户端默认使用 10 秒超时、拒绝重定向并校验统一响应 envelope。浏览器不要直接实例化该客户端。
错误与重试
{
"success": false,
"code": "INSUFFICIENT_POINTS",
"message": "The account does not have enough points",
"request_id": "req_error_01"
}| HTTP | 错误码 | 处理 |
|---|---|---|
| 402 | INSUFFICIENT_POINTS | 余额不足,不继续业务写入 |
| 403 | OPEN_AGENT_SCOPE_REQUIRED | 重新授权所需 Scope |
| 403 | TEAM_CONTEXT_MISMATCH | 不得混用 Personal/Team 或不同 Team |
| 404 | OPEN_AGENT_CHARGE_NOT_FOUND | Personal 原扣费不存在或不属于当前上下文 |
| 404 | OPEN_AGENT_TEAM_CHARGE_NOT_FOUND | Team 原扣费不存在或不属于当前上下文 |
| 409 | BALANCE_IDEMPOTENCY_CONFLICT | 同一键参数不一致,停止自动重试并检查订单 |
| 409 | TEAM_CREDIT_IDEMPOTENCY_CONFLICT | Team 幂等参数冲突,停止自动重试 |
| 422 | OPEN_AGENT_CHARGE_LIMIT_EXCEEDED | 超过当前智能体单笔上限 |
| 422 | OPEN_AGENT_REFUND_EXCEEDS_CHARGE | Personal 累计退款超过原扣费 |
| 422 | TEAM_CREDIT_REFUND_EXCEEDS_CHARGE | Team 累计退款超过原扣费 |
网络超时或 5xx 时结果可能未知:扣费重试继续使用原扣费键,退款重试继续使用原退款键;不要生成新键,也不要在外部 HTTP 请求期间持有数据库事务。日志只保留错误码和 request_id。
字段的权威 Schema 见完整 API 参考。
