# 請求

請求是對一個模型的一次呼叫。它包含 id（`req_…`）、狀態、以 API 點數計算的費用（1000 = 1 USD），以及成功時產生的檔案。以下每個端點針對每個模型都會回傳相同的物件。

## 尋找模型

包含全部 1,496 個模型的目錄是公開 JSON（不需要金鑰）：

```bash
curl "https://api.doitong.com/v1/models?category=text-to-video&lab=Google&limit=20"
```

| 查詢參數 | 說明 |
|---|---|
| `q` | 必須全部出現在名稱、id、製作者或標籤中的字詞，例如 `kling 3`。 |
| `category` | 一個類別 id，例如 `text-to-video` 或 `upscale`。`GET https://api.doitong.com/v1/categories` 會列出全部 21 個類別及其數量。 |
| `lab` | 模型的製作者，可使用名稱或 id，例如 `Google` 或 `black-forest-labs`。 |
| `family` | 來自前一列的 `family` id：同一模型的每個變體（pro、fast、image-to-video、…）。 |
| `mode` | `exact`（根據輸入計算價格）、`measured`（根據輸入檔案的長度或大小）、`estimate`（每次執行的預估價格）或 `metered`（依實際用量收費，每次執行有最高上限）。 |
| `limit`、`cursor` | 頁面大小（1 至 100，預設值 50）及上一頁的 `next_cursor`。 |

