Felo API PlatformFelo API Platform

Hướng dẫn

Tạo hình ảnh

Tạo và chỉnh sửa hình ảnh bất đồng bộ: gửi tác vụ, thăm dò đến khi hoàn tất và tải URL đầu ra đã ký.

API hình ảnh của Felo tạo và chỉnh sửa hình ảnh bằng các mô hình từ danh mục mô hình Felo. API này hoạt động bất đồng bộ: yêu cầu gửi đi trả về task ID ngay lập tức, và bạn thăm dò tác vụ cho đến khi nó đạt trạng thái kết thúc.

Trang này trình bày hợp đồng riêng cho hình ảnh. Về vòng đời tác vụ dùng chung, xem Tác vụ bất đồng bộ.

Trước khi bắt đầu

Khác biệt so với OpenAI Images API

Đường dẫn tương tự OpenAI Images API. Phản hồi thì không:

OpenAI Images APIFelo Image API
Phản hồi khi gửi200 kèm dữ liệu hình ảnh202 với task_id, status: "queued"
Khi hình ảnh tồn tạiTrong phản hồi gửiSau khi thăm dò đạt succeeded
Dữ liệu hình ảnhb64_json hoặc urlMột url đã ký, có giới hạn thời gian
Lỗi yêu cầuLỗi HTTP khi gửiThường là status: "failed" trên tác vụ

Không gửi openai.images.generate() đến endpoint này. SDK mong đợi một mảng data đồng bộ và không thể thăm dò tác vụ. Hãy gọi endpoint qua HTTP và thăm dò tác vụ, hoặc viết một lớp bọc nhỏ cho cả hai bước.

Gửi một tác vụ

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"
  }'

Một lần gửi thành công trả về HTTP 202:

{
  "task_id": "6d1f0c9a-...",
  "status": "queued",
  "kind": "image",
  "outputs": []
}

202 nghĩa là nền tảng đã chấp nhận tác vụ. Điều đó không có nghĩa là câu lệnh, tham số hoặc hình ảnh tham chiếu hợp lệ. Lệnh gọi thượng nguồn chạy sau khi phản hồi, nên hầu hết vấn đề về yêu cầu xuất hiện sau đó dưới dạng tác vụ thất bại. Ngoại lệ là định tuyến mô hình: mô hình chat hoặc video bị từ chối ngay khi gửi.

Thăm dò cho đến khi tác vụ kết thúc

curl "https://openapi.felo.ai/api/v1/images/generations/${TASK_ID}" \
  -H "Authorization: Bearer ${FELO_API_KEY}"
Trạng tháiÝ nghĩaCần làm gì
queuedĐã chấp nhận; đang chờ bắt đầuTiếp tục thăm dò
runningMô hình đang tạo sinhTiếp tục thăm dò
succeededKết thúc; outputs đã có dữ liệuTải các đầu ra
failedKết thúc; đọc error.messageSửa yêu cầu; không thử lại nguyên trạng
interruptedKết thúc; không thể khôi phục kết quảGửi lại tác vụ

Tác vụ thất bại vẫn giữ trạng thái HTTP là 200. Hãy kiểm tra status trong nội dung, không chỉ trạng thái HTTP.

Bắt đầu với khoảng thời gian 2–5 giây và giãn dần. Hầu hết hình ảnh hoàn tất trong vòng một phút; đầu ra 4K và các chỉnh sửa có nhiều hình ảnh tham chiếu mất lâu hơn. Luôn đặt thời hạn của riêng bạn.

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")

Đọc và lưu các đầu ra

Khi tác vụ thành công, outputs chứa một mục cho mỗi hình ảnh được tạo:

{
  "task_id": "6d1f0c9a-...",
  "status": "succeeded",
  "kind": "image",
  "outputs": [
    {
      "media_type": "image/png",
      "url": "https://openapi.felo.ai/api/v1/media/...?exp=...&sig=..."
    }
  ]
}
  • outputs trống cho đến khi tác vụ thành công.
  • url là URL đã ký. Có thể tải xuống mà không cần khóa API, nên hãy coi nó như một liên kết bearer.
  • URL có giới hạn thời gian. Tham số truy vấn exp là thời điểm hết hạn. Hãy tải tệp về và lưu vào bucket hoặc hệ thống tệp của riêng bạn; tác vụ không phải nơi lưu trữ vĩnh viễn.
  • Thăm dò lại sau khi URL hết hạn sẽ trả về cùng URL đã hết hạn đó. Nó không cấp URL mới.
  • Phản hồi không bao gồm dữ liệu hình ảnh 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)

