快速开始
三步接完:创建密钥 → 换接口地址 → 调模型。
登录后到工作台「开放 API」创建。密钥只在创建时显示一次,请立刻保存。
sk-ah-…设置本站接口地址和密钥,并选择实际可用的对话模型。
—模型名从模型与价格页复制,直接发起请求即可。
chat.completions.create—Authorization: Bearer sk-ah-…—鉴权
所有请求都要带上你的密钥,两种写法都支持:
# 推荐 Authorization: Bearer sk-ah-xxxxxxxxxxxxxxxx # 也支持 x-api-key: sk-ah-xxxxxxxxxxxxxxxx
密钥等同于账户余额,不要写进前端代码或提交到仓库。发现泄露请立刻在控制台删除重建。
对话接口
兼容 OpenAI Chat Completions 的常见请求与响应结构,具体能力由模型决定。常见文本结果读取:choices[0].message.content,usage 里的 token 数可用于对账。
curl — \ -H "Authorization: Bearer $AI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gem-3.7-flash", "messages": [{"role": "user", "content": "你好"}] }'
from openai import OpenAI client = OpenAI(api_key="sk-ah-…", base_url=—) r = client.chat.completions.create( model="gem-3.7-flash", messages=[{"role": "user", "content": "你好"}]) print(r.choices[0].message.content)
import OpenAI from 'openai' const client = new OpenAI({ apiKey: 'sk-ah-…', baseURL: — }) const r = await client.chat.completions.create({ model: 'gem-3.7-flash', messages: [{ role: 'user', content: '你好' }] })
流式输出
加 "stream": true 就是 SSE 流。本站会自动向模型请求用量信息,并在上游流结束后追加一条计费对账消息(标准 data: 行,多带一个 _billing 字段,需容忍没有 choices 的事件):
data: {"_billing":{"cost":0.0123,"balance":12.3456}}
如果模型本身没回 token 用量,会按字符数估算并在账单明细里标注「本地估算」,不会冒充精确值。
长思考模型建议一律用流式:非流式可能要等十几分钟,容易触发客户端超时。
模型列表
curl — \ -H "Authorization: Bearer $AI_KEY"
返回 OpenAI 标准结构,可直接喂给 SDK。模型名、价格、计费方式以模型与价格页为准。
图片 / 视频 / 音频生成
本站 API Key 现在可以提交图片、视频、音频异步生成任务并查询结果。请阅读下方媒体生成 API 的接口、参数与轮询示例。媒体生成使用 HTTP 提交,不使用 chat.completions 调用。
官方 SDK 与客户端
官方 SDK 可用于常见对话调用,设置本站 base URL、API Key 与实际模型 ID。高级参数、返回格式和多模态能力需按所选模型调整。
client = OpenAI(api_key=…, base_url=—)new OpenAI({ apiKey: …, baseURL: — })Cherry Studio / LobeChat / NextChat / 沉浸式翻译客户端需支持 Chat Completions、自定义接口地址及模型 ID。若客户端默认使用 Responses 或其他接口,请先切换协议;本站不保证所有客户端功能都兼容。
错误码
| HTTP | 含义 | 怎么办 |
|---|---|---|
401 | 密钥无效或已删除 | 检查密钥是否复制完整,或重新创建 |
402 | 余额不足 | 到工作台充值后再试 |
403 | 账号停用或上游拒绝请求 | 检查错误体中的 message 与 code |
404 | 模型名不存在 | 用 /v1/models 拿准确名字 |
429 | 请求太频繁 | 降低并发,或稍后重试 |
503 | 上游暂时不可用 | 稍后重试;持续失败请联系客服 |
计费与余额
- 按量计费:对话按 token,视频按秒,图片按次,音频按合成时长或 token。
- 余额变动逐笔记录(含变动前后余额),工作台的「用量与余额」页随时可查、可逐笔核对。
- 工作台媒体任务与对话 API 的结算方式不同;请以任务状态、用量记录和实际账单核对。
- 价格及计费单位以本站价格页为准,不同模型可能按 token 或调用次数计费。
接口范围与接入准备
本文面向使用本站 API Key 的第三方开发者。接口根地址为 —;SDK 的 base URL 填到 /v1,直接使用 HTTP 时填写完整接口路径。所有示例中的模型名需要替换为本站实际可用的对话模型 ID。
| 方法 | 路径 | 用途 | 鉴权 |
|---|---|---|---|
| GET | /v1/models | 查询模型 ID 与类型 | 本站 API Key |
| POST | /v1/chat/completions | 非流式 / 流式对话,按模型能力支持多模态输入 | 本站 API Key |
对话走 Chat Completions;图片、视频、音频走本站异步媒体 API,详见下方「媒体生成 API」。媒体接口不是 OpenAI 同步图片响应或音频二进制响应协议,需要使用 HTTP 客户端提交和轮询。当前未开放 Responses、文件管理、同步 audio/speech 或音频转写接口。
- 注册并登录工作台,确认账户有可用余额。
- 在「开放 API」创建本站密钥;使用创建时显示的完整明文密钥。
- 从模型列表选择
type: "chat"的 ID,先发一个小请求确认接通。 - 在服务端环境变量保存密钥,再接入自己的业务。用户登录 Cookie、上游平台密钥和 OSS AccessKey 都不能替代本站 API Key。
export AI_KEY='替换为你的本站API密钥'
export AI_BASE_URL='—/v1'
export AI_MODEL='替换为实际对话模型ID'
curl -sS "$AI_BASE_URL/models" -H "Authorization: Bearer $AI_KEY"$env:AI_KEY = '替换为你的本站API密钥'
$env:AI_BASE_URL = '—/v1'
$env:AI_MODEL = '替换为实际对话模型ID'
Invoke-RestMethod -Uri "$env:AI_BASE_URL/models" -Headers @{Authorization="Bearer $env:AI_KEY"}Linux 示例中的反斜杠续行不能原样用于 PowerShell。Windows 可以使用 curl.exe,或上面的 Invoke-RestMethod。
请求参数与响应字段
| 字段 | 必填 | 说明 |
|---|---|---|
| model | 是 | 精确模型 ID,不是展示名称;从模型列表复制。 |
| messages | 是 | 消息数组;建议至少有一条 user 消息。 |
| stream | 否 | 布尔值,默认 false;必须传 JSON true 才开启流式。 |
| temperature / top_p | 否 | 采样参数,取值和支持情况取决于模型。 |
| max_tokens / max_completion_tokens | 否 | 输出长度限制;选择模型支持的参数,不保证两个名称均受支持。 |
| tools / tool_choice / response_format | 否 | 仅适用于支持对应能力的模型;本站不代替你的服务执行工具调用。 |
| stream_options | 否 | 流式时未提供则默认请求 include_usage: true;上游仍可能不返回用量。 |
常见消息角色包括 system、user、assistant 和工具消息 tool。具体角色、长上下文、思考参数、JSON 模式与工具调用由所选模型决定。本站会将请求交给对应上游,不能保证所有 OpenAI 参数在所有模型上通用。
{
"model": "替换为实际对话模型ID",
"messages": [
{"role": "system", "content": "你是一位简洁的中文助手。"},
{"role": "user", "content": "请解释浏览器缓存。"},
{"role": "assistant", "content": "浏览器会保存部分资源,减少重复下载。"},
{"role": "user", "content": "再举一个例子。"}
],
"stream": false
}API 不自动保存多轮上下文:每次请求需要由你的应用带上所需历史消息。上下文也会占用输入 token,建议在业务中限制历史长度。
{
"id": "上游返回的响应ID",
"object": "chat.completion",
"choices": [{"index": 0, "message": {"role": "assistant", "content": "你好!"}, "finish_reason": "stop"}],
"usage": {"prompt_tokens": 12, "completion_tokens": 3, "total_tokens": 15},
"_billing": {"cost": 0.001, "balance": 10.999, "inputTokens": 12, "outputTokens": 3}
}choices[0].message.content 是常见文本结果,但工具调用或特殊模型的 content 可能为空,需要检查 message 的其他字段。finish_reason、usage 和其他扩展字段以上游实际响应为准;_billing 是本站额外提供的计费信息,不是 OpenAI 标准字段。
可运行的服务端示例
先设置上一节的三个环境变量。Python 安装 python -m pip install openai;Node.js 安装 npm install openai 并保存为 example.mjs。使用与你安装的 SDK 兼容的 Python / Node.js 运行时。
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["AI_KEY"],
base_url=os.environ["AI_BASE_URL"],
timeout=180.0, max_retries=0)
response = client.chat.completions.create(
model=os.environ["AI_MODEL"],
messages=[{"role": "user", "content": "你好,请简短介绍你自己。"}])
print(response.choices[0].message.content)import OpenAI from 'openai';
const client = new OpenAI({
apiKey: process.env.AI_KEY, baseURL: process.env.AI_BASE_URL,
timeout: 180000, maxRetries: 0
});
const response = await client.chat.completions.create({
model: process.env.AI_MODEL,
messages: [{role: 'user', content: '你好,请简短介绍你自己。'}]
});
console.log(response.choices[0]?.message?.content);curl -sS --max-time 180 "$AI_BASE_URL/chat/completions" \
-H "Authorization: Bearer $AI_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"替换为实际对话模型ID","messages":[{"role":"user","content":"你好"}]}'示例关闭 SDK 自动重试,以免在超时后不知情地重复提交生成请求。180 秒仅为接入示例,实际需要根据模型和业务调整;长输出建议使用流式。
流式接收与计费消息
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["AI_KEY"], base_url=os.environ["AI_BASE_URL"],
timeout=180.0, max_retries=0)
for chunk in client.chat.completions.create(
model=os.environ["AI_MODEL"], stream=True,
messages=[{"role": "user", "content": "写一段简短的欢迎词。"}]):
if chunk.choices:
text = chunk.choices[0].delta.content
if text:
print(text, end="", flush=True)
print()原始 HTTP 客户端须按 SSE 空行分隔事件,读取 data: 内容;网络读取块不一定对应完整事件,不能对每个网络块直接 JSON.parse。choices 可能缺失或为空,须先判断再读取 delta。
data: {"choices":[{"index":0,"delta":{"content":"你好"}}]}
data: {"choices":[],"usage":{"prompt_tokens":12,"completion_tokens":3,"total_tokens":15}}
data: [DONE]
data: {"_billing":{"cost":0.001,"balance":10.999,"inputTokens":12,"outputTokens":3}}当前实现会转发上游的 [DONE],并在上游流结束后追加本站 _billing。因此本站计费消息可能位于 [DONE] 之后;标准 SDK 可能在 [DONE] 停止读取而看不到它。如需读取该字段,用原始 SSE 客户端继续读到连接结束,或在工作台用量记录核对。不要假设每条事件都有 choices。
已开始 SSE 后发生错误,可能收到包含 error.message 的事件,或连接直接结束。此时 HTTP 可能仍是 200,业务需要区分正常完成和中途断开;缺少计费事件也不能直接认定未扣费。流式响应提供 X-Request-Id,排障时请记录。
视觉输入与素材地址
仅支持视觉理解的对话模型可在 messages 中接收图片。图片生成模型与视觉对话模型不是同一种调用方式。
{
"model": "替换为支持视觉的对话模型ID",
"messages": [{"role": "user", "content": [
{"type": "text", "text": "请描述这张图片。"},
{"type": "image_url", "image_url": {"url": "https://你的素材域名/example.jpg"}}
]}]
}素材 URL 必须能被上游服务器获取;需要登录 Cookie 的页面、本机地址、内网地址和浏览器 blob URL 不能作为远程素材地址。带签名的 OSS URL 应保留完整查询参数且在任务处理期间有效。支持 data URL 的模型可使用 data:image/png;base64,...,但体积、数量及格式限制以上游要求为准。
工作台中用户上传的图片、视频、音频可以由站点 OSS 保存七天;云端到期删除,签名地址也会过期。浏览器缓存不等于上游仍能读取。请提前下载长期需要的素材,不要把临时地址当成永久业务资产。上游生成结果由上游托管,保存期限以上游为准。
限流、超时与重复请求
- 429 时降低并发并退避;错误体可能包含
error.retryAfter(秒)。本站未承诺固定并发额度,也未保证提供 Retry-After 响应头。 - 建议退避间隔按 1、2、4、8 秒递增并增加随机抖动,设置最大尝试次数。鉴权、额度或参数错误先修正再提交。
- 网络超时不等于生成未执行。当前没有对外提供幂等键去重或按客户端请求 ID 查询生成结果的接口;自动重试可能重复生成和计费。已取得媒体任务 ID 时只查询该任务,不要重复提交。
- 对话 API 不返回媒体任务号;媒体 API 任务使用 /v1/tasks/{id} 查询。
- 每个请求记录时间、模型 ID、HTTP 状态、错误码、可获得的响应 ID / X-Request-Id。日志不记录密钥和含隐私的完整消息。
{
"error": {
"message": "请求过于频繁",
"code": "rate_limited",
"retryAfter": 3
}
}| 状态 | 常见 code / 情况 | 处理 |
|---|---|---|
| 400 | invalid_json / invalid_request / line_no_model / 上游参数错误 | 检查 JSON、模型和 messages;按模型能力调整参数。 |
| 401 | missing_api_key / invalid_api_key / key_revoked / key_disabled | 检查本站密钥及请求头,不要使用上游密钥。 |
| 402 | insufficient_balance / key_quota_exceeded | 账户余额与单个密钥额度分别检查;充值未必解除密钥额度上限。 |
| 403 | account_banned / 上游拒绝 | 检查账号状态或具体 error.message;不一定是模型授权问题。 |
| 404 | 未开放的路径或上游资源不存在 | 检查 /v1 是否重复、路径及上游模型 ID。 |
| 429 | rate_limited / 上游限流 | 减少并发,按错误提示退避。 |
| 502 | upstream_error / upstream_unreachable | 记录错误信息,确认是否已经产生结果再决定重试。 |
| 503 | no_upstream_key / 服务不可用 | 联系站点支持或稍后再试。 |
本站可能保留上游的其他 HTTP 状态及业务错误码,应同时查看状态、message 和 code,不要只凭状态码判断原因。
图片、视频、音频生成 API
使用与对话相同的本站 API Key。提交成功返回 HTTP 202 和本站任务 ID,表示已受理,不表示生成完成。选择模型列表中 type 为 image、video 或 audio 的模型。
| 方法 | 接口 | 说明 |
|---|---|---|
| POST | /v1/images/generations | 图片生成,模型类型必须是 image。 |
| POST | /v1/videos/generations | 视频生成,模型类型必须是 video。 |
| POST | /v1/audio/generations | 音频生成,模型类型必须是 audio。 |
| POST | /v1/media/generations | 通用媒体入口,自动识别上述三种类型。 |
| GET | /v1/media/parameters?model=模型ID | 查询模型可用参数说明;模型 ID 应 URL 编码。 |
| GET | /v1/tasks/{id} | 查询自己账户的单个任务;不可查询其他用户任务。 |
| GET | /v1/tasks?limit=20 | 自己账户最近的任务,最多 100 条;可包含工作台提交的任务。 |
提交字段:model 必填字符串;prompt 为提示词或音频生成文本;params 为参数对象,默认空对象。prompt 与 params 至少有一个非空。尺寸、比例、时长、音色、参考图等参数名和值因模型而异,先查参数说明,不能把一套参数用于所有模型。本站对外入口自动选线路,不开放上游回调或任意线路覆盖参数。
curl -sS "$AI_BASE_URL/images/generations" \
-H "Authorization: Bearer $AI_KEY" -H "Content-Type: application/json" \
-d '{"model":"替换为图片模型ID","prompt":"清晨的海边,写实摄影","params":{}}'# POST /v1/videos/generations
{"model":"替换为视频模型ID","prompt":"镜头缓慢推进,海浪拍打岸边","params":{}}
# POST /v1/audio/generations
{"model":"替换为音频模型ID","prompt":"你好,欢迎使用本站。","params":{}}{
"task": {
"id": "本站任务ID", "object": "media.task",
"model": "实际模型ID", "type": "image",
"state": "submitted", "status": "已提交", "progress": "0",
"is_final": false, "result_url": "", "result_type": "",
"error": null, "created_at": "时间", "completed_at": null,
"_billing": {"settled": false, "cost": 0}
}
}拿 task.id 请求 GET /v1/tasks/{id},建议每 5~10 秒一次。is_final: true 表示终态,仍需检查 error 和 result_url 区分成功与失败;state、status 和 progress 内容以上游结果为准,不依赖固定状态字符串。任务未完成时 result_url 为空、cost 为 0 都是正常情况。
import os, json, time
from urllib.request import Request, urlopen
from urllib.error import HTTPError
base = os.environ["AI_BASE_URL"].rstrip("/")
key = os.environ["AI_KEY"]
def request(path, body=None):
payload = None if body is None else json.dumps(body).encode()
req = Request(base + path, data=payload, headers={
"Authorization": "Bearer " + key, "Content-Type": "application/json"})
try:
with urlopen(req, timeout=120) as response:
return json.load(response)
except HTTPError as e:
raise RuntimeError(str(e.code) + " " + e.read().decode()) from e
# AI_MEDIA_MODEL 设置为实际图片模型 ID;视频/音频替换对应提交路径和模型。
task = request("/images/generations", {
"model": os.environ["AI_MEDIA_MODEL"], "prompt": "清晨的海边,写实摄影", "params": {}
})["task"]
task_id = task["id"]
deadline = time.monotonic() + 1800
while not task["is_final"]:
if time.monotonic() > deadline:
raise TimeoutError("客户端停止等待,请保留任务ID后续查询:" + task_id)
time.sleep(5)
task = request("/tasks/" + task_id)["task"]
if task.get("error") or not task.get("result_url"):
raise RuntimeError(str(task))
print(task["result_url"])
print(task["_billing"])媒体任务沿用工作台结算机制,终态后 _billing.cost 为本站结算金额,按对应账户和提交时使用的密钥记录用量。余额或密钥额度在提交时检查;异步并发任务不预冻结预算,不能把密钥额度当作并发消费的严格预留上限。
result_url 由上游托管,本站不把生成文件复制到服务器或 OSS。需要长期保存请自行下载。参考素材请使用上游可访问的完整 URL,并确保任务处理期间未过期。可通过 JSON 提供有效素材 URL,也可使用下方说明的 multipart 请求一并提交参考文件。
随生成请求提交参考素材
API 不开放独立上传凭证或通用文件存储接口。需要传图片、视频或音频参考文件时,向媒体生成接口发送 multipart/form-data,将模型、提示词、参数和文件一次提交。服务器临时接收后保存到 OSS,并把素材地址加入模型参数,再提交生成任务;不长期保存到本站磁盘。
model、prompt 为普通表单字段;params 为 JSON 对象字符串。文件字段名必须等于该模型的参考素材参数名(通过 /v1/media/parameters 查询),上传地址会覆盖 params 中同名字段。单文件用普通字段名;多文件用 images[] 等实际参数名加 [],每个文件重复该字段,转成 URL 数组。参考素材数量和格式应遵守所选模型的参数说明。已有有效远程 URL 时仍可使用 JSON 请求,不必重新上传。
import os, json
from pathlib import Path
import requests
path = Path("reference.png")
with path.open("rb") as source:
response = requests.post(os.environ["AI_BASE_URL"].rstrip("/") + "/images/generations",
headers={"Authorization": "Bearer " + os.environ["AI_KEY"]},
data={"model": os.environ["AI_MEDIA_MODEL"],
"prompt": "根据参考素材生成画面", "params": json.dumps({})},
# 将 reference_parameter 替换为所选模型实际接收的参考素材参数名。
files={"reference_parameter": (path.name, source, "image/png")}, timeout=180)
response.raise_for_status()
task_id = response.json()["task"]["id"]
print(task_id) # 使用 /tasks/{id} 查询结果
视频和音频使用对应生成路径与实际参考参数名。文件仅接受已列出的图片、视频和音频格式,单个文件上限 30 MB,保留请求频率限制;不另设每请求三个文件或每日 300 MB 的固定限制。账户余额、密钥状态、额度及模型类型先校验再写入 OSS。模型本身及 PHP 的 max_file_uploads、post_max_size 等配置仍可能限制一次上传数量和总大小。
此流程仍会消耗服务器接收和转传带宽,PHP 会产生请求临时文件,结束后自动清理。上传前的网络接收无法完全避免;实际文件大小还受宝塔 PHP 的 upload_max_filesize、post_max_size 和网站请求体上限限制。OSS 未启用或失败时明确报错,不回退到站点持久磁盘。
OSS 素材按用户目录隔离,保留七天,使用私有签名地址。生成结果仍由上游托管。若素材已保存而上游拒绝生成,素材会保留到生命周期删除,失败不会立即清空缓存或已保存的对象。
接入检查与常见问题
- 模型列表能查到,为什么对话失败?检查 type 是否为 chat、账户余额、模型当前可用性和输入能力;目录存在不保证每次上游调用成功。
- 404 或返回 HTML?确认访问本站 API 域名,SDK base URL 只包含一次 /v1;浏览器页面地址 /index.html 和 /admin 不是 API 根地址。
- SDK 类型报错?本站有扩展字段,且模型能力存在差异;不要强制要求所有事件都与单一模型返回完全一致。
- 如何查余额和账单?登录工作台查看用量与余额;对外 API 当前没有独立余额查询接口。非流式 _billing 是本次结果的计费补充信息。
- 工具调用为什么没有执行?模型只返回调用建议,你的应用应验证参数、执行自己的工具并追加 tool 消息。
- 可以直接放在网页里吗?不要向终端用户暴露你的账户密钥。通过自己的后端转发,并对用户鉴权、限制频率和消费。
- 如何寻求支持?提供调用时间、模型、HTTP 状态、脱敏错误体和响应 ID。不要发送密钥、Cookie、OSS Secret 或完整签名素材链接。
文档更新:2026-10-10。示例返回值仅说明结构,不代表固定价格、余额、用量或可用模型。实际价格以价格页及工作台账单为准。
文档随站点更新。有问题先看价格页确认模型是否可用,再到工作台「用量与余额」核对账单。