APIMODELSAPIMODELS
免费 · 仅需 API key

逐单计费:请求 ID 与实扣查询

每一次调用都有一个请求 ID,和一个最终实扣金额。LLM 请求把 ID 放在响应头 x-apimodels-request-id 里,金额直接写在响应体的 usage.cost 里(流式在最后带用量的那一帧),非流式请求的响应头还带 x-apimodels-cost;图片、视频、音频任务的 ID 就是创建时返回的 task_id,创建时还会告诉你预扣了多少。拿任何一个 ID 调 GET /v1/records/{id},拿到的就是这笔请求从余额里扣掉的准确金额 —— 经书面许可转售我们的服务(服务条款第 6 节,联系 business@apimodels.app)、或者要给自己的用户逐笔对账时用它。

一览

Endpoint
GET /api/v1/records/{task_id}
鉴权
Authorization: Bearer <API_KEY>
计费
免费(查询不扣积分)
响应头
x-apimodels-request-id · x-apimodels-cost
响应体
usage.cost · reservedCredits
覆盖
LLM、图片、视频、音频的每一次调用
货币单位
USD

请求 ID 从哪来

LLM 端点(/v1/chat/completions、/v1/messages、Gemini 原生 /v1beta、/v1/responses、/v1/completions)的每个成功响应都带 x-apimodels-request-id 响应头,值就是这笔请求的 task_id。非流式响应另带 x-apimodels-cost:单位 USD、已含你账户的全部折扣,是扣费完成后才写进去的实扣额。流式响应只带 ID —— 金额要等最后一个 chunk 结算后才有,拿 ID 去查记录即可。

HTTP/2 200
content-type: application/json
x-apimodels-request-id: cmumilhfd0013mg012q3qobr9
x-apimodels-cost: 0.0001
access-control-expose-headers: x-apimodels-request-id, x-apimodels-cost

响应体里的 usage.cost

用 OpenAI / Anthropic SDK 的话通常读不到响应头,所以同一笔金额也写进了响应体的 usage.cost。非流式响应里 usage.cost.charged 就是实扣额,和 x-apimodels-cost 是同一个数。

{
  "id": "chatcmpl-…",
  "choices": [ … ],
  "usage": {
    "prompt_tokens": 165,
    "completion_tokens": 6,
    "cost": { "currency": "USD", "amount": 0.0001, "discount": 1, "charged": 0.0001 }
  }
}

流式响应在最后那一帧带用量的数据里给出 usage.cost:OpenAI 格式是 stream_options.include_usage 打开后的用量帧,Anthropic 格式(/v1/messages)是 message_delta,/v1/responses 是 response.completed 里的 response.usage。这一帧发出时扣费还没落库,所以 charged 是用同一个公式算出的应扣额;只有余额不足、没扣满的请求,实扣会比它少,以记录查询为准。message_start 里只有输入用量,不带 cost。

# OpenAI 格式(stream_options.include_usage = true):最后的用量帧
data: {"object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":165,"completion_tokens":6,"cost":{"currency":"USD","amount":0.0001,"discount":1,"charged":0.0001}}}

data: [DONE]

# Anthropic 格式(/v1/messages):message_delta
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"input_tokens":165,"output_tokens":6,"cost":{"currency":"USD","amount":0.0001,"discount":1,"charged":0.0001}}}
字段必填类型说明
usage.cost.currency—string固定为 "USD"
usage.cost.amount—number按标价算的这一单金额,折扣前
usage.cost.discount—number你账户的折扣倍数:1 = 不打折,0.95 = 95 折
usage.cost.charged—number扣款,已含折扣。非流式 = 实扣额;流式 = 应扣额(见上)

usage.cost 覆盖 /v1/chat/completions、/v1/messages、/v1/responses 和 /v1/completions;Gemini 原生 /v1beta 的响应不带它,金额照常用记录查询。

一个例外:非流式 LLM 请求跑超过约 95 秒时,网关会先发响应头保活,这时两个头已经发出去、带不上值,于是同样的两个值补进响应正文的 apimodels 字段。OpenAI / Anthropic 的 SDK 会忽略这个未知字段,不影响解析。

{
  "id": "chatcmpl-…",
  "choices": [ … ],
  "usage": { … },
  "apimodels": { "request_id": "cmumilhfd0013mg012q3qobr9", "cost": 0.0001 }
}

图片、视频、音频任务的 ID 就是创建时返回的 data.taskId。创建响应里同时带 reservedCredits:建单时从余额里冻结的金额,是这单的上限;完成后按实际结算,多冻的部分自动退回,失败全额退回。

{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "cmum4dq3z00dwlm01wugboo5z",
    "state": "pending",
    "model": "seedance-2.0",
    "reservedCredits": 0.46,
    "currency": "USD"
  }
}

任务完成后,GET ?task_id= 的查询结果和回调(callback_url)的 data 里都带 credits(最终实扣)和 currency,和记录查询的值一致。

{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "cmum4dq3z00dwlm01wugboo5z",
    "state": "completed",
    "credits": 0.338,
    "currency": "USD",
    "resultUrls": ["https://r2.apimodels.app/videos/cmum4dq3z00dwlm01wugboo5z.mp4"]
  }
}

浏览器里直接调用时,这两个响应头已通过 Access-Control-Expose-Headers 暴露,fetch 的 response.headers.get() 能读到。

查询记录

GET /api/v1/records/{task_id}
Authorization: Bearer <API_KEY>