Chỉnh sửa hình ảnh

Truyền hình ảnh tham chiếu trong input_references. Mô hình dùng chúng làm ngữ cảnh; câu lệnh vẫn mô tả thay đổi.

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"}
      }
    ]
  }'

Mỗi tham chiếu là một URL HTTP(S) hoặc một data URL base64. Thứ tự tham chiếu được giữ nguyên; hãy tham chiếu hình ảnh theo vị trí trong câu lệnh khi điều đó quan trọng. Các mô hình hiện tại chấp nhận tối đa 14 tham chiếu.

Các trường yêu cầu

TrườngBắt buộcMô tả
modelCóModel ID trong danh mục, ví dụ gemini-3-pro-image. Không dùng ID google/... của thượng nguồn
promptCóChỉ dẫn văn bản. Với thao tác chỉnh sửa, mô tả thay đổi và những gì phải giữ nguyên
resolutionKhôngBậc đầu ra. Các mô hình hiện tại chấp nhận 1K, 2K hoặc 4K
aspect_ratioKhôngTỷ lệ đầu ra. Giá trị được chấp nhận phụ thuộc vào mô hình
nKhôngSố lượng hình ảnh. Các mô hình hiện tại chấp nhận 1
input_referencesKhôngHình ảnh tham chiếu để chỉnh sửa hoặc ghép

Các mô hình hình ảnh hiện tại:

Model IDĐộ phân giảiTỷ lệ khung hìnhHình ảnh mỗi tác vụTham chiếu
gemini-3-pro-image1K, 2K, 4K1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:91Tối đa 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:91Tối đa 14

Để ghim một nhà cung cấp, hãy gửi header X-Felo-Channel với một mã kênh từ danh sách channels của mô hình. Xem Kênh và định tuyến nhà cung cấp.

Tìm mô hình ảnh

Không có endpoint liệt kê mô hình hình ảnh riêng. Hãy truy vấn danh mục chung và lọc theo 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} trả về các kênh và mức giá được công bố của mô hình.

supported_parameters trong danh mục chung là danh sách ở cấp giao thức. Với các mô hình hình ảnh, nó không liệt kê đáng tin cậy các trường hình ảnh ở trên, nên đừng xây dựng yêu cầu của bạn từ đó. Hãy dùng bảng trường trong hướng dẫn này và xác nhận model ID từ danh mục.

Giá

Việc tạo hình ảnh được tính phí theo mức giá được công bố của mô hình. Danh mục công bố input_image và output_image cùng với mức giá văn bản prompt và completion. Mức giá hình ảnh là mức giá token: resolution thay đổi số token hình ảnh đầu ra mà một hình ảnh tiêu thụ, nên một hình ảnh 4K tốn nhiều hơn một hình ảnh 1K. Hình ảnh tham chiếu làm tăng token hình ảnh đầu vào.

Phản hồi tác vụ không bao gồm đối tượng usage. Hãy kiểm tra Console Billing để xem khoản phí.

Một tác vụ kết thúc failed hoặc interrupted không tạo đầu ra và không bị tính phí. Một lần gửi bị từ chối với 402 đã không tạo tác vụ.

Lỗi

Lỗi ở cấp endpoint từ tuyến hình ảnh dùng cấu trúc lỗi của OpenAI:

{
  "error": {
    "message": "Model kind does not match this generation endpoint",
    "type": "invalid_request_error",
    "param": null,
    "code": "model_kind_mismatch"
  }
}

Request ID nằm trong header phản hồi X-Request-Id. Hãy ghi nó cùng với task ID.

HTTPerror.codeÝ nghĩa
400invalid_request_errorThiếu model, hoặc nội dung không phải đối tượng JSON
400model_not_configuredModel ID không có trong danh mục đang bật
400chat_model_not_allowedMột mô hình chat đã được gửi đến endpoint hình ảnh
400model_kind_mismatchMột mô hình video hoặc mô hình không phải hình ảnh đã được gửi
402insufficient_balanceKhông đủ tín dụng; không có tác vụ nào được tạo
404generation_task_not_foundTask ID không xác định hoặc thuộc tài khoản khác
429daily_spend_limit_exceededĐã đạt giới hạn chi tiêu hàng ngày của tài khoản
503generation_unavailableTạo sinh tạm thời không khả dụng; thử lại sau

Lỗi xác thực được mô tả trong Lỗi, giới hạn và thử lại.

Liên quan