> ## Documentation Index
> Fetch the complete documentation index at: https://dripart-chore-mintlify-theme-mint.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# キューによる配信

> Comfy Router にリクエストを送信すると、すぐにリクエスト ID が返ります。その後はステータスを追跡し、結果を取得するかキャンセルできます。Python、TypeScript、cURL に対応し、各 SDK の submit、subscribe、handle を使用します。

`POST /v2/models/{provider}/{model}` は、モデルの処理が完了するまで接続を保持します。キュー経由の配信は同じモデル ID と同じネイティブなリクエストボディを使用しますが、Router が実行を受理した時点で応答を返します。`request_id` をすぐに受け取り、準備ができたときに同じプロセスまたは別のプロセスから結果を取得します。

**同期ルートには 10 分の上限があります。** この上限こそがこのページが存在する理由です。Router のデフォルトのデッドラインは 10 分（デプロイごとに設定可能）であり、同期呼び出しがそこに達すると、プロバイダーがまだ処理を続けていても `504` / `deadline_exceeded` で切断されます。それより長く実行される可能性がある生成や、10 分間接続を開いたままにできない呼び出し元は、キューを使用する必要があります。デッドラインが課金について何を伝え、何を伝えないかについては、[サーバーのデッドラインで呼び出しが切断される](/ja/development/comfy-router/limitations#サーバーのデッドラインで呼び出しが打ち切られます) を参照してください。

キューは、1 回の生成が自分が保持できる接続時間より長引く可能性がある場合、Web リクエストが今すぐ応答を返す必要がある場合、あるプロセスで送信して別のプロセスで結果を取得する場合、あるいは多数の生成を同時に進行させたい場合に使用します。順序付け、受付、リトライ、タイムアウト、課金、有効期限はすべてサーバー側で決定されます。SDK はその上にポーリングと使いやすさを追加するだけで、それ以外は何も行いません。

## 2つの配信モード、1つのリクエスト

|      | 同期                                                                                                                       | キュー中                                                    |
| ---- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------- |
| ルート  | `POST /v2/models/{provider}/{model}`                                                                                     | `POST /v2/models/{provider}/{model}/requests`           |
| 応答   | モデルのネイティブ出力を含む `200`                                                                                                     | `request_id` と3つのURLを含む `201`                           |
| 結果   | レスポンス内                                                                                                                   | 後で収集され、バイト単位で同一の出力                                      |
| 時間制限 | Router の [10分のデッドライン](/ja/development/comfy-router/limitations#サーバーのデッドラインで呼び出しが打ち切られます)、その後 `504` / `deadline_exceeded` | 実行には制限なし。完了した結果は [24時間保持されます](#idempotency-and-billing) |

SDK（`comfy-sdk` および `@comfyorg/sdk`、0.3.0 以降）は、`run` の隣にキューを3つのメソッドとして公開しています:

* **`submit(model, body)`** はリクエストを送信し、すぐにハンドルを返します。ハンドルは `status()`、`get()`、`cancel()`、そしてイベントイテレータ（Python では `iter_events()`、TypeScript では `events()`）を備えています。
* **`subscribe(model, body, ...)`** は送信、ポーリング、収集を1回の呼び出しで行い、進捗コールバックを備えています。
* **`handle(model, request_id)`** は2つのIDから別のプロセスでハンドルを再構築します。呼び出しは発生しません。

両方の ID がリクエストの指定に関わるため、どの場面でも両方の ID が必要です。ルートは `/v2/models/{provider}/{model}/requests/{request_id}` です。

<Note>
  ここでの `events()` は、Comfy Cloud クライアントの `job.events()` では**ありません**。こちらはステータスルートをポーリングし、Router リクエストのキューの観測結果（ステータスとキュー位置）を返します。Cloud の方は、ComfyUI ワークフロージョブの進行状況、プレビュー、出力を運ぶライブ SSE ストリームです。`subscribe()` はまた別のもので、イテレータではなく、送信、ポーリング、収集を1回の呼び出しにまとめたものです。詳しくは [`events()` is not `subscribe()`](/ja/development/api-development/sdks#events-は-subscribe-ではない) を参照してください。
</Note>

## 4つのルート

| ルート                                                              | 応答                                                                                        |
| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `POST /v2/models/{provider}/{model}/requests`                    | `request_id`、`status`、`queue_position`、`status_url`、`response_url`、`cancel_url` を含む `201` |
| `GET /v2/models/{provider}/{model}/requests/{request_id}/status` | 現在の `status` と `queue_position`、および `Retry-After` ヒントを含む `200`                            |
| `GET /v2/models/{provider}/{model}/requests/{request_id}`        | 完了後はモデルネイティブの出力を含む `200`、未完了の間はステータスボディを含む `202`                                          |
| `PUT /v2/models/{provider}/{model}/requests/{request_id}/cancel` | `202` `CANCELLATION_REQUESTED`、または `409` `ALREADY_COMPLETED`                              |

`status` は `IN_QUEUE`、`IN_PROGRESS`、`COMPLETED` のいずれかです。失敗やキャンセル済みを表す独立したステータスはありません。成功しなかったリクエストは `error_type` を持つ `COMPLETED` になるため、4つ目のステータス値ではなく、このフィールドの有無で分岐してください。SDK はこれを自動で処理します。`get()` は失敗を結果として返すのではなく、型付きの Router エラーを送出または reject します。

進捗イベント、webhook、優先度レベルはありません。リクエストを追跡する手段はステータスルートです。[API リファレンス](/ja/development/comfy-router/reference#エンドポイント)に、各ルートの完全なコントラクトが記載されています。

## リクエストをキューに登録する

[クイックスタート](/ja/development/comfy-router/quickstart)が送信するのと同じリクエストをキューに登録し、画像を収集します。まずキーを `COMFY_API_KEY` としてエクスポートしてください。

<CodeGroup>
  ```python Python theme={null}
  from comfy_sdk import Comfy

  # 環境変数 COMFY_API_KEY を読み取ります。
  # 各 submit() 呼び出しは独自の Idempotency-Key を発行し、自動リトライで再利用します。
  with Comfy() as client:
      handle = client.models.submit(
          "bfl/flux-2-pro",
          {"prompt": "a red teapot on a windowsill, morning light"},
      )
      print("request_id:", handle.request_id)  # モデル ID と合わせれば、別プロセスが必要とする情報はこれだけです

      # リクエストが完了するまでポーリングし、サーバーが示す Retry-After の秒数だけ待機します。
      for update in handle.iter_events():
          print(update.status, update.queue_position)

      # プロバイダー自身のペイロードで、models.run() が返すのと同じ値です。
      # 失敗またはキャンセルされたリクエストは、ここで型付きの Router エラーを送出します。
      result = handle.get()

  print("image:", result["result"]["sample"])
  ```

  ```typescript TypeScript theme={null}
  import { comfy } from "@comfyorg/sdk";

  // 環境変数 COMFY_API_KEY を読み取ります。
  // 各 submit() 呼び出しは独自の Idempotency-Key を発行し、自動リトライで再利用します。
  type FluxResult = { result: { sample: string } };
  const handle = await comfy.models.submit<FluxResult>("bfl/flux-2-pro", {
    prompt: "a red teapot on a windowsill, morning light",
  });
  console.log("requestId:", handle.requestId); // モデル ID と合わせれば、別プロセスが必要とする情報はこれだけです

  // リクエストが完了するまでポーリングし、サーバーが示す Retry-After の秒数だけ待機します。
  for await (const update of handle.events()) {
    console.log(update.status, update.queuePosition);
  }

  // models.run() が返すのと同じ結果です。失敗またはキャンセルされたリクエストは、ここで reject されます。
  const result = await handle.get();
  if (result.kind !== "json") throw new Error("expected a JSON result");

  console.log("image:", result.data.result.sample);
  ```

  ```bash cURL theme={null}
  BASE="https://api.comfy.org/v2/models/bfl/flux-2-pro"

  # 1. 送信。Router は request_id、status_url、response_url、cancel_url とともに 201 を返します。
  curl "$BASE/requests" \
    -H "X-API-Key: $COMFY_API_KEY" \
    -H "Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d '{"prompt": "a red teapot on a windowsill, morning light"}'

  # 2. status が COMPLETED になるまでポーリングし、各レスポンスが示す Retry-After 秒だけ待機します。
  REQUEST_ID="<request_id from the 201 body>"
  curl -i "$BASE/requests/$REQUEST_ID/status" -H "X-API-Key: $COMFY_API_KEY"

  # 3. 収集。完了時はモデルネイティブの出力とともに 200、まだ実行中はステータスボディとともに 202 を返します。
  curl "$BASE/requests/$REQUEST_ID" -H "X-API-Key: $COMFY_API_KEY"

  # 4. 完了していないリクエストをキャンセルします。あくまでリクエストであり、保証ではありません。
  curl -X PUT "$BASE/requests/$REQUEST_ID/cancel" -H "X-API-Key: $COMFY_API_KEY"
  ```
</CodeGroup>

各[モデルページ](/ja/development/comfy-router/models)では、同期スニペットの隣にある **Queue and collect later** タブに、そのモデル向けのこの形が記載されています。

### 進捗を追跡して 1 回の呼び出しで収集する

待機しつつ進捗も表示したい場合は、`subscribe` が送信、ポーリング、収集を 1 回の呼び出しにまとめます:

<CodeGroup>
  ```python Python theme={null}
  def on_update(update):
      print(update.status, update.queue_position)

  result = client.models.subscribe(
      "bfl/flux-2-pro",
      {"prompt": "a red teapot on a windowsill, morning light"},
      on_queue_update=on_update,
      timeout=300,
  )
  ```

  ```typescript TypeScript theme={null}
  const result = await comfy.models.subscribe<FluxResult>(
    "bfl/flux-2-pro",
    { prompt: "a red teapot on a windowsill, morning light" },
    {
      onQueueUpdate: (update) => console.log(update.status, update.queuePosition),
      timeoutMs: 300_000,
    },
  );
  ```
</CodeGroup>

タイムアウトはクライアント側の制限であり、サーバー側の意味はありません。タイムアウトすると、`subscribe` は例外を送出する前にベストエフォートのキャンセルを 1 回行います。キャンセルは、まだ実行が始まっていないリクエストにのみ効果があります。パートナー側ですでに実行中の生成は、誰が収集するかに関わらず完了し、課金されます。呼び出し元より長く存続すべきリクエストには `submit` を使用してください。

### 別のプロセスから収集する

`request_id` はモデル ID の隣に保存してください。ハンドルを再構築するには両方が必要で、実際に使うまで呼び出しは行われません。

<CodeGroup>
  ```python Python theme={null}
  handle = client.models.handle("bfl/flux-2-pro", request_id)
  result = handle.get()
  ```

  ```typescript TypeScript theme={null}
  const handle = comfy.models.handle<FluxResult>("bfl/flux-2-pro", requestId);
  const result = await handle.get();
  ```
</CodeGroup>

### ステータスの確認またはキャンセル

`status()` は 1 回のポーリングで、現在の状態を返します。`cancel()` は、まだ完了していないリクエストを停止するようサーバーに要求します。これはリクエストであり、保証ではありません。パートナー側ですでに処理中の実行はそのまま完了する可能性があり、次に `status()` が返す内容が真実です。

<CodeGroup>
  ```python Python theme={null}
  update = handle.status()
  print(update.status, update.queue_position, update.error_type)

  handle.cancel()
  ```

  ```typescript TypeScript theme={null}
  const update = await handle.status();
  console.log(update.status, update.queuePosition, update.errorType);

  await handle.cancel();
  ```
</CodeGroup>

### 非同期 Python

`AsyncComfy` はすべての名前、引数、引数の順序をミラーします。`run_async` が存在しないのと同じ理由で、`submit_async` も存在しません。

```python theme={null}
from comfy_sdk import AsyncComfy

async with AsyncComfy() as client:
    handle = await client.models.submit(
        "bfl/flux-2-pro",
        {"prompt": "a red teapot on a windowsill, morning light"},
    )
    async for update in handle.iter_events():
        print(update.status, update.queue_position)
    result = await handle.get()
```

### SDK が送出するエラー

成功せずに終了したリクエストは、`error_type` を持つ `COMPLETED` として報告されます。`get()` と `subscribe()` はそれをバケットごとの型付き Router エラーに変換します。Python では `comfy_sdk.router_exceptions` のクラス、TypeScript では `routerErrors.*` です。イベントイテレーターはこのケースでは例外を送出しません。これはキューの進捗を映すビューだからです。`error_type` を持つ完了は最後の観測として yield され、収集を行うのは `get()` です。送信時の `403` `not_enabled` は `NotEnabled` として届き、終端となるため、SDK はリトライしません。

## レスポンスの形式

**送信、`201`。** この時点で `status` は常に `IN_QUEUE` です。3 つの URL は絶対 URL で、送信時と同じキーで認証されます。

```json theme={null}
{
  "request_id": "6f1a1a6e-6a53-4a5f-9d3a-2b3b0a1f9c21",
  "status": "IN_QUEUE",
  "queue_position": 3,
  "status_url": "https://api.comfy.org/v2/models/bfl/flux-2-pro/requests/6f1a1a6e-6a53-4a5f-9d3a-2b3b0a1f9c21/status",
  "response_url": "https://api.comfy.org/v2/models/bfl/flux-2-pro/requests/6f1a1a6e-6a53-4a5f-9d3a-2b3b0a1f9c21",
  "cancel_url": "https://api.comfy.org/v2/models/bfl/flux-2-pro/requests/6f1a1a6e-6a53-4a5f-9d3a-2b3b0a1f9c21/cancel"
}
```

`request_id` は送信時の `X-Comfy-Request-Id` ヘッダーの値でもあります。モデル ID も一緒に控えておいてください。リクエストはその両方で指定されます。

**ステータス、`200`。** 同じ形状で、現在の状態が入ります。`queue_position` は自分の前にあるリクエストを数え、実行が先頭に来ると `0` になります。このレスポンスの `Retry-After` は、再度ポーリングする価値があるのはいつかについての Router の推定値です。これはヒントであり制約ではなく、キューの後方にあるリクエストはすでに実行中のものよりも長く待つよう通知されます。より速くポーリングしても早く何かが分かるわけではなく、自身のレート制限の許容量を消費するだけです。

```json theme={null}
{
  "request_id": "6f1a1a6e-6a53-4a5f-9d3a-2b3b0a1f9c21",
  "status": "IN_PROGRESS",
  "queue_position": 0,
  "status_url": "...",
  "response_url": "...",
  "cancel_url": "..."
}
```

成功せずに完了したリクエストは `COMPLETED` で、`error_type` を持ち、結果の読み取りが `X-Comfy-Error-Type` に付けるのと同じ粗いバケットを運びます。このフィールドは成功時には `null` ではなく存在しません。

```json theme={null}
{
  "request_id": "6f1a1a6e-6a53-4a5f-9d3a-2b3b0a1f9c21",
  "status": "COMPLETED",
  "error_type": "content_policy_violation",
  "status_url": "...",
  "response_url": "...",
  "cancel_url": "..."
}
```

**結果。** `200` はモデル自身のネイティブ出力を、同じモデルと入力に対して同期ルートが返すものとバイト単位で完全に同一のまま、プロバイダー自身の `Content-Type` で返します。リクエストが未完了の間、読み取りは上記のステータスボディを伴う `202` を返すため、結果 URL だけをポーリングするクライアントは 1 つの型だけを解析します。失敗したリクエストは、`X-Comfy-Error-Type` が設定されたエラーレスポンスとして返り、同期ルートと同じバケットです。

**キャンセル。** `CANCELLATION_REQUESTED` を伴う `202` は、要求が受け付けられたことを意味し、実行が停止したことを意味するものではありません。パートナー側ですでに実行中のランはそのまま完了する可能性があり、完了したパートナー生成は、誰かがそれを取得するかどうかに関わらず課金されます。その後ステータスを読み取ってください。有効になったキャンセルは `error_type: cancelled` を伴う `COMPLETED` として表示されます。実行される前に期限切れになったリクエストも同様に `queue_timeout` を表示します。すでに完了していたリクエストは `ALREADY_COMPLETED` を伴う `409` を返します。

<h2 id="idempotency-and-billing">
  冪等性と課金
</h2>

* **同期ルートと同じ課金。** 課金はプロバイダーが Comfy に課金したタイミングで発生します。キューでの待機に費やした時間は課金されません。
* **送信ごとに 1 つの `Idempotency-Key`。** SDK は `submit` 呼び出しごとに新しいキーを生成するため、同じ入力に対する意図的な 2 回の送信は 2 つのリクエストになります。同じキーでの同じ呼び出しの再試行は、2 回目の実行をキューに入れません。オリジナルのハンドルを `Idempotent-Replayed: true` とともに返します。レスポンスの消失によって `request_id` を失う可能性がある場合は、独自のキーを渡してください。[Headers](/ja/development/comfy-router/headers) を参照してください。
* **結果は失効します。** 完了したリクエストは、完了後 24 時間保持されます。その後、ステータスと結果の読み取りは `410` を返し、結果は失われます。速やかに収集し、出力が持つアセット URL をダウンロードしてください。
* **ポーリングもリクエストです。** ステータスと結果の読み取りも、[呼び出し元ごとのリクエストレート](/ja/development/comfy-router/limitations#リクエストは呼び出し元ごとにレート制限される)にカウントされます。固定の短い間隔でポーリングするのではなく、`Retry-After` に従ってください。

## エラー

| Status | `X-Comfy-Error-Type`         | 意味                                                                                                                            |
| ------ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `402`  | `insufficient_credits`       | ワークスペースがこの実行を賄えない。何もキューに入らず、課金もされない。資金が確保されれば、同じ `Idempotency-Key` を再送できる。                                                    |
| `403`  | `not_enabled`                | この呼び出し元はキューを使用できない。背後にワークスペースが存在しないキー（ワークスペース以前のレガシーキー）、独自キーを持ち込むリクエスト、またはキューで実行できないモデルのいずれかである。そのリクエストはターミナルエラーであり、再試行しないこと。 |
| `404`  | `model_not_found`            | `{provider}/{model}` ID がどの Router モデルにも解決されない。                                                                               |
| `404`  | `request_not_found`          | この呼び出し元とモデルに対して、その ID のリクエストは存在しない。                                                                                           |
| `409`  | `concurrency_limit_exceeded` | 同じ `Idempotency-Key` がまだ受け付け処理中である。`Retry-After` の時間だけ待ち、同じキーを再送してオリジナルのハンドルを取得すること。                                          |
| `409`  | `invalid_input`              | その `Idempotency-Key` は別のリクエストによって保持されている。このリクエストは新しいキーで送信すること。                                                                |
| `409`  | ボディ内の `ALREADY_COMPLETED`    | キャンセルルートのみ: リクエストはすでに完了していたため、キャンセルするものは何もなかった。                                                                               |
| `410`  |                              | リクエストは存在していたが、保持ウィンドウを過ぎている。完了から 24 時間後。その ID に対しては恒久的なもの。                                                                    |
| `422`  | `invalid_input`              | モデルが入力を受け付けなかった。ボディには、同期ルートとまったく同じように、フィールドごとの詳細が含まれる。                                                                        |

すべてのエラーレスポンスには `X-Comfy-Request-Id` が含まれる。サポートに連絡する際はこれを伝えること。

<h2 id="next">
  Next
</h2>

<CardGroup cols={2}>
  <Card title="クイックスタート" icon="rocket" href="/ja/development/comfy-router/quickstart">
    同じモデルに対する同期呼び出しを、ゼロから画像生成まで。
  </Card>

  <Card title="モデル" icon="grid" href="/ja/development/comfy-router/models">
    各モデルのページには、そのモデルとボディに対応するキュー用スニペットがあります。
  </Card>

  <Card title="ヘッダー" icon="list" href="/ja/development/comfy-router/headers">
    認証、冪等性、リクエスト ID、エラーバケット、リトライのペーシング。
  </Card>

  <Card title="API リファレンス" icon="book" href="/ja/development/comfy-router/reference#エンドポイント">
    4 つのキュールートを、フィールドごとに解説します。
  </Card>
</CardGroup>