每一列都有 `id`、`name`、`lab`、`category`、`family`、`summary`、`tags`、`output_kind`、`docs_url` 和 `price` 物件（請參閱 [定價](https://doitong.com/developers/docs/pricing#price-objects)）。`GET https://api.doitong.com/v1/models/{model_id}` 會額外提供完整的輸入與輸出 JSON Schema、標準參數名稱、價格規則及輸入範例。未知的 `category` 或 `mode` 會回傳 `400 invalid_parameter`。

## 執行模型

```bash
curl -X POST "https://api.doitong.com/v1/run/{model_id}?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1842-cover" \
  -d '{"prompt": "..."}'
```

- 本文體是模型輸入，一個 JSON 物件。每個模型頁面都會列出其參數。
- 輸入會在收費前先經過檢查。無效輸入會回傳 `422 invalid_input` 及有問題的 `param`，且不會產生費用。
- `?wait=N`（最多 20 秒）會持續等待，直到請求完成或時間到期。
- `?webhook_url=https://…` 會在請求完成時，向該 URL 傳送已簽署的 POST（請參閱 [Webhook](https://doitong.com/developers/docs/webhooks)）。
- `?storage=permanent` 或 `?storage=temporary` 會選擇輸出檔案的保留時間；未指定時套用帳戶設定（請參閱[檔案儲存位置](#storage)）。

請求仍在處理時，回應為 `202 Accepted`；在等待期間完成時（或這是重播請求，請見下文），回應為 `200 OK`。`Location` 和 `Doitong-Request-Id` 標頭會提供請求 URL 和 id。

## 狀態

請求生命週期: `queued` → `running` → `succeeded` | `failed` | `canceled` (完成；失敗和已取消的請求會退款).

| 狀態 | 說明 | 最終狀態 |
|---|---|---|
| `queued` | 已接受並收費，等待工作程序處理。`queue_position` 可能會顯示排隊位置。 | 否 |
| `running` | 模型正在產生內容。 | 否 |
| `succeeded` | 已完成。`outputs` 會列出檔案。 | 是 |
| `failed` | 模型或限制使其停止。`error` 會說明原因。API 點數會退款。 | 是 |
| `canceled` | 在產生結果前取消。API 點數會退款。 | 是 |

執行時間超過時限的請求會以 `timeout` 代碼失敗並退款：圖像為 15 分鐘、影片為 60 分鐘、音訊及其他項目為 30 分鐘。

## 請求物件

```json
{
  "id": "req_8k2m4q7x1z9c3v5b6n0p2r4t",
  "object": "request",
  "model": "flux/schnell",
  "status": "succeeded",
  "created_at": "2026-10-20T12:00:00Z",
  "started_at": "2026-10-20T12:00:01Z",
  "completed_at": "2026-10-20T12:00:02Z",
  "queue_position": null,
  "cost": { "credits": 3, "usd": "0.003", "charged": 3, "refunded": 0 },
  "input": { "prompt": "..." },
  "output": { "images": [ { "url": "https://content.doitong.com/dev-api/…/0-output.jpeg", "width": 1024, "height": 768 } ] },
  "outputs": [
    { "type": "image", "url": "https://content.doitong.com/dev-api/…/0-output.jpeg", "content_type": "image/jpeg",
      "width": 1024, "height": 768, "file_size": 183920, "stored": true }
  ],
  "error": null,
  "metrics": { "inference_seconds": 1.2 },
  "storage": { "mode": "permanent", "bytes": 183920, "expires_at": null, "expired": false },
  "urls": {
    "self": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t",
    "cancel": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel"
  }
}
```

- `outputs` 對每個模型都相同：每個產生的檔案各有一個項目，包含 `type`（`image`、`video`、`audio`、`file` 或 `3d`）、我們儲存空間上的 `url`、`content_type`，以及在已知時提供的 `file_size`、`width`、`height`、`duration`。
- `output` 是模型自己的結果物件（其欄位列於每個模型頁面），包含相同的 URL。
- `storage` 說明檔案的保留方式：`mode`（`permanent` 或 `temporary`）、已儲存的 `bytes`、`expires_at`（暫存檔案刪除的時間，永久檔案為 `null`）及 `expired`（檔案消失後為 `true`）。
- `cost.credits` 是此次呼叫的 API 點數價格（`cost.usd` 為 USD），`cost.charged` 是從 API 餘額扣除的金額，`cost.refunded` 是退回的金額。對於 `metered` 模型，`cost.credits` 是開始時保留的最高點數（`cost.held`）；執行成功後，`cost.settled` 會顯示實際用量，最高點數的剩餘部分會列在 `cost.refunded`（請參閱[依用量收費](https://doitong.com/developers/docs/pricing#metered)）。
- 請求失敗時，`error` 為 `{ "type": …, "code": …, "message": … }`。

## 讀取請求

```bash
curl "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

- `?wait=N`（最多 20 秒）會執行長輪詢：請求進入最終狀態時立即回傳，否則在 N 秒後回傳目前狀態。反覆執行這項操作是等待結果最簡單的方法。
- `?logs=1` 會將模型的進度記錄行（最後 50 行）以 `logs` 加入回應。

你只能讀取自己帳戶的請求；其他 id 會回傳 `404 request_not_found`。

## 列出請求

```bash
curl "https://api.doitong.com/v1/requests?limit=20&status=succeeded&model=flux/schnell" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

按照最新順序排列。`limit` 為 1 至 100（預設值 20），`status` 和 `model` 可用來篩選。回應為 `{ "object": "list", "data": [ … ], "has_more": true, "next_cursor": "req_…" }`；傳入 `cursor=<next_cursor>` 以取得下一頁。

## 取消請求

```bash
curl -X POST "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

- 在模型開始前取消：狀態變為 `canceled`，API 點數會退款，並回傳 `200`。
- 已開始產生：取消操作會轉交模型處理，並回傳 `202` 及 `"cancel_requested": true`。若模型仍完成，請求會正常成功並收費。
- 已是最終狀態：`409 not_cancelable`（已是 `canceled` 的請求會直接回傳 `200`）。

## 刪除請求的檔案

```bash
curl -X DELETE "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/files" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

立即刪除我們儲存的請求輸出檔案副本，並停止其儲存費用。回應是 `storage.expired: true` 的請求物件；其 URL 仍保留在記錄中，但不再有效。再次呼叫不會有任何變化（`200`）。仍處於 `queued` 或 `running` 狀態的請求尚無檔案：`409 request_active`。需要 `models:run`。

## 冪等性：重試而不重複付費

網路可能會失敗。若要安全地重試執行，請傳送 `Idempotency-Key` 標頭（任意最多 255 個字元的字串，每個操作都必須唯一，例如你自己的訂單 id）：

- 相同金鑰及與之前相同的本文體：會取得原始請求（`200`，標頭為 `Idempotent-Replayed: true`），且不會再次收費。
- 相同金鑰及本文體，但先前的執行在到達模型前失敗（提交時為 `upstream_error` 或 `internal_error`，或為 `insufficient_credits`、`budget_exceeded`、`too_many_inflight`）：未產生任何內容，也未收費，因此重試會再次執行模型，而不是回傳失敗結果。
- 相同金鑰但本文體不同：`409 idempotency_mismatch`。
- 金鑰的適用範圍限於傳送該金鑰的 API 金鑰。

## 檔案儲存位置

每個輸出檔案都會在請求標記為 `succeeded` 前複製到我們的儲存空間，因此 `outputs` 中的 URL 位於我們自己的主機上，你可以直接連結到這些 URL。檔案的保留時間由你決定：

| 模式 | 保留時間 | 價格 |
|---|---|---|
| `permanent`（預設值） | 直到你刪除檔案 | 每 GB 每月 100 API 點數（$0.10），每日從 API 餘額扣款 |
| `temporary` | 7 天，之後刪除 | 免費 |

- 帳戶設定會決定新請求的設定： [控制台](https://doitong.com/developers/dashboard#balance)中的「永久保存檔案」切換開關，或使用 `PATCH https://api.doitong.com/v1/account/storage` 搭配 `{"mode": "temporary"}`。`GET https://api.doitong.com/v1/account` 會在 `storage` 下顯示該設定、你保留的位元組數及每月預估費用。
- 執行時的 `?storage=permanent|temporary`（MCP `run` 工具的 `storage` 引數）會覆寫該次執行的設定。
- 變更設定絕不會影響你已有的檔案；請使用 [`DELETE /requests/{id}/files`](#delete-files) 刪除這些檔案。
- 當 API 餘額無法支付儲存費用時，不會收費，你會收到電子郵件：請在 30 天內儲值，否則保留的檔案會變為暫存檔案，並在 7 天後刪除。

在少數我們的副本建立失敗的情況下，項目會有 `"stored": false`，而 URL 會是原始的短期有效 URL：請儘快下載。
