ガイド
画像生成
画像生成・編集タスクを非同期で送信し、ステータスをポーリングして署名付き URL をダウンロードします。
Felo の画像 API は、Felo モデルカタログのモデルで画像を生成・編集します。非同期 API です。送信リクエストはすぐにタスク ID を返し、タスクが終端状態になるまでポーリングします。
このページでは画像 API 固有の契約を説明します。共通のタスクライフサイクルは非同期タスクを参照してください。
開始前に
- API key。認証を参照してください。
model_kindがimage_generationのモデル。後述の「画像モデルを探す」を参照してください。- Base URL:
https://openapi.felo.ai。
OpenAI Images API との違い
パスは OpenAI の Images API に似ていますが、レスポンスは異なります。
| OpenAI Images API | Felo 画像 API | |
|---|---|---|
| 送信レスポンス | 200 で画像データを返す | 202 で task_id、status: "queued" を返す |
| 画像が存在するタイミング | 送信レスポンス内 | ポーリングが succeeded に到達した後 |
| 画像のペイロード | b64_json または url | 有効期限付きの署名付き url |
| リクエストエラー | 送信時に HTTP エラー | 通常はタスクの status: "failed" |
openai.images.generate() をこの endpoint に向けないでください。SDK は同期的な data 配列を想定しており、タスクをポーリングできません。HTTP で直接呼び出してポーリングするか、2 つのステップを自分でラップしてください。
タスクを送信する
curl -X POST "https://openapi.felo.ai/api/v1/images/generations" \
-H "Authorization: Bearer ${FELO_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-pro-image",
"prompt": "A studio product photo of a ceramic coffee cup on warm linen, soft morning light",
"resolution": "2K",
"aspect_ratio": "4:3"
}'送信に成功すると HTTP 202 が返ります。
{
"task_id": "6d1f0c9a-...",
"status": "queued",
"kind": "image",
"outputs": []
}202 はプラットフォームがタスクを受け付けたことだけを意味します。prompt、パラメータ、参考画像が有効であることを意味しません。上流の呼び出しはレスポンスの後に実行されるため、ほとんどのリクエスト問題は後から失敗タスクとして現れます。例外はモデルルーティングです。chat または video モデルは送信時に拒否されます。
終端状態までポーリングする
curl "https://openapi.felo.ai/api/v1/images/generations/${TASK_ID}" \
-H "Authorization: Bearer ${FELO_API_KEY}"| ステータス | 意味 | 対応 |
|---|---|---|
queued | 受け付け済み。開始待ち | ポーリングを続ける |
running | モデルが生成中 | ポーリングを続ける |
succeeded | 終端。outputs が入っている | 出力をダウンロードする |
failed | 終端。error.message を読む | リクエストを修正する。そのまま再試行しない |
interrupted | 終端。結果を復元できなかった | タスクを再送信する |
タスクが失敗しても HTTP ステータスは 200 のままです。HTTP ステータスだけでなく、レスポンス本文の status を確認してください。
2〜5 秒から始めて間隔を広げます。ほとんどの画像は 1 分以内に完了します。4K 出力や参考画像の多い編集にはより長くかかります。必ず独自の期限を設定してください。
import os
import time
import requests
BASE = "https://openapi.felo.ai"
HEADERS = {"Authorization": f"Bearer {os.environ['FELO_API_KEY']}"}
def generate_image(prompt: str, **params) -> list[dict]:
response = requests.post(
f"{BASE}/api/v1/images/generations",
headers=HEADERS,
json={"model": "gemini-3-pro-image", "prompt": prompt, **params},
timeout=30,
)
response.raise_for_status()
task = response.json()
deadline = time.monotonic() + 300
delay = 2.0
while time.monotonic() < deadline:
time.sleep(delay)
delay = min(delay * 1.5, 10.0)
poll = requests.get(
f"{BASE}/api/v1/images/generations/{task['task_id']}",
headers=HEADERS,
timeout=30,
)
poll.raise_for_status()
task = poll.json()
if task["status"] == "succeeded":
return task["outputs"]
if task["status"] in {"failed", "interrupted"}:
message = task.get("error", {}).get("message", task["status"])
raise RuntimeError(message)
raise TimeoutError(f"image task {task['task_id']} did not finish")出力を取得して保存する
タスクが成功すると、outputs に生成された画像ごとに 1 件のエントリが入ります。
{
"task_id": "6d1f0c9a-...",
"status": "succeeded",
"kind": "image",
"outputs": [
{
"media_type": "image/png",
"url": "https://openapi.felo.ai/api/v1/media/...?exp=...&sig=..."
}
]
}outputsはタスクが成功するまで空です。urlは署名付き URL です。API key なしでダウンロードできるため、bearer リンクとして扱ってください。- URL には有効期限があります。
expクエリパラメータが期限時刻です。ファイルをダウンロードして自分のバケットやファイルシステムに保存してください。タスクは永続ストレージではありません。 - URL の期限切れ後に再度ポーリングしても、同じ期限切れ URL が返るだけで、新しい URL は発行されません。
- レスポンスに base64 の画像データは含まれません。
for index, output in enumerate(outputs):
image = requests.get(output["url"], timeout=60)
image.raise_for_status()
with open(f"image-{index}.png", "wb") as file:
file.write(image.content)画像を編集する
参考画像は input_references で渡します。モデルはそれをコンテキストとして使いますが、prompt には変更内容を記述する必要があります。
curl -X POST "https://openapi.felo.ai/api/v1/images/generations" \
-H "Authorization: Bearer ${FELO_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-pro-image",
"prompt": "Keep the product and framing. Replace the background with a sunlit marble countertop.",
"resolution": "2K",
"aspect_ratio": "4:3",
"input_references": [
{
"type": "image_url",
"image_url": {"url": "https://example.com/product.png"}
}
]
}'各参考画像は HTTP(S) URL または base64 data URL です。参考画像の順序は保持されます。必要な場合は prompt 内で位置を指定して参照してください。現在のモデルは最大 14 枚の参考画像を受け付けます。
リクエストフィールド
| フィールド | 必須 | 説明 |
|---|---|---|
model | はい | カタログのモデル ID。例: gemini-3-pro-image。上流の google/... ID は使わないでください |
prompt | はい | テキスト指示。編集時は変更内容と維持すべき要素を記述します |
resolution | いいえ | 出力ティア。現在のモデルは 1K、2K、4K を受け付けます |
aspect_ratio | いいえ | 出力比率。受け付ける値はモデルによって異なります |
n | いいえ | 画像数。現在のモデルは 1 を受け付けます |
input_references | いいえ | 編集や構図に使う参考画像 |
現在の画像モデル:
| モデル ID | 解像度 | アスペクト比 | 1 タスクあたりの画像数 | 参考画像 |
|---|---|---|---|---|
gemini-3-pro-image | 1K、2K、4K | 1:1、2:3、3:2、3:4、4:3、4:5、5:4、9:16、16:9、21:9 | 1 | 最大 14 枚 |
gemini-nano-banana-2.1 | 1K、2K、4K | 1:1、1:4、1:8、2:3、3:2、3:4、4:1、4:3、4:5、5:4、8:1、9:16、16:9、21:9 | 1 | 最大 14 枚 |
特定のサプライヤーに固定するには、モデルの channels リストにある channel code を X-Felo-Channel ヘッダーで送ります。チャネルとプロバイダールーティングを参照してください。
画像モデルを探す
画像モデル専用のリスト endpoint はありません。一般カタログを取得し、model_kind でフィルタします。
curl "https://openapi.felo.ai/api/v1/models" \
-H "Authorization: Bearer ${FELO_API_KEY}" \
| jq '.data[] | select(.model_kind == "image_generation") | {id, name}'GET /api/v1/models/{model_id} はモデルの channels と公開レートを返します。
一般カタログの supported_parameters はプロトコルレベルのリストです。画像モデルでは上記の画像フィールドを確実に列挙しないため、これをもとにリクエストを組み立てないでください。このページのフィールド表を使い、モデル ID はカタログで確認してください。
料金
画像生成はモデルの公開レートで課金されます。カタログにはテキストの prompt と completion に加えて、input_image と output_image があります。画像レートは token レートです。resolution によって 1 枚の画像が消費する出力画像 token 数が変わるため、4K は 1K より高くなります。参考画像は入力画像 token を追加します。
タスクのレスポンスには usage オブジェクトが含まれません。実際の請求は Console Billing の利用記録で確認してください。
failed または interrupted で終了したタスクは出力がなく、課金されません。送信時に 402 が返った場合、タスクは作成されていません。
エラー
画像ルートの endpoint レベルのエラーは OpenAI エラーエンベロープを使います。
{
"error": {
"message": "Model kind does not match this generation endpoint",
"type": "invalid_request_error",
"param": null,
"code": "model_kind_mismatch"
}
}request ID は X-Request-Id レスポンスヘッダーにあります。task ID と一緒に記録してください。
| HTTP | error.code | 意味 |
|---|---|---|
| 400 | invalid_request_error | model がない、または本文が JSON オブジェクトではない |
| 400 | model_not_configured | モデル ID が有効なカタログにない |
| 400 | chat_model_not_allowed | chat モデルを画像 endpoint に送った |
| 400 | model_kind_mismatch | video など画像以外のモデルを画像 endpoint に送った |
| 402 | insufficient_balance | クレジット不足。タスクは作成されていない |
| 404 | generation_task_not_found | タスク ID が不明、または別のアカウントのもの |
| 429 | daily_spend_limit_exceeded | アカウントの 1 日あたりの利用上限に達した |
| 503 | generation_unavailable | 生成サービスが一時的に利用できない。後で再試行する |
認証エラーはエラー、レート制限、リトライを参照してください。