Felo API PlatformFelo API Platform

ガイド

画像生成

画像生成・編集タスクを非同期で送信し、ステータスをポーリングして署名付き 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 APIFelo 画像 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-image1K、2K、4K1:1、2:3、3:2、3:4、4:3、4:5、5:4、9:16、16:9、21:91最大 14 枚
gemini-nano-banana-2.11K、2K、4K1: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:91最大 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 と一緒に記録してください。

HTTPerror.code意味
400invalid_request_errormodel がない、または本文が JSON オブジェクトではない
400model_not_configuredモデル ID が有効なカタログにない
400chat_model_not_allowedchat モデルを画像 endpoint に送った
400model_kind_mismatchvideo など画像以外のモデルを画像 endpoint に送った
402insufficient_balanceクレジット不足。タスクは作成されていない
404generation_task_not_foundタスク ID が不明、または別のアカウントのもの
429daily_spend_limit_exceededアカウントの 1 日あたりの利用上限に達した
503generation_unavailable生成サービスが一時的に利用できない。後で再試行する

認証エラーはエラー、レート制限、リトライを参照してください。

関連