余额与用量查询
生产环境如何健壮地监控余额、API Key 限速和请求成本。
查询接口概览
GET /v1/wallet— 当前余额、冻结额、可用额(Console JWT)GET /v1/keys— API Key 限速、预算、Token 上限、过期时间与备注(Console JWT)GET /v1/wallet/transactions— 交易流水分页(Console JWT)GET /v1/monitoring/usage/summary— 用量汇总(Console JWT)
注意这些是**平台 API**,用 JWT 认证,不是
sk-swx-*。用 SDK 客户端不能直接用。 登录后通过 Console → 设置可以生成长期 personal access token 调用这些接口。推荐的监控模式
1. 定时低频查询(每分钟)
python
import httpx
import time
def get_wallet_balance(jwt):
r = httpx.get(
"http://api.swarmixtoken.com/v1/wallet",
headers={"Authorization": f"Bearer {jwt}"},
)
r.raise_for_status()
return r.json()
while True:
w = get_wallet_balance(JWT)
print(f"余额 ¥{w['balance']:.2f}, 冻结 ¥{w['frozen']:.2f}")
if w["available"] < 10:
send_alert("低余额")
time.sleep(60)2. 请求前预检(高 QPS 慎用)
如果你做 SaaS 转卖,需要在每次用户下单时检查余额:
python
def forward_request(user_request):
# 不要在每次都查 /v1/wallet — 太慢,加缓存
if not has_budget_cached(user_id):
return 402, "Insufficient budget"
# 转发到 Swarmix
return swarmix_client.chat.completions.create(**user_request)Swarmix 本身在余额不足时会直接返回 402 给客户端,你不需要自己预检查 — 除非你做了一层业务逻辑,想自己决定何时报错。
3. Webhook 订阅事件(最可靠)
Swarmix 在余额低于阈值、扣款或告警产生时推 webhook:
billing.low_balance— 余额低于预警线billing.deduction— 每次扣款(高频,谨慎订阅)alert.created— 新告警产生
订阅方式:Console → Webhooks 添加订阅。Swarmix 会向你的 URL POST JSON:
http
POST https://your-app.com/hook
Content-Type: application/json
X-Swarmix-Event: billing.low_balance
X-Swarmix-Signature: sha256=<hmac>
X-Swarmix-Delivery: evt_xxxxx
{
"event": "billing.low_balance",
"tenant_id": 13,
"data": {
"balance": 8.52,
"threshold": 10.0,
"currency": "CNY"
},
"timestamp": 1776996123
}请校验
X-Swarmix-Signature:HMAC-SHA256,密钥为 webhook 创建时分配的 secret。避免伪造的回调。用量分析 SQL
企业私有部署时你可以直接查 ClickHouse:
sql
-- 本月每个模型的消费
SELECT
model,
count() AS requests,
sum(total_tokens) AS tokens,
sum(cost_cny) AS cost_cny
FROM ygj_logs.request_logs
WHERE tenant_id = 13
AND created_at >= toDate('2026-04-01')
GROUP BY model
ORDER BY cost_cny DESC;
-- 今日各时段 QPS 曲线
SELECT
toStartOfMinute(created_at) AS minute,
count() AS rps
FROM ygj_logs.request_logs
WHERE tenant_id = 13
AND created_at >= toStartOfDay(now())
GROUP BY minute
ORDER BY minute;