Felo API PlatformFelo API Platform

الأدلة

توليد الصور

ولّد الصور وحرّرها بشكل غير متزامن: أرسل مهمة، واستعلم حتى الاكتمال، ونزّل عناوين URL الموقّعة للمخرجات.

يولّد API الصور من Felo الصور ويحرّرها باستخدام نماذج من كتالوج نماذج Felo. وهو غير متزامن: يعيد طلب الإرسال معرّف مهمة فورًا، وتستطلع المهمة حتى تصل إلى حالة نهائية.

تغطي هذه الصفحة العقد الخاص بالصور. لدورة حياة المهام المشتركة، راجع المهام غير المتزامنة.

قبل أن تبدأ

كيف يختلف عن OpenAI Images API

المسار مشابه لواجهة OpenAI Images API. لكن الاستجابة ليست كذلك:

OpenAI Images APIFelo Image API
استجابة الإرسال200 مع بيانات الصورة202 مع task_id وstatus: "queued"
متى توجد الصورةفي استجابة الإرسالبعد وصول الاستطلاع إلى succeeded
حمولة الصورةb64_json أو urlurl موقّع محدود المدة
أخطاء الطلبخطأ HTTP عند الإرسالعادةً status: "failed" في المهمة

لا ترسل openai.images.generate() إلى هذا endpoint. تتوقع SDK مصفوفة data متزامنة ولا يمكنها استطلاع مهمة. استدعِ endpoint عبر 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 أن المنصة قبلت المهمة. ولا تعني أن الموجّه أو المعاملات أو الصور المرجعية صالحة. يجري استدعاء المنبع بعد الاستجابة، لذا تظهر معظم مشكلات الطلب لاحقًا كمهمة فاشلة. الاستثناء هو توجيه النموذج: يُرفض نموذج الدردشة أو الفيديو عند الإرسال.

استطلع حتى تصبح المهمة نهائية

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، لذا تعامل معه كرابط حامل (bearer).
  • عنوان URL محدود المدة. معامل الاستعلام exp هو وقت انتهاء صلاحيته. نزّل الملف وخزّنه في حاوية التخزين أو نظام الملفات لديك؛ فالمهمة ليست تخزينًا دائمًا.
  • إعادة الاستطلاع بعد انتهاء صلاحية عنوان 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) أو عنوان بيانات base64. يُحفظ ترتيب المراجع؛ وأشر إلى الصور بحسب موقعها في الموجّه عندما يكون ذلك مهمًا. تقبل النماذج الحالية ما يصل إلى 14 مرجعًا.

حقول الطلب

الحقلمطلوبالوصف
modelنعممعرّف النموذج في الكتالوج، مثل gemini-3-pro-image. لا تستخدم معرّف google/... الخاص بالمنبع
promptنعمنص التعليمات. للتحرير، صف التغيير وما يجب أن يبقى كما هو
resolutionلافئة الإخراج. تقبل النماذج الحالية 1K أو 2K أو 4K
aspect_ratioلانسبة الإخراج. تعتمد القيم المقبولة على النموذج
nلاعدد الصور. تقبل النماذج الحالية 1
input_referencesلاصور مرجعية للتحرير أو التركيب

نماذج الصور الحالية:

معرّف النموذجالدقاتنسب العرض إلى الارتفاعالصور لكل مهمةالمراجع
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

لتثبيت مزوّد، أرسل رأس X-Felo-Channel مع رمز قناة من قائمة channels الخاصة بالنموذج. راجع القنوات وتوجيه المزوّد.

Find an image model (العثور على نموذج صور)

لا يوجد 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 في الكتالوج العام قائمة على مستوى البروتوكول. وبالنسبة لنماذج الصور، فهي لا تعدّد حقول الصور أعلاه بشكل موثوق، لذا لا تبنِ طلبك منها. استخدم جدول الحقول في هذا الدليل وأكّد معرّف النموذج من الكتالوج.

التسعير

تُفوتر عملية توليد الصور وفق الأسعار المنشورة للنموذج. يعرض الكتالوج 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"
  }
}

يوجد معرّف الطلب في رأس الاستجابة X-Request-Id. سجّله مع معرّف المهمة.

HTTPerror.codeالمعنى
400invalid_request_errormodel مفقود، أو النص ليس كائن JSON
400model_not_configuredمعرّف النموذج غير موجود في الكتالوج الممكّن
400chat_model_not_allowedأُرسل نموذج دردشة إلى endpoint الصور
400model_kind_mismatchأُرسل نموذج فيديو أو نموذج آخر غير خاص بالصور
402insufficient_balanceأرصدة غير كافية؛ لم تُنشأ مهمة
404generation_task_not_foundمعرّف المهمة غير معروف أو يخص حسابًا آخر
429daily_spend_limit_exceededبلغ الحساب حد الإنفاق اليومي
503generation_unavailableالتوليد غير متاح مؤقتًا؛ أعد المحاولة لاحقًا

تُوصف أخطاء المصادقة في الأخطاء والحدود وإعادة المحاولة.

ذو صلة