> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apiyi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# APIYI 画像 API 統合実践: 独自の非同期キューを構築する

> APIYI の画像 API は同期型です。このガイドでは、その上に非同期タスクキューを構築する方法を紹介します: タスク単位の管理、リトライの分離、結果の永続化、複数プロバイダーの統合。

<Info>
  このページは、自社の製品に画像生成を統合する開発チーム向けの**技術共有 / アドバイザリー記事**です。ここで共有するのはエンジニアリングの実践のみで、APIYI側で何か変更を行う必要はありません。既存の同期APIの上に、そのすべてを実装できます。
</Info>

## 同期か、非同期か？まずは APIYI の API モデルを理解しましょう

APIYI の画像生成 API は**すべて同期**です。`/v1/images/generations` のようなエンドポイントは、リクエストを「送信すると完了まで処理する」形で動作します。クライアントが途中で切断されても、サーバーは生成を最後まで完了します。つまり、「まず task\_id を受け取り、そのあと結果をポーリングする」という**非同期タスク API**ではありません。

<Info>
  ゲートウェイ層では、APIYI がすでに上流の非同期ポーリング（プロバイダーによってはネイティブに `polling_url` ループを使います）を**同期的な OpenAI Images API** にラップしています。利用者側では常に「1 回送信して、1 回結果を受け取る」だけです。**自分でポーリングループを書く必要はありません**。
</Info>

多くのチームはすぐにこう考えます。「では、非同期タスク管理はどうすればいいの？」実際には、この 2 つは別物です。

* **同期** — APIYI API の形です（HTTP リクエストレベル: 1 回のリクエスト、1 つの結果）。
* **非同期キュー** — **利用者側の設計手法**です（ビジネスタスクレベル: すぐに応答し、バックグラウンドで実行する）。

この 2 つは矛盾しません。以下では、同期 API の上に非同期キューを自分で重ねる方法を説明します。

## なぜ開発チームは今でも「タスクレベル」の管理を必要とするのか

画像 API をユーザーのリクエストスレッド内で同期的に呼び出すのは、デモなら問題ありません。ですが、実際にエンドユーザー向けの本番プロダクトを作る段階になると、「ビジネスタスク」と「単一の HTTP 呼び出し」を切り離す必要がほぼ確実に出てきます。理由は 4 つあります。

<CardGroup cols={2}>
  <Card title="成功 ≠ 1 回の呼び出し" icon="repeat">
    「成功したタスク」は、しばしば**複数の同期呼び出し**をつなぎ合わせて成立します。最初のタイムアウトや、たまに発生する 429/503 はリトライが必要です。タスクと呼び出しを分離すると、リトライ、バックオフ、タイムアウトはすべてエンドユーザーからは見えなくなり、ユーザーが目にするのは「この画像は最終的に成功した」という結果だけです。
  </Card>

  <Card title="透明転送、保存なし" icon="database">
    APIYI は**透明転送のみを行い、ユーザー入力や出力を保存しません**（prompt、参照画像、生成結果は保持されません）。ユーザーに履歴、状態照会、結果の永続化を提供するには、**自分で保存する必要があります**。これはプロダクト側で避けられない工程です。
  </Card>

  <Card title="エンドユーザーにやさしい UX" icon="smile">
    ユーザーは送信時に `task_id` を受け取り、frontend は長時間の接続を張り続ける代わりに**タスク状態をポーリング**します。ページを再読み込みしても、短時間のネットワーク切断があってもタスクは失われません。バッチ生成もキューに積んで、1 件ずつ埋めていけます。
  </Card>

  <Card title="複数プロバイダ対応が可能に" icon="layers">
    独自のタスク抽象を持てば、Worker レイヤーは必要に応じて **複数のプロバイダ** 間で切り替え / フェイルオーバー / 価格比較を行えます。少なくとも、「卵を一つのかごに盛らない」ことを可能にします。
  </Card>
</CardGroup>

## リファレンスアーキテクチャ: 同期呼び出しを非同期キューで包む

核心となる考え方は一文です。**API 層は「タスクを受け取り、キューに入れて、task\_id を返す」だけで、実際の同期呼び出しはバックグラウンド Worker が行います。**

```text theme={null}
  Client/Frontend ──①submit──▶  API layer  ──②enqueue──▶  Queue (Redis / MQ / DB table)
        ▲                          │                                  │
        │ ⑤poll task status         │ return task_id now                │ ③pull task
        │                          ▼                                  ▼
        └────────────────────  Database  ◀──④persist(status/input/url)── Worker
                                                                        │ sync call APIYI
                                                                        │ (with retry/backoff)
                                                                        ▼
                                                            api.apiyi.com (sync image API)
```

