Guias
Geração de imagens
Gere e edite imagens de forma assíncrona: envie uma tarefa, consulte a conclusão e baixe URLs de saída assinadas.
A API de imagens da Felo gera e edita imagens com modelos do catálogo de modelos Felo. Ela é assíncrona: a requisição de envio retorna um ID de tarefa imediatamente, e você consulta a tarefa até que ela alcance um estado terminal.
Esta página cobre o contrato específico de imagens. Para o ciclo de vida compartilhado das tarefas, consulte Tarefas assíncronas.
Antes de começar
- Uma chave de API. Consulte Autenticação.
- Um modelo cujo
model_kindsejaimage_generation. Consulte Encontre um modelo de imagem. - A URL base
https://openapi.felo.ai.
Como difere da API Images da OpenAI
O caminho é parecido com o da API Images da OpenAI. A resposta não é:
| API Images da OpenAI | API de imagens da Felo | |
|---|---|---|
| Resposta do envio | 200 com os dados da imagem | 202 com task_id e status: "queued" |
| Quando a imagem existe | Na resposta do envio | Depois que a consulta chega a succeeded |
| Payload da imagem | b64_json ou url | Uma url assinada com prazo de validade |
| Erros de requisição | Erro HTTP no envio | Normalmente status: "failed" na tarefa |
Não envie openai.images.generate() para este endpoint. O SDK espera um array data síncrono e não consegue consultar uma tarefa. Chame o endpoint via HTTP e consulte a tarefa, ou escreva um pequeno wrapper para as duas etapas.
Envie uma tarefa
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"
}'Um envio bem-sucedido retorna HTTP 202:
{
"task_id": "6d1f0c9a-...",
"status": "queued",
"kind": "image",
"outputs": []
}202 significa que a plataforma aceitou a tarefa. Não significa que o prompt, os parâmetros ou as imagens de referência sejam válidos. A chamada ao upstream acontece depois da resposta, então a maioria dos problemas de requisição aparece mais tarde como uma tarefa com falha. A exceção é o roteamento de modelos: um modelo de chat ou de vídeo é rejeitado no envio.
Consulte até a tarefa chegar ao estado terminal
curl "https://openapi.felo.ai/api/v1/images/generations/${TASK_ID}" \
-H "Authorization: Bearer ${FELO_API_KEY}"| Status | Significado | O que fazer |
|---|---|---|
queued | Aceita; aguardando início | Continue consultando |
running | O modelo está gerando | Continue consultando |
succeeded | Terminal; outputs está preenchido | Baixe as saídas |
failed | Terminal; leia error.message | Corrija a requisição; não tente novamente sem alterações |
interrupted | Terminal; o resultado não pôde ser recuperado | Reenvie a tarefa |
Falhas de tarefa mantêm o status HTTP em 200. Verifique status no corpo, não apenas o status HTTP.
Comece com um intervalo de 2–5 segundos e aumente. A maioria das imagens termina em até um minuto; saída em 4K e edições com muitas imagens de referência levam mais tempo. Defina sempre o seu próprio prazo limite.
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")Leia e armazene as saídas
Quando a tarefa tem sucesso, outputs contém uma entrada por imagem gerada:
{
"task_id": "6d1f0c9a-...",
"status": "succeeded",
"kind": "image",
"outputs": [
{
"media_type": "image/png",
"url": "https://openapi.felo.ai/api/v1/media/...?exp=...&sig=..."
}
]
}outputsfica vazio até a tarefa ter sucesso.urlé uma URL assinada. Ela é baixada sem chave de API, então trate-a como um link bearer.- A URL tem prazo de validade. O parâmetro de consulta
expé o horário de expiração. Baixe o arquivo e armazene-o no seu próprio bucket ou sistema de arquivos; a tarefa não é armazenamento permanente. - Consultar novamente depois que a URL expira retorna a mesma URL expirada. Não é emitida uma URL nova.
- A resposta não inclui dados de imagem em 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)Edite uma imagem
Passe imagens de referência em input_references. O modelo as usa como contexto; o prompt ainda descreve a alteração.
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"}
}
]
}'Cada referência é uma URL HTTP(S) ou uma URL de dados base64. A ordem das referências é preservada; mencione as imagens pela posição no prompt quando isso importar. Os modelos atuais aceitam até 14 referências.
Campos da requisição
| Campo | Obrigatório | Descrição |
|---|---|---|
model | Sim | ID de modelo do catálogo, por exemplo gemini-3-pro-image. Não use o ID upstream google/... |
prompt | Sim | Instrução em texto. Para uma edição, descreva a alteração e o que deve permanecer igual |
resolution | Não | Faixa de saída. Os modelos atuais aceitam 1K, 2K ou 4K |
aspect_ratio | Não | Proporção de saída. Os valores aceitos dependem do modelo |
n | Não | Número de imagens. Os modelos atuais aceitam 1 |
input_references | Não | Imagens de referência para edição ou composição |
Modelos de imagem atuais:
| ID do modelo | Resoluções | Proporções | Imagens por tarefa | Referências |
|---|---|---|---|---|
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 | Até 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 | Até 14 |
Para fixar um fornecedor, envie o cabeçalho X-Felo-Channel com um código de canal da lista channels do modelo. Consulte Canais e roteamento de provedores.
Encontre um modelo de imagem
Não existe um endpoint separado para listar modelos de imagem. Consulte o catálogo geral e filtre por 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} retorna os canais do modelo e as tarifas publicadas.
supported_parameters no catálogo geral é uma lista de nível de protocolo. Para modelos de imagem, ele não enumera de forma confiável os campos de imagem acima, então não monte sua requisição a partir dele. Use a tabela de campos deste guia e confirme o ID do modelo no catálogo.
Preços
A geração de imagens é cobrada com base nas tarifas publicadas do modelo. O catálogo expõe input_image e output_image ao lado das tarifas de texto prompt e completion. As tarifas de imagem são tarifas por token: resolution muda quantos tokens de imagem de saída uma imagem consome, então uma imagem 4K custa mais que uma imagem 1K. Imagens de referência adicionam tokens de imagem de entrada.
A resposta da tarefa não inclui um objeto usage. Verifique a cobrança em Console Billing.
Uma tarefa que termina em failed ou interrupted não produz saída e não é cobrada. Um envio rejeitado com 402 não criou uma tarefa.
Erros
Erros no nível do endpoint da rota de imagens usam o envelope de erro da OpenAI:
{
"error": {
"message": "Model kind does not match this generation endpoint",
"type": "invalid_request_error",
"param": null,
"code": "model_kind_mismatch"
}
}O request ID fica no cabeçalho de resposta X-Request-Id. Registre-o junto com o ID da tarefa.
| HTTP | error.code | Significado |
|---|---|---|
| 400 | invalid_request_error | model está faltando ou o corpo não é um objeto JSON |
| 400 | model_not_configured | O ID do modelo não está no catálogo habilitado |
| 400 | chat_model_not_allowed | Um modelo de chat foi enviado ao endpoint de imagens |
| 400 | model_kind_mismatch | Um modelo de vídeo ou outro modelo que não é de imagem foi enviado |
| 402 | insufficient_balance | Créditos insuficientes; nenhuma tarefa foi criada |
| 404 | generation_task_not_found | O ID da tarefa é desconhecido ou pertence a outra conta |
| 429 | daily_spend_limit_exceeded | O limite diário de gastos da conta foi atingido |
| 503 | generation_unavailable | A geração está temporariamente indisponível; tente novamente mais tarde |
Erros de autenticação são descritos em Erros, limites e novas tentativas.