# リクエスト

リクエストは、1つのモデルを1回呼び出すことです。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を1つ指定します。たとえば `text-to-video` や `upscale`。`GET https://api.doitong.com/v1/categories` ですべての 21 とその件数を一覧表示します。 |
| `lab` | モデルのメーカー。名前またはidで指定します。たとえば `Google` や `black-forest-labs`。 |
| `family` | 前の行にある `family` id。1つのモデルのすべてのバリエーション（pro、fast、image-to-video、…）。 |
| `mode` | `exact`（入力から料金を計算）、`measured`（入力ファイルの長さまたはサイズから計算）、`estimate`（1回の実行あたりの推定料金）、`metered`（実際の使用状況に応じて請求。1回の実行あたりの上限あり）のいずれか。 |
| `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オブジェクトです。各モデルのページにパラメータが記載されています。
- 入力は請求前に検証されます。無効な入力には、問題のある `param` を含む `422 invalid_input` が返され、料金はかかりません。
- `?wait=N`（最大20秒）は、リクエストが完了するか時間切れになるまで呼び出しを保持します。
- `?webhook_url=https://…` は、リクエスト完了時に署名付きPOSTをそのURLへ送信します（[Webhook](https://doitong.com/developers/docs/webhooks)を参照）。
- `?storage=permanent` または `?storage=temporary` で出力ファイルの保持期間を選択します。指定しない場合はアカウント設定が適用されます（[ファイルの保存場所](#storage)を参照）。

リクエストの処理中は `202 Accepted`、waitの時間内に完了した場合（または後述の再生の場合）は `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` はすべてのモデルで共通です。生成されたファイルごとに1つのエントリがあり、`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` が返されます。
- 生成中の場合、キャンセルが転送され、`"cancel_requested": true` とともに `202` が返されます。モデルがそのまま完了した場合、リクエストは通常どおり成功し、請求されます。
- すでに最終状態の場合は `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`）、再度請求されません。
- モデルに到達する前に失敗した実行の後で、同じキーおよび本文を指定した場合（submit時の `upstream_error` または `internal_error`、`insufficient_credits`、`budget_exceeded`、`too_many_inflight`）：何も生成されず請求もされていないため、失敗を返す代わりにモデルが再実行されます。
- 同じキーで本文が異なる場合：`409 idempotency_mismatch`。
- キーは、それを送信したAPIキーごとにスコープされます。

## ファイルの保存場所

すべての出力ファイルは、リクエストが `succeeded` になる前にストレージへコピーされます。そのため、`outputs` 内のURLは当社のホスト上にあり、直接リンクできます。保持期間は選択できます。

| モード | 保持期間 | 料金 |
|---|---|---|
| `permanent`（デフォルト） | 削除するまで | 1GB・1か月あたり 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になります。早めにダウンロードしてください。