<Steps>
  <Step title="すぐに返す">
    フロントエンドは生成リクエストを自分の API 層に送信します。API 層はタスクレコード（ステータス `pending`）を作成してキューに投入し、**`task_id` をフロントエンドへ即座に返します**。ユーザーは待たされることがなく、ミリ秒単位で応答が返ります。
  </Step>

  <Step title="キューに投入">
    キューは軽量なもので十分です。Redis List / Stream、RabbitMQ / Kafka、あるいはスケジュールで走査する `status` 列付きのデータベーステーブルでも構いません。どれを選ぶかは規模次第で、最初から重いミドルウェアを使う必要はありません。
  </Step>

  <Step title="Worker: 同期呼び出し + リトライ">
    バックグラウンド Worker がタスクを取り出し、ステータスを `running` に設定して、APIYI の画像 API を**同期的に呼び出します**。リトライ可能なエラーでは、指数バックオフでリトライします（下の「リトライと課金」を参照）。これらはすべてユーザーからは透過的です。
  </Step>

  <Step title="永続化">
    成功しても失敗しても、結果をデータベースに書き戻します。成功時は出力画像 URL、レイテンシ、課金メタデータを保存し、ステータスを `succeeded` に設定します。失敗時はエラーを保存し、ステータスを `failed` に設定します。**ここはまさに APIYI が代わりにやってくれない部分であり、ご自身で実装する必要があります。**
  </Step>

  <Step title="フロントエンドのポーリング">
    フロントエンドは定期的に `task_id` でタスクステータスを確認します（または WebSocket / SSE 経由でプッシュします）。タスクが完了したら結果を表示し、失敗したら分かりやすいメッセージを表示します。ユーザーのブラウザが長時間接続を保持する必要はありません。
  </Step>
</Steps>

## タスクの状態マシンとデータモデル

各タスクのライフサイクルは、明確な状態マシンで表します。

| 状態          | 意味                        | 典型的な遷移                                |
| ----------- | ------------------------- | ------------------------------------- |
| `pending`   | キューに入り、Worker を待機中        | → `running`                           |
| `running`   | Worker が APIYI を同期的に呼び出し中 | → `succeeded` / `retrying` / `failed` |
| `retrying`  | 再試行可能なエラーが発生し、バックオフ待ち     | → `running`                           |
| `succeeded` | 正常に生成され、結果が保存済み           | terminal                              |
| `failed`    | 再試行回数を使い切った、または再試行不可のエラー  | terminal                              |

タスクテーブルには、少なくとも次のフィールドを記録してください（型はスタックによって異なります）。

| フィールド                       | 説明                                    |
| --------------------------- | ------------------------------------- |
| `task_id`                   | 一意なタスク識別子。送信時にフロントエンドへ返します            |
| `status`                    | 上記のステータス enum                         |
| `provider` / `model`        | 使用したプロバイダとモデル（マルチプロバイダ向けに予約）          |
| `input`                     | ユーザー入力（prompt、参照画像の参照先、サイズ、その他のパラメータ） |
| `output_url`                | 結果の URL（できれば自前のストレージに再ホストした後のもの）      |
| `retry_count`               | これまでの再試行回数。レート制限とデバッグ用                |
| `error`                     | 失敗理由（エラーコード + わかりやすいメッセージ）            |
| `created_at` / `updated_at` | 作成時刻と最終更新時刻（タイムゾーンを含める。例: UTC+8）      |
| `latency` / `cost`          | レイテンシと課金メタデータ。コスト計算とモニタリング用           |

<Tip>
  生成された結果は **自前のオブジェクトストレージ**（OSS / S3 など）に再ホストし、その URL を永続化してください — サードパーティの一時リンクに長期的に依存しないでください。一時リンクは期限切れになることがあるため、自前のコピーを保持したほうがエンドユーザーにとって安定します。
</Tip>

## リトライと課金: 何を再試行し、何を再試行しないか

「タスク単位の管理」で最も価値があるのは、リトライを正しく扱えることです。課金とリトライ戦略はエラーの種類ごとに異なります。

| シナリオ                                     | 課金対象？          | 再試行？                                              |
| ---------------------------------------- | -------------- | ------------------------------------------------- |
| `429` / `503` (レート制限 / 上流ビジー)            | 課金対象外          | ✅ リトライ可、指数バックオフ、約2回                               |
| クライアントタイムアウト / 事前切断                      | **それでも課金されます** | ⚠️ 再試行は可能ですが、まず解像度ごとに妥当なタイムアウト（約60〜600秒）を設定してください |
| コンテンツ安全性による拒否 (status 200, still billed) | **それでも課金されます** | ❌ 再試行しないでください。ユーザーには親切なメッセージを返してください              |

<Warning>
  「**ビジネスタスクのリトライ回数**」と「**課金されたかどうか**」は別々に考慮してください。`429/503` のリトライは課金されないため、遠慮なくバックオフできます。しかし、タイムアウトによる切断やコンテンツ安全性の拒否は、「失敗」していても課金されます。やみくもに再試行すると**コストが増幅**します。再度費用を発生させる前に、まずエラー種別を確認してください。
</Warning>

エラー判定と親切なメッセージングの完全な基準については、以下を参照してください。

