Tare API (2026-08-22.4)

Download OpenAPI specification:

一个 OpenAI 兼容的模型网关,外加子钥签发与对账接口

完整的说明性文档在 www.jamerly.ai/docs/tare(中英双语)。 ⚠️ 2026-08-22.4:.3 曾以缺两段的形式发布过(chat 端点与 Generation.upstream_inference_cost 关于「转售不返回上游成本」的说明在发布流程中 丢失)。行为本身从 0.1.13 起就是这样,丢的只是文字。拿过 .3 的话请重新拉一份。

这份文件只描述 接口形状,不重复文档里的那些判断依据(为什么额度用尽是 403、为什么流式末帧 两种方言不一致等等)——接入前请两份一起读。

鉴权

全部接口都用 Authorization: Bearer <key>。三类 key 权限互不重叠,用错类型返回明确的 拒绝,而不是含糊的 401:

key 能做什么
推理 key 调模型(/v1/chat/completions、/v1/embeddings、/v1/models、/v1/generation)
母钥 管子钥(/v1/keys/*),不能调模型
对账 key 读账(/v1/integration/*),不能调模型

请求头

除了 Authorization(和流式的 Accept: text/event-stream),不要求任何请求头。

⚠️ 未识别的请求头一律忽略,不会因此拒绝请求,也不会转发给上游。 发往上游的请求头 由我们重建(凭据、Content-Type、方言要求的那几个),你带的头不会出现在上游那一侧。 OpenRouter 的归因头 HTTP-Referer / X-Title 属于这一类:带上无害,但不会到达任何 地方,也不影响路由、计费和限流。

归因请改用 usage_label(请求体内,原样落进用量记录)和子钥本身。

时间与时区

所有时间戳都是 ISO 8601。⚠️ 不带偏移量的那些(2026-08-21T17:30:00)按 Asia/Shanghai(UTC+8)解释 —— 它们是服务端本地时间。账期也按这个时区切, /v1/integration/whoami 会返回当时使用的时区,以该字段为准,不要硬编码。

两种响应形状

接口 形状 失败时
/v1/chat/completions、/v1/embeddings、/v1/keys/*、/v1/models、/v1/generation OpenAI:{"error":{...}} HTTP 非 2xx
/v1/integration/* ApiResponse:{"code","message","data","success"} HTTP 非 2xx,body 仍是 ApiResponse(不是 200 + success:false)

Chat

OpenAI 兼容的模型端点

发起一次模型调用(OpenAI 兼容)

请求体原样透传:未识别的字段照发给上游,这是 cache_control、reasoning、 plugins 这类字段能工作的原因。我们只改动四处:模型名换成上游认的、stream 固定为本次尝试的模式、流式强制 stream_options.include_usage=true、剥除归因字段。

⚠️ usage.cost 是「花了你多少」。 走平台渠道(token 的钱由我们垫)时,回包中 不含 usage.cost_details —— 那一格是上游向我们收取的金额。BYOK 下保留: 那是你自己上游账单上的钱,也正是成本归因需要的数据。 (2026-08-22 之前两种模式都返回了;已修。) 算不出来时 cost 整格不出现,而不是 0 —— 「该模型尚未定价」也算算不出来。

⚠️ 两种上游方言的流式末帧形状不一致(OpenAI 兼容是 choices: [],Anthropic 是 choices 有一项而 delta 为空)。按帧渲染时判据写成「choices 为空 或 delta 无内容 → 跳过渲染,只取 usage」。

Authorizations:
bearerAuth
Request Body schema: application/json
required
model
required
string

平台侧模型名,取自 GET /models 的 id

required
Array of objects
stream
boolean
Default: false
max_tokens
integer
temperature
number
usage_label
string

你自己的归因标签,会原样落进用量记录,基数不设上限

property name*
additional property
any

Responses

Request samples

Content type
application/json
{
  • "model": "GLM 5.1",
  • "messages": [
    ],
  • "stream": false,
  • "max_tokens": 0,
  • "temperature": 0,
  • "usage_label": "string"
}

Response samples

Content type
{
  • "id": "string",
  • "object": "chat.completion",
  • "created": 0,
  • "model": "string",
  • "provider": "string",
  • "choices": [
    ],
  • "usage": {
    }
}

把文本转成向量(OpenAI 兼容)

请求体原样透传,回包是上游原文加一格 usage.cost。

⚠️ 模型名不做映射。 chat 那边写的是我们这边的模型名(取自 GET /models), 这里写的是上游自己的名字(text-embedding-3-small 这一类)—— embeddings 不走模型路由表,所以没有那层映射,回包里的模型名同样不改写。

⚠️ 打到哪条渠道:你自己的渠道优先(显式配的 > 按方言推出来的), 都没有才走平台那条被指定的渠道。 两者的计费不同(自己的渠道只记账,平台渠道按售价扣余额),所以不会在两者 之间自动故障转移 —— 一次静默的回退等于在你没同意的情况下开始花钱。

没有流式。gen- 编号走响应头,用法和 chat 一致。

Authorizations:
bearerAuth
Request Body schema: application/json
required
model
required
string

上游的模型名(不是 GET /models 里的 id)。 ⚠️ embedding 模型不会出现在 GET /models —— 那份目录来自上游的 模型目录,而上游的目录里没有 embedding 模型。请按上游文档写。

required
string or Array of strings

字符串或字符串数组

dimensions
integer
encoding_format
string
Enum: "float" "base64"
usage_label
string

你自己的归因标签,会原样落进用量记录

property name*
additional property
any

Responses

Request samples

Content type
application/json
{
  • "model": "text-embedding-3-small",
  • "input": "string",
  • "dimensions": 0,
  • "encoding_format": "float",
  • "usage_label": "string"
}

Response samples

Content type
application/json
{
  • "object": "list",
  • "model": "string",
  • "data": [
    ],
  • "usage": {
    }
}

Keys

母钥签发与管理子钥

开一把子钥(母钥调用)

完整明文只在创建时返回一次。带 external_id 时同一个编号重复创建是幂等的: 返回已存在的那把,HTTP 状态码是 200 而不是 201。

⚠️ 幂等重放只在创建后 5 分钟内能拿回明文。超过窗口 key 是 null, 并附 key_unavailable_reason(枚举值)和 key_unavailable_message(文案会变)。

Authorizations:
bearerAuth
Request Body schema: application/json
required
name
required
string

用途说明,由你填写;原样进入账单归因

limit
number or null

累计消费上限(美元)。不传 = 不限额

external_id
string

你自己的编号,用来做创建幂等;唯一性是 (账号, external_id)

include_byok_in_limit
boolean
Default: true

BYOK 渠道的消耗算不算进这把 key 的上限

expires_at
string

形如 2027-01-01T00:00:00

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "limit": 0,
  • "external_id": "string",
  • "include_byok_in_limit": true,
  • "expires_at": "string"
}

Response samples

Content type
application/json
{
  • "key": "string",
  • "key_unavailable_reason": "plaintext_window_expired",
  • "key_unavailable_message": "string",
  • "data": {
    }
}

列出这个账号下的子钥

游标翻页。⚠️ 游标是 id 不是 offset:翻页途中若有新 key 创建,offset 会让某一把被 跳过或重复出现。账号下的子钥总数不设上限,单次返回的行数有上限。

Authorizations:
bearerAuth
query Parameters
limit
integer <= 200
Default: 100

单页行数。超过 200 不报错,会被压到 200

after
integer <int64>

上一页返回的 next_cursor,首页不传

Responses

Response samples

Content type
application/json
{
  • "data": [
    ],
  • "next_cursor": 0
}

查一把子钥的额度与用量

Authorizations:
bearerAuth
path Parameters
hash
required
string

创建时返回的 data.hash,这把 key 的稳定标识

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

改额度 / 停用 / 恢复

⚠️ 解封用 {"disabled": false},不要用同一个 external_id 再开一把: external_id 的唯一性包含已停用的 key,一个编号永久对应一把 key。

Authorizations:
bearerAuth
path Parameters
hash
required
string

创建时返回的 data.hash,这把 key 的稳定标识

Request Body schema: application/json
required
limit
number or null

改累计上限;null = 改成不限额

name
string
disabled
boolean

true 停用、false 恢复

include_byok_in_limit
boolean
expires_at
string or null <date-time>

改到期时间;显式 null = 取消到期(与 limit 字段语义一致)。 ⚠️ 到期的 key 调模型返回 401,与被吊销的表现完全一致:区分二者等于向持有无效 凭据的人确认「这把 key 曾经存在」。 ⚠️ 到期不会把 disabled 置为 true,该字段只表示「被停用」,判断到期请读 expires_at。

Responses

Request samples

Content type
application/json
{
  • "limit": 0,
  • "name": "string",
  • "disabled": true,
  • "include_byok_in_limit": true,
  • "expires_at": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

按你自己的编号查子钥

有了它就不必在你那边维护一张 external_id → hash 的映射表。

Authorizations:
bearerAuth
path Parameters
externalId
required
string

你自己的编号

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

按你自己的编号改额度 / 停用 / 恢复

Authorizations:
bearerAuth
path Parameters
externalId
required
string

你自己的编号

Request Body schema: application/json
required
limit
number or null

改累计上限;null = 改成不限额

name
string
disabled
boolean

true 停用、false 恢复

include_byok_in_limit
boolean
expires_at
string or null <date-time>

改到期时间;显式 null = 取消到期(与 limit 字段语义一致)。 ⚠️ 到期的 key 调模型返回 401,与被吊销的表现完全一致:区分二者等于向持有无效 凭据的人确认「这把 key 曾经存在」。 ⚠️ 到期不会把 disabled 置为 true,该字段只表示「被停用」,判断到期请读 expires_at。

Responses

Request samples

Content type
application/json
{
  • "limit": 0,
  • "name": "string",
  • "disabled": true,
  • "include_byok_in_limit": true,
  • "expires_at": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Catalog

模型目录与单次调用回查

这个账号能用的模型和价格

带上推理 key,目录里就包含你自己配的模型:你在自己渠道上配的那些 ∪ 平台的那些, 同名时以你自己那条为准 —— 和真正调用时的路由口径完全一致。

凭据是可选的:不带任何请求头时返回平台目录(客户端确实这么用,这条路一直保留)。 但带了就必须是真的 —— 无效或过期的 key 返回 401,不会静默给你一份 「少了你自己模型」的目录。

推理 key 和母钥都可以。母钥没有绑 Router,它拿到的是账号默认那套路由的目录; 要看某一把绑了别的 Router 的子钥能用什么,就拿那把子钥来调。 对账 key 返回 403(它碰不到模型这一片)。

⚠️ 你自己渠道上的模型,pricing.prompt / completion 是 0:那些 token 你直接付给 上游,不经我们的价目表。真实成本读回包的 usage.cost。

Authorizations:
bearerAuthNone

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

按编号回查一次调用的真实成本

⚠️ 404 是正常路径,不是错误:用量记录在响应之后才写入。非流式通常 1 秒内可查, 流式以流结束为准;中途断开的流需事后向上游回查,可能到分钟级。 请把 404 当作「稍后再试」,退避几秒后重试。

Authorizations:
bearerAuth
query Parameters
id
required
string

响应头 X-Generation-Id 或回包 id 里的 gen-…

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Content

调用内容的留存开关与查看授权(ApiResponse 形状)

调用内容存不存、留多久、我们能不能看

这一组是留存开关本身(控制台上叫 Call Traces)。默认不存:关闭时 request_content / response_content 两列为空 —— 是没有存,不是存了不给看。

Authorizations:
bearerAuth
query Parameters
productLine
string

指定产品线;不传即账号级。 ⚠️ 只能放在 GET 的 query 上,写操作一律放在 body:前置网关会丢弃 POST/PUT 的 query string,写在 query 上不报错也不生效。

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": {
    }
}

开关保存、改留存期

Authorizations:
bearerAuth
Request Body schema: application/json
required
enabled
boolean
retentionDays
integer [ 1 .. 365 ]

默认 30;超出 1–365 返回 400

productLine
string

Responses

Request samples

Content type
application/json
{
  • "enabled": true,
  • "retentionDays": 1,
  • "productLine": "string"
}

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": {
    }
}

授权我们查看一段时间

⚠️ 没有「永久授权」这个选项,时长 1 小时 – 30 天:无时限的授权会在排查结束后 一直留存。授权期内每次读取都会记录审计。

Authorizations:
bearerAuth
Request Body schema: application/json
required
hours
integer [ 1 .. 720 ]
Default: 24
reason
string

给审计看的理由

productLine
string

Responses

Request samples

Content type
application/json
{
  • "hours": 24,
  • "reason": "string",
  • "productLine": "string"
}

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": {
    }
}

提前收回授权

到期的授权自动失效,无需处理。

Authorizations:
bearerAuth
Request Body schema: application/json
optional
productLine
string

Responses

Request samples

Content type
application/json
{
  • "productLine": "string"
}

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": {
    }
}

Reconciliation

给机器用的账务接口(ApiResponse 形状)

这把对账 key 是谁的、当前账期、能访问哪些资源

接入时从这里开始,否则「空数组」与「鉴权失败」无法区分。

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": {
    }
}

一期的勾稽:期初 + 本期变动 = 期末

Authorizations:
bearerAuth
query Parameters
period
string
Examples: period=2026-07

YYYY-MM,默认上一期(当月还在累加)

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": null
}

按天的用量汇总

读取夜间汇总表,当天部分为实时计算。⚠️ 单次查询窗口上限 100 天,超出返回 明确的错误,不做静默截断。

Authorizations:
bearerAuth
query Parameters
from
string <date>

含,默认本期第一天

to
string <date>

含,默认今天

apiKeyId
integer <int64>

只看某一把 key

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": null
}

余额、授信、可用额度

⚠️ 账号级:同一账号下所有 key 共享一个钱包。要限制单把 key 的消费用母钥的 limit,那是另一套机制。

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": {
    }
}

余额流水,分页

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": {
    }
}

已锁定的账单列表,最近的在前

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": [
    ]
}

成本归因:按模型、渠道、标签拆开

Authorizations:
bearerAuth

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": { }
}

某一期的账单详情

⚠️ 已锁定的账单不会被改写。 迟到的更正计入下一期,该行会注明来自哪个月。 如果你的 ERP 预期「更正到达后上个月的数字会变」,那不会发生。

Authorizations:
bearerAuth
path Parameters
period
required
string
Examples: 2026-07

Responses

Response samples

Content type
application/json
{
  • "code": 0,
  • "message": "string",
  • "success": true,
  • "data": null
}