指南
圖片生成
非同步提交圖片生成與編輯任務,輪詢狀態並下載簽名圖片連結。
Felo 圖片 API 使用 Felo 模型目錄中的模型生成和編輯圖片。它是非同步的:提交請求會立即回傳任務 ID,然後輪詢任務直到進入終態。
本頁說明圖片介面的專屬約定。通用任務生命週期見非同步任務。
開始之前
- 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 呼叫並輪詢,或自己封裝這兩步。
提交任務
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。要檢查回應裡的 status,不能只看 HTTP 狀態。
從 2–5 秒開始,逐步退避。大多數圖片一分鐘內完成;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 每張圖片一個條目:
{
"task_id": "6d1f0c9a-...",
"status": "succeeded",
"kind": "image",
"outputs": [
{
"media_type": "image/png",
"url": "https://openapi.felo.ai/api/v1/media/...?exp=...&sig=..."
}
]
}- 任務成功前
outputs為空。 url是簽名連結,無需 API key 即可下載,請按 bearer 連結對待。- URL 有時效。
exp查詢參數就是過期時間。請下載檔案並存到你自己的儲存桶或檔案系統;任務不是永久儲存。 - 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 | 解析度 | 寬高比 | 單任務圖片數 | 參考圖 |
|---|---|---|---|---|
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 張 |
要固定供應商,傳送 X-Felo-Channel 請求標頭,值取自模型 channels 列表中的 channel code。見通道與供應商路由。
查找圖片模型
沒有獨立的圖片模型列表 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 會改變一張圖消耗的輸出圖片 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 | 達到帳號的每日消費上限 |
| 503 | generation_unavailable | 生成服務暫時不可用;稍後重試 |
認證錯誤見錯誤、限流與重試。