<CardGroup cols={2}>
  <Card title="Gemini 画像エラーハンドリング" icon="triangle-alert" href="/ja/api-capabilities/gemini-image-error-handling">
    失敗検出シグナル、コンテンツモデレーションポリシー、親切なメッセージ戦略。
  </Card>

  <Card title="生成失敗保証" icon="shield-check" href="/ja/api-capabilities/nano-banana-pro-guarantee">
    あなたに起因しない失敗については、クレジットが件数ベースで返還されます。
  </Card>
</CardGroup>

## 上級編: 1つのキュー、複数のプロバイダー

タスク抽象化を使うと、Worker の呼び出しを「1つのエンドポイントにハードコードされている状態」から「`provider`によってルーティングされる状態」へ移せます。単一の`submit(provider, payload)`エントリに統一し、Worker にタスクの`provider`フィールドに基づいて実際の上流先を判断させます。

* **フェイルオーバー**: プロバイダー A が失敗し続ける場合に、ユーザーに気付かれない形で自動的に B に切り替えます。
* **価格比較 / ルーティング**: コストやシナリオに応じて、異なるタスクを異なるプロバイダーやモデルへ振り分けます。
* **カナリア**: 新しいモデルに少量のトラフィックを送って検証し、その後で段階的に増やします。

<Info>
  多くの場合、実は自前のマルチプロバイダー層は**不要**です。APIYI 自体が gpt-image-2、Nano Banana、FLUX、Seedream などを集約しているため、1つの APIYI キーで 1つの API スタイルのままほとんどの要件をカバーできます。自前のプロバイダー抽象化は「念のため」の選択肢であり、プロバイダー横断のフェイルオーバーや価格比較が本当に必要なときだけ追加してください。
</Info>

## よくある質問

<AccordionGroup>
  <Accordion title="なぜ、同期型ではなく非同期タスク API をそのまま提供しないのですか？">
    画像生成は本質的に「1回送信して、1枚の画像を受け取る」という強い同期的な意味合いを持っており、ほとんどの利用者にとっては同期 API として包むのが最も簡単です（ポーリングの維持も、タスク期限切れへの対応も不要です）。非同期キュー、ステートマシン、永続化が必要かどうかは、あなたの**プロダクトの形**（エンドユーザー向けかどうか、履歴が必要かどうか）によるため、最大限の柔軟性のために、その部分は必要に応じてご自身で実装してください。
  </Accordion>

  <Accordion title="クライアントがタイムアウトして切断された場合、タスクはまだ実行中ですか？課金されますか？">
    実行は継続されます。同期エンドポイントは一度リクエストを受け取ると完了まで実行されるため、クライアントの切断ではサーバー側の生成は**中断されず**、その生成は**通常どおり課金**されます。そのため、解像度に応じて十分なタイムアウトを設定してください（約60〜600秒）——短くしすぎて「画像を受け取れないのに支払う」ことがないようにしてください。
  </Accordion>

  <Accordion title="APIYI は私の画像生成履歴を保存しますか？">
    いいえ。APIYI は**透過的な転送のみ**を行い、ユーザーの入力や出力を保存しません。ユーザーに履歴、ステータス照会、結果の永続化を提供するには、あなた側で永続化する必要があります——だからこそ、このガイドでは「タスクレベルの管理」を推奨しています。
  </Accordion>

  <Accordion title="すでに単一の APIYI キーを使っていますが、それでもマルチプロバイダー層は必要ですか？">
    通常は不要です。APIYI はすでに複数のモデルファミリーを 1 つの API スタイルにまとめており、単一のキーで十分なことがほとんどです。クロスプロバイダーのフェイルオーバー、価格比較、コンプライアンスルーティングといった明確な要件がある場合にのみ、Worker 層にプロバイダー抽象化を追加することを検討してください。これは任意であり、必須ではありません。
  </Accordion>
</AccordionGroup>

## 関連ドキュメント

<CardGroup cols={2}>
  <Card title="Image API の基礎とベストプラクティス" icon="book-check" href="/ja/api-capabilities/image-api-best-practices">
    モデルごとのタイムアウト表、base64 の取り扱い、URL 出力のリファレンスです。
  </Card>

  <Card title="非同期 API がない理由" icon="circle-help" href="/ja/faq/image-async-api">
    FAQ: 非同期の画像 API はありますか？ task ID で結果を問い合わせできますか？
  </Card>

  <Card title="FLUX の概要" icon="sparkles" href="/ja/api-capabilities/flux/overview">
    上流の非同期ポーリングを同期的な OpenAI Images API にラップした例です。
  </Card>

  <Card title="Nano Banana 開発ガイド" icon="compass" href="/ja/api-capabilities/nano-banana-dev-guide">
    同期マルチスレッド呼び出し、タイムアウト設定、課金の基本をまとめて確認できます。
  </Card>

  <Card title="Gemini 画像エラー処理" icon="triangle-alert" href="/ja/api-capabilities/gemini-image-error-handling">
    失敗検知シグナルと親しみやすいメッセージ戦略です。
  </Card>

  <Card title="生成失敗保証" icon="shield-check" href="/ja/api-capabilities/nano-banana-pro-guarantee">
    ご自身が原因ではない失敗に対するクレジット返還ルールです。
  </Card>
</CardGroup>
