Felo API PlatformFelo API Platform

指南

图片生成

异步提交图片生成与编辑任务,轮询状态并下载签名图片链接。

Felo 图片 API 使用 Felo 模型目录中的模型生成和编辑图片。它是异步的:提交请求会立即返回任务 ID,然后轮询任务直到进入终态。

本页说明图片接口的专属约定。通用任务生命周期见异步任务。

开始之前

  • API key。见认证。
  • model_kind 为 image_generation 的模型。见下文“查找图片模型”。
  • Base URL:https://openapi.felo.ai。

与 OpenAI Images API 的区别

路径与 OpenAI 的 Images API 相似,但响应不是:

OpenAI Images APIFelo 图片 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-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 列表中的 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 一起记录。

HTTPerror.code含义
400invalid_request_error缺少 model,或请求体不是 JSON 对象
400model_not_configured模型 ID 不在已启用的目录中
400chat_model_not_allowed把 chat 模型发到了图片 endpoint
400model_kind_mismatch把 video 或其他非图片模型发到了图片 endpoint
402insufficient_balance额度不足;任务没有创建
404generation_task_not_found任务 ID 不存在,或属于其他账号
429daily_spend_limit_exceeded达到账号的每日消费上限
503generation_unavailable生成服务暂时不可用;稍后重试

认证错误见错误、限流与重试。

相关