示例:调用后逐单对账

cURL

curl https://api.apimodels.app/v1/records/cmumilhfd0013mg012q3qobr9 \
  -H "Authorization: Bearer $API_KEY"

Python

import requests, os

# 1) make the call and keep the request id from the response headers
r = requests.post(
    "https://api.apimodels.app/v1/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
    json={"model": "claude-haiku-5-5", "messages": [{"role": "user", "content": "Hi"}]},
)
request_id = r.headers["x-apimodels-request-id"]
print("charged now:", r.headers.get("x-apimodels-cost"))   # non-streaming only

# 2) any time later: the authoritative billed amount for that one request
rec = requests.get(
    f"https://api.apimodels.app/v1/records/{request_id}",
    headers={"Authorization": f"Bearer {os.environ['API_KEY']}"},
).json()["data"]
print(rec["settled"], rec["credits"], rec["currency"])

Node.js

const headers = { Authorization: "Bearer " + process.env.API_KEY };

// 1) make the call and keep the request id from the response headers
const r = await fetch("https://api.apimodels.app/v1/chat/completions", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ model: "claude-haiku-5-5", messages: [{ role: "user", content: "Hi" }] }),
});
const requestId = r.headers.get("x-apimodels-request-id");
console.log("charged now:", r.headers.get("x-apimodels-cost")); // non-streaming only

// 2) any time later: the authoritative billed amount for that one request
const rec = await fetch("https://api.apimodels.app/v1/records/" + requestId, { headers });
const { data } = await rec.json();
console.log(data.settled, data.credits, data.currency);

响应

{
  "code": 200,
  "msg": "success",
  "data": {
    "task_id": "cmumilhfd0013mg012q3qobr9",
    "model": "claude-haiku-5-5",
    "type": "LANGUAGE_MODEL",
    "state": "completed",
    "settled": true,
    "credits": 0.0001,
    "currency": "USD",
    "usage": {
      "input_tokens": 165,
      "output_tokens": 6,
      "cached_input_tokens": 149,
      "cache_creation_tokens": 0
    },
    "created_at": 1790676571513,
    "completed_at": 1790676572799
  }
}
字段必填类型说明
data.task_id—string请求 ID,与响应头 / 创建时返回的 taskId 相同
data.model—string公开模型名,如 claude-haiku-5-5
data.type—stringLANGUAGE_MODEL / TEXT_TO_IMAGE / IMAGE_TO_VIDEO / … 与调用记录一致
data.state—stringpending(还在跑)/ completed / failed
data.settled—booleantrue 表示金额已是最终值;false 时 credits 为 null,稍后再查
data.credits—number | null从余额里实际扣掉的美元,已含账户折扣与按模型定价;失败的请求为 0
data.currency—string固定为 "USD"
data.usage—object仅 LLM:input_tokens、output_tokens、cached_input_tokens、cache_creation_tokens;推理 token 计入 output_tokens
data.created_at—number创建时间,毫秒时间戳
data.completed_at—number | null完成时间,毫秒时间戳;未完成为 null

金额的口径

  • credits 是最终从余额里扣掉的数,不是标价乘用量:账户折扣、按模型协商价都已经算进去。
  • 失败的请求一律 0。上游报错、被我们的校验拒绝、超时,都不收费。
  • 流式 LLM 在最后一个 chunk 结算;按成片时长计费的视频模型在成片出来后结算。结算前 settled 为 false。
  • x-apimodels-cost、非流式响应的 usage.cost.charged 与记录里的 credits 是同一个数;记录是权威来源,头和响应体只是省你一次查询。
  • usage.cost.charged 约等于 amount × discount。LLM 的 amount 和 charged 都按 4 位小数取整、单笔最低 $0.0001;用了按模型协商价的账户,以 charged 为准。
  • reservedCredits 是上限,不是账单:冻结期间这部分余额不能用于别的请求,结算后多的部分立刻退回可用余额。
  • 金额保留到小数点后 6 位(百万分之一美元)。

错误

  • 401 — API Key 缺失或无效
  • 404 — 记录不存在。别的账户的请求 ID 也返回 404,不会确认它是否存在
  • 500 — 服务器内部错误

常见问题

怎么知道某一次调用扣了多少钱?

从响应头读 x-apimodels-request-id(LLM),或记下创建时返回的 task_id(图片、视频、音频),然后带 API key 调 GET https://api.apimodels.app/v1/records/{id}。data.credits 就是折扣后实际从余额扣掉的美元数,失败的请求为 0。非流式 LLM 响应还直接在 x-apimodels-cost 头里给出金额。

为什么 credits 是 null、settled 是 false?

这笔请求还没结算完。流式 LLM 在最后一个 chunk 结算,部分视频模型按实际成片时长结算。完成后再查一次;settled 变成 true 后金额就是最终值,不会再变。

流式响应带金额头吗?

不带。流式只带 x-apimodels-request-id,因为金额要到流结束才知道,最后一个 chunk 之后去查 GET /v1/records/{id}。非流式两个头都带;跑超过约 95 秒的非流式 LLM 请求会改为在响应正文的 apimodels 字段里给出同样两个值,因为那时响应头已经为保活先发出去了。

能查别的账户的请求吗?

不能。属于别的账户的请求 ID 返回 404,和不存在的 ID 一样;接口不会确认这样的 ID 是否存在。查询本身免费,不计为调用。