# 模型 (https://hypit.ai/zh/api-reference/models/)

> 查询你的 Key 能路由到哪些模型，以及花钱之前先看清它的额度费率。

模型目录是唯一权威地回答「这把 Key 能用哪些模型、每个模型多少钱」的地方。上游厂商会上下线，模型
可用性随之变化，所以请在运行时读取，不要把模型名写死。

## 列出模型 [#列出模型]

```bash
curl https://hypit.ai/v1/models \
  -H "Authorization: Bearer $HYPIT_API_KEY"
```

```json
{
  "object": "list",
  "data": [
    {
      "id": "nano-banana-pro",
      "object": "model",
      "created": 1787824589,
      "owned_by": "hypit",
      "modality": "image",
      "display_name": "Nano Banana Pro",
      "description": "…",
      "tags": ["image", "edit"],
      "endpoints": ["images", "image_edits"],
      "pricing": {
        "mode": "per_image",
        "currency": "usd",
        "per_image_usd": 0.0,
        "credits": { "base": 0.0 }
      }
    }
  ]
}
```

前四个字段（`id`、`object`、`created`、`owned_by`）与 OpenAI 的形状逐字节一致，所以未经改造的
OpenAI SDK 调 `client.models.list()` 可以直接用。后面的字段是我们自己的；不需要的客户端会自动忽略。

### `endpoints` [#endpoints]

最有用的一个字段。它写明这个模型实际能被哪几条路由接受，也是「为什么这个模型在 `/v1/videos` 上
404」的答案。取值是固定的：

| 取值               | 路由                                     |
| ---------------- | -------------------------------------- |
| `images`         | `POST /v1/images/generations`          |
| `image_edits`    | `POST /v1/images/edits`                |
| `videos`         | `POST /v1/videos`                      |
| `chat`           | `POST /v1/chat/completions`            |
| `gemini`         | `POST /v1beta/models/{model}:{action}` |
| `audio_speech`   | `POST /v1/audio/speech`                |
| `transcriptions` | `POST /v1/audio/transcriptions`        |
| `audio_music`    | `POST /v1/audio/music`                 |

`modality` 粒度更粗，取值是 `image`、`video`、`chat`、`audio` 之一，也就是 Job 信封里 `kind` 会
写的东西。

### `pricing` [#pricing]

`pricing.mode` 说明这个模型按什么计价：`per_image`、`per_request`、`per_second`、`per_token`、
`per_k_char` 或 `per_audio_second`。带 `*_usd&#x60; 的数字是已经含我们加价的零售价，作为参考保留；真正
要看的是 &#x2A;*`pricing.credits`**，因为额度是账号持有的唯一余额。

```json
"pricing": {
  "mode": "per_second",
  "currency": "usd",
  "per_second_usd": 0.0,
  "resolution_ratio": { "480p": 1, "720p": 2.1579, "1080p": 5.3684 },
  "credits": { "per_second": 0.0 }
}
```

`credits` 里的 token 费率按**每千 token** 计（`input_per_k`、`output_per_k`、`cached_per_k`、
`reasoning_per_k`），而旁边的 USD 字段按每百万计——厂商是这么发布的，我们的费率表也是这么存的。
四张比率表（`size_ratio`、`quality_ratio`、`resolution_ratio`、`flag_ratio`）是纯乘数：某模型
`resolution_ratio["1080p"]` 是 `5.3684`，那么一秒 1080p 的价格就是 `per_second × 5.3684`。

`token_tiers` 是长上下文阶梯，每一档带一个 `min_prompt_tokens` 阈值和该档之上适用的费率；某一档
里留成 0 的费率表示沿用头档费率。

<Callout type="info" title="不要用 USD 数字反推额度">
  从美元折算到额度时，中间有一个按模型设置的乘数，接口刻意不公开它。请直接读 `pricing.credits`；
  用一个固定系数去乘 `per_second_usd` 的客户端，会在促销模型和溢价模型上算错——而且是无声地错，
  恰好错在算错要花钱的地方。
</Callout>

## 取单个模型 [#取单个模型]

```bash
curl https://hypit.ai/v1/models/nano-banana-pro \
  -H "Authorization: Bearer $HYPIT_API_KEY"
```

模型 id 可以带命名空间斜杠，这条路由能完整接住：

```bash
curl https://hypit.ai/v1/models/bytedance/seedance-2 \
  -H "Authorization: Bearer $HYPIT_API_KEY"
```

返回的是单个模型卡片，也就是上面 `data` 数组里的一项。你的 Key 路由不到的模型返回 `404`
`model_not_found`——与「模型不存在」的返回完全一样：目录不会告诉你某个模型存在但你够不着。

## 匿名价目表 [#匿名价目表]

有一个不需要认证的端点，给定价页用，也给还没注册就想先看价格的人用：

```bash
curl https://hypit.ai/api/hub/public/models
```

```json
{
  "object": "list",
  "count": 18,
  "modalities": { "image": 7, "video": 9, "chat": 2, "audio": 0 },
  "updated_at": 1787824589,
  "data": [
    {
      "name": "bytedance/seedance-2",
      "modality": "video",
      "endpoints": ["videos"],
      "pricing": { "mode": "per_second", "unit": "per second", "currency": "usd", "credits": {} }
    }
  ]
}
```

注意它和 `/v1/models` 的差别：模型主键叫 `name` 而不是 `id`；`pricing` 多一个 `unit` 字符串，直接
写明头部数字按什么计；信封上带 `count`、`modalities` 和 `updated_at`，页面不必遍历列表就能渲染
「价格更新于……」。它也只展示默认路由组——你的 Key 在 `/v1/models` 上可能看到更多模型。

它按 IP 限流 60 次/分钟，从预渲染快照直接返回，带 `ETag`，并支持 `If-None-Match`：

```bash
curl -i https://hypit.ai/api/hub/public/models \
  -H 'If-None-Match: "ce323a…"'
```

## 在代码里挑模型 [#在代码里挑模型]

```python
import os, httpx

r = httpx.get(
    f"{os.environ['HYPIT_BASE_URL']}/models",
    headers={"Authorization": f"Bearer {os.environ['HYPIT_API_KEY']}"},
)
r.raise_for_status()

video = [m for m in r.json()["data"] if "videos" in m["endpoints"]]
for m in video:
    print(m["id"], m["pricing"]["credits"].get("per_second"), "额度/秒")
```

```js
const r = await fetch(`${process.env.HYPIT_BASE_URL}/models`, {
  headers: { Authorization: `Bearer ${process.env.HYPIT_API_KEY}` },
});
if (!r.ok) throw new Error(await r.text());

const { data } = await r.json();
for (const m of data.filter((m) => m.endpoints.includes("videos"))) {
  console.log(m.id, m.pricing.credits?.per_second, "额度/秒");
}
```