คู่มือ
การสร้างภาพ
สร้างและแก้ไขภาพแบบอะซิงโครนัส: ส่งงาน ติดตามจนเสร็จ และดาวน์โหลด URL ผลลัพธ์ที่ลงนามแล้ว
API รูปภาพของ Felo สร้างและแก้ไขรูปภาพด้วยโมเดลจากแค็ตตาล็อกโมเดล Felo การทำงานเป็นแบบอะซิงโครนัส: คำขอส่งงานจะให้ task ID กลับมาทันที และคุณโพลงานจนกว่าจะถึงสถานะสิ้นสุด
หน้านี้อธิบายสัญญาเฉพาะของรูปภาพ สำหรับวงจรชีวิตของงานที่ใช้ร่วมกัน ดูงานอะซิงโครนัส
ก่อนเริ่มต้น
- คีย์ API ดูการรับรองความถูกต้อง
- โมเดลที่มี
model_kindเป็นimage_generationดูค้นหาโมเดลรูปภาพ - Base URL
https://openapi.felo.ai
แตกต่างจาก OpenAI Images API อย่างไร
พาธคล้ายกับ Images API ของ OpenAI แต่การตอบกลับไม่เหมือนกัน:
| OpenAI Images API | Felo Image API | |
|---|---|---|
| การตอบกลับเมื่อส่งงาน | 200 พร้อมข้อมูลรูปภาพ | 202 พร้อม task_id, status: "queued" |
| เมื่อมีรูปภาพแล้ว | ในการตอบกลับเมื่อส่งงาน | หลังการโพลถึง succeeded |
| เนื้อหารูปภาพ | b64_json หรือ url | url ที่ลงนามและมีเวลาจำกัด |
| ข้อผิดพลาดของคำขอ | ข้อผิดพลาด HTTP ตอนส่งงาน | โดยปกติเป็น status: "failed" บนงาน |
ห้ามส่ง openai.images.generate() ไปยัง endpoint นี้ SDK คาดหวังอาร์เรย์ data แบบซิงโครนัสและไม่สามารถโพลงานได้ ให้เรียก endpoint ผ่าน HTTP และโพลงาน หรือเขียน wrapper ขนาดเล็กสำหรับทั้งสองขั้นตอน
ส่งงาน
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 หมายความว่าแพลตฟอร์มยอมรับงานแล้ว ไม่ได้หมายความว่าพรอมต์ พารามิเตอร์ หรือรูปภาพอ้างอิงถูกต้อง การเรียกไปยังต้นทางจะทำงานหลังการตอบกลับ ดังนั้นปัญหาคำขอส่วนใหญ่จะปรากฏในภายหลังเป็นงานที่ล้มเหลว ข้อยกเว้นคือการกำหนดเส้นทางโมเดล: โมเดลแชตหรือวิดีโอจะถูกปฏิเสธตอนส่งงาน
โพลจนกว่างานจะสิ้นสุด
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เป็น URL ที่ลงนามแล้ว ดาวน์โหลดได้โดยไม่ต้องใช้คีย์ API จึงควรปฏิบัติต่อ URL นี้เสมือนลิงก์แบบ bearer- URL มีเวลาจำกัด พารามิเตอร์คิวรี
expคือเวลาหมดอายุ ให้ดาวน์โหลดไฟล์และจัดเก็บไว้ใน bucket หรือระบบไฟล์ของคุณเอง งานไม่ได้เป็นที่จัดเก็บถาวร - การโพลอีกครั้งหลัง 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 โมเดลจะใช้รูปเหล่านี้เป็นบริบท ส่วนพรอมต์ยังคงอธิบายการเปลี่ยนแปลง
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"}
}
]
}'รูปอ้างอิงแต่ละรูปเป็น URL แบบ HTTP(S) หรือ data URL แบบ base64 ลำดับของรูปอ้างอิงจะคงเดิม ให้อ้างถึงรูปภาพตามตำแหน่งในพรอมต์เมื่อจำเป็น โมเดลปัจจุบันรองรับรูปอ้างอิงสูงสุด 14 รูป
ฟิลด์คำขอ
| ฟิลด์ | จำเป็น | คำอธิบาย |
|---|---|---|
model | ใช่ | ID โมเดลในแค็ตตาล็อก เช่น gemini-3-pro-image ห้ามใช้ ID ต้นทาง google/... |
prompt | ใช่ | คำสั่งเป็นข้อความ สำหรับการแก้ไข ให้อธิบายการเปลี่ยนแปลงและสิ่งที่ต้องคงไว้ |
resolution | ไม่ | ระดับเอาต์พุต โมเดลปัจจุบันรองรับ 1K, 2K หรือ 4K |
aspect_ratio | ไม่ | อัตราส่วนเอาต์พุต ค่าที่รองรับขึ้นอยู่กับโมเดล |
n | ไม่ | จำนวนรูปภาพ โมเดลปัจจุบันรองรับ 1 |
input_references | ไม่ | รูปภาพอ้างอิงสำหรับแก้ไขหรือประกอบภาพ |
โมเดลรูปภาพปัจจุบัน:
| Model 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 |
หากต้องการตรึงซัพพลายเออร์ ให้ส่ง header X-Felo-Channel พร้อมรหัสช่องทางจากรายการ channels ของโมเดล ดูช่องทางและการกำหนดเส้นทางผู้ให้บริการ
ค้นหาโมเดลรูปภาพ
ไม่มี 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} ส่งช่องทางและอัตราค่าบริการที่เผยแพร่ของโมเดล
supported_parameters ในแค็ตตาล็อกทั่วไปเป็นรายการระดับโปรโตคอล สำหรับโมเดลรูปภาพ ฟิลด์นี้ไม่ได้ระบุฟิลด์รูปภาพข้างต้นอย่างน่าเชื่อถือ จึงไม่ควรสร้างคำขอจากฟิลด์นี้ ให้ใช้ตารางฟิลด์ในคู่มือนี้และยืนยัน ID โมเดลจากแค็ตตาล็อก
ราคา
การสร้างรูปภาพเรียกเก็บเงินตามอัตราที่เผยแพร่ของโมเดล แค็ตตาล็อกเปิดเผย input_image และ output_image ควบคู่กับอัตราข้อความ prompt และ completion อัตรารูปภาพเป็นอัตราต่อโทเค็น: resolution เปลี่ยนจำนวนโทเค็นรูปภาพเอาต์พุตที่รูปหนึ่งใช้ ดังนั้นรูป 4K จึงมีค่าใช้จ่ายสูงกว่ารูป 1K รูปภาพอ้างอิงเพิ่มโทเค็นรูปภาพอินพุต
การตอบกลับของงานไม่มีออบเจกต์ 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 อยู่ใน header การตอบกลับ X-Request-Id ให้บันทึกไว้พร้อม ID งาน
| HTTP | error.code | ความหมาย |
|---|---|---|
| 400 | invalid_request_error | ไม่มี model หรือเนื้อหาคำขอไม่ใช่ออบเจกต์ JSON |
| 400 | model_not_configured | ID โมเดลไม่อยู่ในแค็ตตาล็อกที่เปิดใช้งาน |
| 400 | chat_model_not_allowed | ส่งโมเดลแชตไปยัง endpoint รูปภาพ |
| 400 | model_kind_mismatch | ส่งโมเดลวิดีโอหรือโมเดลที่ไม่ใช่รูปภาพอื่น |
| 402 | insufficient_balance | เครดิตไม่เพียงพอ ไม่มีการสร้างงาน |
| 404 | generation_task_not_found | ไม่รู้จัก ID งานหรือ ID งานเป็นของบัญชีอื่น |
| 429 | daily_spend_limit_exceeded | ถึงขีดจำกัดการใช้จ่ายรายวันของบัญชีแล้ว |
| 503 | generation_unavailable | การสร้างไม่พร้อมใช้งานชั่วคราว ให้ลองใหม่ภายหลัง |
ข้อผิดพลาดในการรับรองความถูกต้องอธิบายไว้ในข้อผิดพลาด ขีดจำกัด และการลองใหม่