> For the complete documentation index, see [llms.txt](https://getsquish.gitbook.io/squish/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://getsquish.gitbook.io/squish/zh/can-kao/http-api.md).

# 托管 API

托管 API 会把一个 **有意上传的** 视频转换为带时间戳的 contact sheet JPEG，以及 JSON 元数据和时间码。工作流无法运行本地 [CLI](/squish/zh/can-kao/cli.md)/[MCP](/squish/zh/can-kao/mcp.md) 工具（CI、serverless、托管 agent、没有 ffmpeg）时就用它。对于本地工作流，优先使用 CLI/MCP server——它们会在你的机器上处理一切，不会上传任何内容。参见 [隐私与数据流](/squish/zh/primitive/privacy-and-data-flow.md).

契约字符串： `squish-http-v0` （见 [稳定性与版本控制](/squish/zh/can-kao/stability.md)).

## 端点

```
POST https://api.getsquish.app/v1/squish
```

一次同步请求就是整个任务——没有 job queue API、没有轮询端点、也没有 webhooks。

## 认证

* 请求头： `Authorization: Bearer <key>`
* 密钥格式： `sq_live_` + 40 个十六进制字符，在 [getsquish.app/api-keys](https://getsquish.app/api-keys) （邮箱 OTP 登录）时签发。
* 明文密钥会显示 **一次** ——系统只存储它的 SHA-256 哈希，因此丢失的密钥无法找回，只能替换。
* 缺失、格式错误或已撤销的密钥会返回 `401 invalid_key` ，在读取 body 之前。

## 请求

`multipart/form-data` ，且必须只包含一个文件字段，并且字段名必须是 **`video`** (`video=@clip.mov`）；其他文件部分会被忽略。

可选表单字段：

| 字段        | 数值                         | 默认值    | 说明                                                             |
| --------- | -------------------------- | ------ | -------------------------------------------------------------- |
| `density` | `3x3`, `4x4`, `5x5`, `6x6` | `3x3`  | 更高的密度会让每张 sheet 消耗更多 credits（[credits](#credits-and-pricing)). |
| `响应`      | `json`, `image`            | `json` | `image` 会直接返回第一张 sheet 的 JPEG（[见下文](#responseimage)).          |

{% hint style="warning" %}
**目前还没有 zoom window。** 托管 API 不接受 `start`/`end` ——一个请求始终覆盖整个 clip，且你发送的任何 `start`/`end` 字段都会被忽略。 [导航循环](/squish/zh/primitive/the-navigation-loop.md)的 zoom step 目前只支持本地 CLI/MCP。Window 支持会随着 video sessions 到来（一次上传，多次 squish）。
{% endhint %}

## JSON 响应

```json
{
  "job_id": "...",
  "input": "clip.mov",
  "duration": 10.0,
  "frames": 9,
  "sheets": 1,
  "density": "3x3",
  "credits_charged": 1,
  "credits_remaining": 33,
  "files": ["https://api.getsquish.app/v1/sheets/<job_id>/video.sheet-1.jpg"],
  "timecodes": [["0:00", "0:01", "0:02", "0:03", "0:05", "0:06", "0:07", "0:08", "0:10"]],
  "warnings": [],
  "contract": "squish-http-v0"
}
```

`文件` 是临时 capability URL（见 [任务生命周期](#job-lifecycle)）。Sheet 文件始终命名为 `video.sheet-N.jpg` ——服务器会用自己固定的名称存储上传内容，所以原始文件名不会出现在 URL 中；它会改为回显在 `input` 字段中（见 [文件名契约](/squish/zh/can-kao/sheet-format.md#filename-contract)). `timecodes[][]` 始终与打印在 sheet 像素上的标签一致——格式 `m:ss`，亚秒级 `m:ss.d` 适用于短视频片段，在这些片段里，整秒级别无法区分相邻单元格（见 [sheet 格式规范](/squish/zh/can-kao/sheet-format.md#timecode-grammar)）。长视频会按顺序生成多张 sheet——请全部读取。

### response=image

`response=image` 会直接返回 **第一张** sheet JPEG，而不是 JSON，元数据会放在响应头中： `x-squish-job` （任务 ID）和 `x-credits-remaining`。多 sheet 任务应使用默认 JSON 模式——image 模式不会包含其他 sheet 的 URL，也没有时间码。

## 错误

|    状态 | 错误                     | 含义                                       | 处理方式                                                                                                                              |
| ----: | ---------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `401` | `invalid_key`          | 凭证缺失、已撤销或错误                              | 从 [`/api-keys`](https://getsquish.app/api-keys).                                                                                  |
| `402` | `insufficient_credits` | 余额不足——对于从未付费的账户，在触发此错误之前，免费的每日额度已经自动应用过了 | 去充值 `/api-keys`，降低 `density`，或者发送更短的 clip；从未付费的账户也可以等待下一个 UTC 日。                                                                  |
| `413` | `too_large`            | 上传超过当前上限（`max_mb` 在 body 中）              | 裁剪/压缩，或使用更短的 clip / 更低的密度。                                                                                                        |
| `422` | `bad_request`          | 请求格式错误，或者 `density`/`响应` 值               | 请先修正请求再重试。                                                                                                                        |
| `422` | `unreadable_video`     | 上传内容无法被识别为视频                             | 请发送一个位于常见容器中的真实视频文件。                                                                                                              |
| `422` | `too_long`             | 时长超过上限（`max_s` 在 body 中）                 | 裁剪 clip 或发送更短的。                                                                                                                   |
| `429` | `busy`                 | 单任务 worker 已满                            | 请稍后再试。                                                                                                                            |
| `500` | `processing_failed`    | 引擎在扣费后失败                                 | 响应体为 `{ "error": "processing_failed", "refunded": true\|false }` — **check `refunded`**: `true` → 重试一次； `false` → 费用已保留，请报告，不要重试。 |

## 重试策略

哪些情况可以安全重试，取决于资金何时变动——credits 会在 *之后* 、在精确价格已知后，以原子方式扣除， *在……之前* 帧提取：

* **`401`** **`402`** **`413`** **`422` ——不要在请求未变时重试。** 没有产生任何扣费；同一个请求会以同样方式失败。请先修复原因（新密钥、充值、更小/更短的 clip、修正字段）。
* **`429` ——可以安全重试。** 没有产生任何扣费；服务一次只处理一个任务，并有一个短队列。任务只需几秒（12 秒的 clip 约 6 秒），所以稍等一下再重试（约 10–30 秒）。在 `Retry-After` 中没有 `squish-http-v0`.
* **`500` header——重试前请先读取 `refunded` body 中的内容。** `refunded: true` （正常情况）：费用已自动退回——重试一次，如果两次都失败则报告。 `refunded: false` （少见）：自动退款本身失败了，费用保留—— **不要** 盲目重试； `/api-keys` 上的使用表会记录真实净成本。
* **没有幂等键。** 每个被接受的请求都会成为一个新任务和一笔新收费——不要盲目重新发送一个可能已经成功的请求（断开的连接 *之后* 处理仍然会收费；请查看 `/api-keys`).

## 任务生命周期

1. 上传会流式写入磁盘（从不缓存在内存中）。
2. 探测 → 规划 → 定价 → 原子扣除 credits → 帧提取 → 响应。
3. 连接在整个处理期间会保持打开（典型 clip 只需几秒）。
4. `job_id` 中的响应是收据：它会出现在 sheet URL 和你在 `/api-keys`.

## 数据生命周期

托管 API 是一个 **计算服务，而不是存储服务** ——这是一个无状态任务，带有短暂的输出缓存。两类数据走的是不同轨道：

```
上传的视频 ──► 处理中 ──► 任务结束瞬间删除
                       │           （成功或失败）
                       ▼
              生成的 sheets ──► 临时缓存（约 24 小时） ──► 自动过期
```

* **上传的视频** 只用于处理携带它的请求，然后在任务结束的瞬间删除——无论成功还是失败。它从不保留，从不用于训练，也没有媒体库。
* **生成的 sheets** 会作为临时缓存保存在它们的 capability URL 上——大约保留 24 小时，方便你下载或重新获取这些 URL，然后它们会过期并自动删除。缓存不是存储：想保留的内容请及时下载。

需要更强的保障？在本地运行 Squish——本地 [CLI](/squish/zh/can-kao/cli.md) 和 [MCP 服务器](/squish/zh/can-kao/mcp.md) 永远不要上传你的视频。

## 限制

当前 v0 限制：

* 上传上限： **300 MB**
* 时长上限： **30 分钟**
* 一次只处理一个任务，并带有一个小队列；过载时返回 `429 忙碌`
* 输出是临时的，不是永久存储

## credits 和定价

credits 预付并按 **每个输出 sheet**计费，按密度：

| 密度    | 每张 sheet 的 credits |
| ----- | -----------------: |
| `3x3` |                  1 |
| `4x4` |                  2 |
| `5x5` |                  3 |
| `6x6` |                  5 |

现售套餐： **$3 = 30 credits · $9 = 120 credits · $29 = 500 credits.**

### 每日免费额度

一个 **从未购买过任何东西** （没有 web Pro，也没有 credit 包）会自动补到一个较低的下限——目前为 **7 credits** ——每 **UTC 日**，在当天第一个计费请求发现余额低于下限时发放。这是补到下限，而不是累加：未使用的额度不会叠加（昨天剩余的额度会减少今天的发放量，因此单个 UTC 日的消耗不会超过下限），达到或高于下限时不会发放，已购买的余额也不会被动用。

## 健康检查

```
GET https://api.getsquish.app/healthz
```

返回 `{ "ok": true, "contract": "squish-http-v0", "version": "…" }` ——无需认证。对 agent 来说很有用，可区分“API 挂了”还是“我的请求有问题”。

## sheet 是什么——以及不是什么

这样 agent 才能设定正确预期：

* **仅限视觉。** sheet 不包含音频、语音或 transcript。Squish 会看，不会听。
* **是序列图，不是运动替代品。** 帧会在整个 clip 中采样；采样之间发生的事件不可见。更密的网格（`4x4`–`6x6`）会缩小间隙，但不会消除它们。
* **输出仅为 JPEG contact sheet** （质量 0.70），密度 `3x3`–`6x6`.
* **服务端不会进行任何分析。** API 返回的是制品；阅读/推理是调用模型的工作。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://getsquish.gitbook.io/squish/zh/can-kao/http-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
