Felo API PlatformFelo API Platform

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

Como difere da API Images da OpenAI

O caminho é parecido com o da API Images da OpenAI. A resposta não é:

API Images da OpenAIAPI de imagens da Felo
Resposta do envio200 com os dados da imagem202 com task_id e status: "queued"
Quando a imagem existeNa resposta do envioDepois que a consulta chega a succeeded
Payload da imagemb64_json ou urlUma url assinada com prazo de validade
Erros de requisiçãoErro HTTP no envioNormalmente 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}"
StatusSignificadoO que fazer
queuedAceita; aguardando inícioContinue consultando
runningO modelo está gerandoContinue consultando
succeededTerminal; outputs está preenchidoBaixe as saídas
failedTerminal; leia error.messageCorrija a requisição; não tente novamente sem alterações
interruptedTerminal; o resultado não pôde ser recuperadoReenvie 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=..."
    }
  ]
}
  • outputs fica 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

CampoObrigatórioDescrição
modelSimID de modelo do catálogo, por exemplo gemini-3-pro-image. Não use o ID upstream google/...
promptSimInstrução em texto. Para uma edição, descreva a alteração e o que deve permanecer igual
resolutionNãoFaixa de saída. Os modelos atuais aceitam 1K, 2K ou 4K
aspect_ratioNãoProporção de saída. Os valores aceitos dependem do modelo
nNãoNúmero de imagens. Os modelos atuais aceitam 1
input_referencesNãoImagens de referência para edição ou composição

Modelos de imagem atuais:

ID do modeloResoluçõesProporçõesImagens por tarefaReferências
gemini-3-pro-image1K, 2K, 4K1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:91Até 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:91Até 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.

HTTPerror.codeSignificado
400invalid_request_errormodel está faltando ou o corpo não é um objeto JSON
400model_not_configuredO ID do modelo não está no catálogo habilitado
400chat_model_not_allowedUm modelo de chat foi enviado ao endpoint de imagens
400model_kind_mismatchUm modelo de vídeo ou outro modelo que não é de imagem foi enviado
402insufficient_balanceCréditos insuficientes; nenhuma tarefa foi criada
404generation_task_not_foundO ID da tarefa é desconhecido ou pertence a outra conta
429daily_spend_limit_exceededO limite diário de gastos da conta foi atingido
503generation_unavailableA geração está temporariamente indisponível; tente novamente mais tarde

Erros de autenticação são descritos em Erros, limites e novas tentativas.

Relacionados