OpenAI 兼容。把官方 SDK 的 base_url 指到本站即可。
在控制台创建虚拟密钥,请求头携带 Authorization: Bearer sk-t365-...。
curl https://xuanwujicloud.com/v1/models \ -H "Authorization: Bearer sk-t365-..."
成功时 HTTP 状态码为 200,响应体为 JSON(流式对话除外,见下方 SSE)。失败时同样返回 JSON,结构统一为:
{
"error": {
"message": "余额不足,请先充值",
"type": "billing_error",
"code": "insufficient_balance"
}
}
| 字段 | 说明 |
|---|---|
error.message | 可读错误说明 |
error.type | invalid_request_error / auth_error / billing_error / server_error / upstream_error |
error.code | 可选机器码,如 missing_token、invalid_api_key、account_disabled、insufficient_balance、budget_exceeded、model_not_found、model_not_allowed、no_deployment、task_not_found |
常见 HTTP 状态码:400 请求不合法,401 缺少或无效密钥,403 账号停用 / 余额不足 / 超预算 / 无权调用该模型,404 模型或任务不存在,502 上游失败,503 模型暂无可用上游。
与 OpenAI POST /v1/chat/completions 一致,支持 stream。模型请使用广场中的 model_id,也可用短名(如 deepseek-chat)。
curl https://xuanwujicloud.com/v1/chat/completions \
-H "Authorization: Bearer sk-t365-..." \
-H "Content-Type: application/json" \
-d '{
"model": "qwen/qwen-plus",
"messages": [{"role":"user","content":"用一句话介绍 OpenRouter"}]
}'
主体与 OpenAI 一致,额外附带本站结算字段 bill。model 会被改写为广场中的 model_id。
{
"id": "chatcmpl-xxxxxxxx",
"object": "chat.completion",
"created": 1710000000,
"model": "qwen/qwen-plus",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "OpenRouter 是一个统一接入多家大模型的 API 网关。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 18,
"completion_tokens": 24,
"total_tokens": 42
},
"bill": {
"amount": 0.0012,
"bill_amount": 0.0012,
"estimate": 0.008,
"currency": "CNY",
"prompt_tokens": 18,
"completion_tokens": 24,
"cached_tokens": 0,
"markup": 1.0,
"billed": 1
}
}
| 字段 | 说明 |
|---|---|
choices[].message.content | 模型回复文本 |
usage | 上游 Token 用量,结算以此为准 |
bill.amount / bill.bill_amount | 本次实扣 = 后台目录价 × 该用户 markup |
bill.estimate | 请求时预扣金额 |
bill.markup | 该密钥所属账号的价格系数 |
bill.cached_tokens | 命中缓存的输入 Token |
bill.billed | 1 表示已记账 |
stream: true响应 Content-Type 为 text/event-stream,帧格式与 OpenAI SSE 一致,服务端记账但不改写 SSE 帧,因此流式响应里没有 bill 字段。客户端按行解析 data:,直到 data: [DONE]。
data: {"id":"chatcmpl-xxxxxxxx","object":"chat.completion.chunk","model":"qwen/qwen-plus","choices":[{"index":0,"delta":{"content":"Open"},"finish_reason":null}]}
data: {"id":"chatcmpl-xxxxxxxx","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Router"},"finish_reason":null}]}
data: [DONE]
curl https://xuanwujicloud.com/v1/embeddings \
-H "Authorization: Bearer sk-t365-..." \
-H "Content-Type: application/json" \
-d '{"model":"qwen/text-embedding-v3","input":"你好,世界"}'
与 OpenAI /v1/embeddings 一致,额外附带 bill(字段含义同对话)。
{
"object": "list",
"model": "qwen/text-embedding-v3",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [0.0123, -0.0456, 0.0789]
}
],
"usage": {
"prompt_tokens": 4,
"total_tokens": 4
},
"bill": {
"amount": 0.0001,
"estimate": 0.0004,
"currency": "CNY",
"prompt_tokens": 4,
"completion_tokens": 0,
"cached_tokens": 0,
"billed": 1
}
}
data[].embedding 为浮点数组,长度由模型决定。上面只截取了前几维作为示意。
POST /v1/images/generations。同步完成时直接返回 image_url;异步任务返回 id / task_id(同一值)后请轮询查询接口。可选 provider 指定供应商(如 dashscope / moma)。
curl https://xuanwujicloud.com/v1/images/generations \
-H "Authorization: Bearer sk-t365-..." \
-H "Content-Type: application/json" \
-d '{
"model": "moma/qwen-image-2.0-pro",
"provider": "moma",
"prompt": "写实风格,黄昏海边礁石,暖金色阳光",
"size": "1024*1024"
}'
{
"id": "img-xxxxxxxx",
"task_id": "img-xxxxxxxx",
"object": "task",
"kind": "image",
"status": "queued",
"estimate": 0.15,
"markup": 1.0,
"currency": "CNY"
}
{
"id": "img-xxxxxxxx",
"task_id": "img-xxxxxxxx",
"object": "task",
"kind": "image",
"status": "succeeded",
"image_url": "https://cdn.example.com/generated/xxxx.png",
"bill_amount": 0.12,
"estimate": 0.15,
"markup": 1.0,
"currency": "CNY"
}
图生图时在请求里传 images 或 kind: "i2i",成功报文里 kind 为 i2i,其余字段相同。拿到 id / task_id 且 status 不是终态时,用 查询生成结果 轮询。
POST /v1/videos/generations。文生视频与图生视频都是异步任务:提交成功不会立刻返回成片地址,只会返回任务编号 id / task_id(两者相同)。把这个值填进 GET /v1/tasks/{task_id} 轮询。HappyHorse 可传 resolution(720p/1080p)、duration(秒)、ratio。
curl https://xuanwujicloud.com/v1/videos/generations \
-H "Authorization: Bearer sk-t365-..." \
-H "Content-Type: application/json" \
-d '{
"model": "moma/happyhorse-1.1-t2v",
"provider": "moma",
"prompt": "黄昏海边,镜头缓缓前推,浪花拍上礁石",
"resolution": "720p",
"duration": 5,
"ratio": "16:9"
}'
{
"id": "vid-xxxxxxxx",
"task_id": "vid-xxxxxxxx",
"object": "task",
"kind": "video",
"status": "queued",
"estimate": 0.8,
"markup": 1.0,
"currency": "CNY"
}
查询用的就是这里的 id 或 task_id,例如 GET /v1/tasks/vid-xxxxxxxx。video_url 不会出现在提交接口,需轮询到 status 为 succeeded 后读取。
同一接口,在 content 里带参考图(或传 images)。返回字段与文生视频完全一致,同样用 task_id 查询。
curl https://xuanwujicloud.com/v1/videos/generations \
-H "Authorization: Bearer sk-t365-..." \
-H "Content-Type: application/json" \
-d '{
"model": "moma/happyhorse-1.1-i2v",
"provider": "moma",
"prompt": "镜头缓缓前推,浪花拍上礁石",
"resolution": "720p",
"duration": 5,
"content": [
{"type": "text", "text": "镜头缓缓前推,浪花拍上礁石"},
{"type": "image_url", "image_url": {"url": "https://cdn.example.com/ref.jpg"}, "role": "reference_image"}
]
}'
task_id 来自提交文生图 / 文生视频 / 图生视频后的返回字段 id 或 task_id(同一值)。用它轮询 GET /v1/tasks/{task_id},直到 status 为 succeeded 或 failed。成功时图片看 image_url,视频看 video_url。实扣金额在 bill_amount(已含账号价格系数)。
curl https://xuanwujicloud.com/v1/tasks/TASK_ID \ -H "Authorization: Bearer sk-t365-..."
{
"id": "img-xxxxxxxx",
"task_id": "img-xxxxxxxx",
"object": "task",
"kind": "image",
"status": "running",
"image_url": "",
"video_url": "",
"error_msg": "",
"bill_amount": 0,
"estimate_amount": 0.15,
"billed": 0,
"balance": 12.34,
"frozen": 0.15,
"markup": 1.0,
"currency": "CNY"
}
{
"id": "img-xxxxxxxx",
"task_id": "img-xxxxxxxx",
"object": "task",
"kind": "image",
"status": "succeeded",
"image_url": "https://cdn.example.com/generated/xxxx.png",
"video_url": "",
"error_msg": "",
"bill_amount": 0.12,
"estimate_amount": 0.15,
"billed": 1,
"balance": 12.22,
"frozen": 0,
"markup": 1.0,
"currency": "CNY"
}
{
"id": "vid-xxxxxxxx",
"task_id": "vid-xxxxxxxx",
"object": "task",
"kind": "video",
"status": "failed",
"image_url": "",
"video_url": "",
"error_msg": "生成失败,请稍后重试。",
"bill_amount": 0,
"estimate_amount": 0.8,
"billed": 0,
"balance": 12.34,
"frozen": 0,
"markup": 1.0,
"currency": "CNY"
}
| 字段 | 说明 |
|---|---|
id / task_id | 任务编号,二者相同,取提交接口返回的这个值填进路径 |
kind | image / i2i / video |
status | queued 排队、running 生成中、succeeded 完成、failed 失败,以及 expired / cancelled |
image_url | 图片任务成功后的地址;视频任务为空字符串 |
video_url | 视频任务成功后的地址;图片任务为空字符串 |
error_msg | 失败原因,成功时为空 |
bill_amount | 实扣金额;未结算时为 0 |
estimate_amount | 提交时预扣金额 |
billed | 1 已结算,0 尚未结算 |
balance / frozen | 当前可用余额与冻结金额 |
markup | 该密钥所属账号的价格系数 |
import time, requests
headers = {"Authorization": "Bearer sk-t365-..."}
base = "https://xuanwujicloud.com/v1"
created = requests.post(base + "/images/generations", headers=headers, json={
"model": "moma/qwen-image-2.0-pro",
"prompt": "一只橘猫坐在窗边",
"size": "1024*1024",
}).json()
if created.get("error"):
print(created["error"]["message"])
elif created.get("status") == "succeeded":
print(created.get("image_url"))
else:
task_id = created.get("task_id") or created.get("id")
while True:
task = requests.get(base + "/tasks/" + task_id, headers=headers).json()
if task.get("status") in ("succeeded", "failed", "expired", "cancelled"):
print(task.get("status"), task.get("image_url") or task.get("video_url") or task.get("error_msg"))
break
time.sleep(3)
常见 status:queued(排队)、running(生成中)、succeeded(完成)、failed(失败)。任务不属于当前密钥所属账号时返回 404,error.code 为 task_not_found。
GET /v1/models 返回当前已启用且配置了上游部署的模型。pricing 已乘以当前密钥所属账号的价格系数 markup。
{
"object": "list",
"data": [
{
"id": "qwen/qwen-plus",
"object": "model",
"created": 0,
"owned_by": "dashscope",
"mode": "chat",
"context_length": 131072,
"pricing": {
"prompt": 0.0008,
"completion": 0.002,
"cached": 0.0002,
"markup": 1.0,
"currency": "CNY"
}
}
]
}
| 字段 | 说明 |
|---|---|
data[].id | 广场 model_id,请求时填到 model |
data[].mode | chat / embedding / image / video 等,需与对应接口匹配 |
data[].pricing.prompt | 输入单价(元 / 千 Token 或目录单位,已含系数) |
data[].pricing.completion | 输出单价 |
data[].pricing.cached | 缓存命中单价 |
用户实付 = 后台维护的目录价 × 该账号价格系数(markup,默认 1)。管理员可在后台为每个用户单独设置倍率。调用接口返回的 bill.amount / bill.bill_amount、任务的 bill_amount,以及 GET /v1/models 里的 pricing,都已按该系数计算。网站「定价」页展示的是未乘用户倍率的目录价。
对话 / 向量:先按预估 Token 预扣,成功后按实际上游 usage 结算,差额退回或补扣,失败全额解冻。响应中附带 bill 字段(流式接口在服务端记账,不改 SSE 帧格式)。
文生图 / 文生视频:提交时预扣(含 15% 缓冲),完成后按实际张数或时长结算,bill_amount 为乘以价格系数后的实扣。