গাইড
ছবি তৈরি
ছবি তৈরি ও সম্পাদনার কাজ অ্যাসিঙ্ক্রোনাসভাবে জমা দিন, স্ট্যাটাস পোল করুন এবং সাইন করা ছবির লিংক ডাউনলোড করুন।
Felo ইমেজ API Felo মডেল ক্যাটালগের মডেল দিয়ে ইমেজ জেনারেট ও এডিট করে। এটি অ্যাসিঙ্ক্রোনাস: সাবমিট অনুরোধ সাথে সাথে একটি টাস্ক ID ফেরত দেয়, এবং আপনি টাস্কটি টার্মিনাল অবস্থায় পৌঁছানো পর্যন্ত পোল করেন।
এই পেজে ইমেজ-নির্দিষ্ট চুক্তি আলোচনা করা হয়েছে। শেয়ার করা টাস্ক লাইফসাইকলের জন্য Async Tasks দেখুন।
শুরু করার আগে
- একটি API key। Authentication দেখুন।
- এমন একটি মডেল যার
model_kindহলোimage_generation। Find an Image Model দেখুন। - base URL
https://openapi.felo.ai।
OpenAI Images API থেকে এটি কীভাবে আলাদা
path OpenAI-র Images API-র মতো। রেসপন্স নয়:
| OpenAI Images API | Felo Image API | |
|---|---|---|
| সাবমিট রেসপন্স | ইমেজ ডেটাসহ 200 | task_id, status: "queued" সহ 202 |
| ইমেজ কখন থাকে | সাবমিট রেসপন্সে | পোলিং succeeded-এ পৌঁছানোর পরে |
| ইমেজ পেলোড | b64_json বা url | সময়সীমাবদ্ধ স্বাক্ষরিত url |
| অনুরোধ ত্রুটি | সাবমিটে HTTP ত্রুটি | সাধারণত টাস্কে status: "failed" |
এই endpoint-এ openai.images.generate() পাঠাবেন না। SDK একটি সিঙ্ক্রোনাস data অ্যারে প্রত্যাশা করে এবং টাস্ক পোল করতে পারে না। HTTP-র মাধ্যমে endpoint কল করে টাস্ক পোল করুন, অথবা উভয় ধাপের জন্য একটি ছোট 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 মানে প্ল্যাটফর্ম টাস্কটি গ্রহণ করেছে। এর মানে prompt, প্যারামিটার বা reference ইমেজ বৈধ তা নয়। রেসপন্সের পরে আপস্ট্রিম কল চলে, তাই বেশিরভাগ অনুরোধ সমস্যা পরে ব্যর্থ টাস্ক হিসেবে দেখা দেয়। ব্যতিক্রম মডেল রাউটিং: chat বা video মডেল সাবমিটেই প্রত্যাখ্যাত হয়।
টাস্ক টার্মিনাল হওয়া পর্যন্ত পোল করুন
curl "https://openapi.felo.ai/api/v1/images/generations/${TASK_ID}" \
-H "Authorization: Bearer ${FELO_API_KEY}"| স্ট্যাটাস | অর্থ | কী করবেন |
|---|---|---|
queued | গৃহীত; শুরু হওয়ার অপেক্ষায় | পোল করতে থাকুন |
running | মডেল জেনারেট করছে | পোল করতে থাকুন |
succeeded | টার্মিনাল; outputs পূর্ণ | output ডাউনলোড করুন |
failed | টার্মিনাল; error.message পড়ুন | অনুরোধ ঠিক করুন; অপরিবর্তিত অবস্থায় রিট্রাই করবেন না |
interrupted | টার্মিনাল; ফলাফল উদ্ধার করা যায়নি | টাস্ক আবার সাবমিট করুন |
টাস্ক ব্যর্থতায় HTTP স্ট্যাটাস 200 থাকে। কেবল HTTP স্ট্যাটাস নয়, body-তে status দেখুন।
2–5 সেকেন্ডের বিরতি দিয়ে শুরু করুন এবং ব্যাকঅফ করুন। বেশিরভাগ ইমেজ এক মিনিটের মধ্যে শেষ হয়; 4K output এবং অনেক reference ইমেজযুক্ত এডিট বেশি সময় নেয়। সবসময় নিজের একটি ডেডলাইন সেট করুন।
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")output পড়ুন ও সংরক্ষণ করুন
টাস্ক সফল হলে 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 key ছাড়াই ডাউনলোড হয়, তাই এটিকে bearer লিংক হিসেবে ধরুন।- URL সময়সীমাবদ্ধ।
expquery প্যারামিটার তার মেয়াদ সময়। ফাইলটি ডাউনলোড করে আপনার নিজের bucket বা ফাইলসিস্টেমে সংরক্ষণ করুন; টাস্ক স্থায়ী স্টোরেজ নয়। - 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-এ reference ইমেজ পাঠান। মডেল সেগুলো context হিসেবে ব্যবহার করে; 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"}
}
]
}'প্রতিটি reference একটি HTTP(S) URL বা একটি base64 data URL। reference-এর ক্রম সংরক্ষিত থাকে; গুরুত্বপূর্ণ হলে prompt-এ অবস্থান অনুযায়ী ইমেজ উল্লেখ করুন। বর্তমান মডেলগুলো সর্বোচ্চ 14টি reference গ্রহণ করে।
অনুরোধ ফিল্ড
| ফিল্ড | আবশ্যক | বর্ণনা |
|---|---|---|
model | হ্যাঁ | ক্যাটালগ মডেল ID, যেমন gemini-3-pro-image। আপস্ট্রিম google/... ID ব্যবহার করবেন না |
prompt | হ্যাঁ | টেক্সট নির্দেশনা। এডিটের জন্য পরিবর্তন এবং কী একই থাকতে হবে তা বর্ণনা করুন |
resolution | না | output টিয়ার। বর্তমান মডেল 1K, 2K বা 4K গ্রহণ করে |
aspect_ratio | না | output অনুপাত। গৃহীত মান মডেলের উপর নির্ভর করে |
n | না | ইমেজের সংখ্যা। বর্তমান মডেল 1 গ্রহণ করে |
input_references | না | এডিটিং বা কম্পোজিশনের জন্য reference ইমেজ |
বর্তমান ইমেজ মডেল:
| মডেল ID | রেজোলিউশন | Aspect ratio | প্রতি টাস্কে ইমেজ | Reference |
|---|---|---|---|---|
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 তালিকা থেকে একটি চ্যানেল কোডসহ X-Felo-Channel header পাঠান। Channels and Provider Routing দেখুন।
Find an Image Model (ইমেজ মডেল খুঁজুন)
আলাদা কোনো ইমেজ মডেল তালিকা endpoint নেই। সাধারণ ক্যাটালগ query করুন এবং 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 নিশ্চিত করুন।
মূল্য
ইমেজ জেনারেশন মডেলের প্রকাশিত রেট থেকে বিল হয়। ক্যাটালগ টেক্সট prompt ও completion রেটের পাশাপাশি input_image ও output_image প্রকাশ করে। ইমেজ রেটগুলো টোকেন রেট: resolution নির্ধারণ করে একটি ইমেজ কত output ইমেজ টোকেন খরচ করে, তাই একটি 4K ইমেজ 1K ইমেজের চেয়ে বেশি খরচ করে। reference ইমেজ input ইমেজ টোকেন যোগ করে।
টাস্ক রেসপন্সে usage অবজেক্ট থাকে না। চার্জের জন্য Console Billing দেখুন।
failed বা interrupted-এ শেষ হওয়া টাস্ক কোনো output তৈরি করে না এবং বিল হয় না। 402 দিয়ে প্রত্যাখ্যাত সাবমিট কোনো টাস্ক তৈরি করেনি।
ত্রুটি
ইমেজ রুটের endpoint-স্তরের ত্রুটি OpenAI error envelope ব্যবহার করে:
{
"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 রেসপন্স header-এ থাকে। এটি টাস্ক ID-সহ লগ করুন।
| HTTP | error.code | অর্থ |
|---|---|---|
| 400 | invalid_request_error | model অনুপস্থিত, বা body একটি JSON অবজেক্ট নয় |
| 400 | model_not_configured | মডেল ID সক্রিয় ক্যাটালগে নেই |
| 400 | chat_model_not_allowed | ইমেজ endpoint-এ একটি chat মডেল পাঠানো হয়েছে |
| 400 | model_kind_mismatch | একটি video বা অন্য নন-ইমেজ মডেল পাঠানো হয়েছে |
| 402 | insufficient_balance | যথেষ্ট ক্রেডিট নেই; কোনো টাস্ক তৈরি হয়নি |
| 404 | generation_task_not_found | টাস্ক ID অজানা বা অন্য অ্যাকাউন্টের |
| 429 | daily_spend_limit_exceeded | অ্যাকাউন্টের দৈনিক খরচের সীমা পৌঁছেছে |
| 503 | generation_unavailable | জেনারেশন সাময়িকভাবে অনুপলব্ধ; পরে রিট্রাই করুন |
প্রমাণীকরণ ত্রুটি Errors, Limits, and Retries-এ বর্ণিত।