Documentação
Geração de imagens
Dois endpoints: texto para imagem e edição/conversão de imagem em imagem. Ambos retornam URLs de resultado permanentes: a Kunavo arquiva todas as imagens na própria CDN.
A Kunavo disponibiliza /v1/images/generations (texto para imagem) e /v1/images/edits (imagem para imagem/edição). Ambos são síncronos por padrão — a chamada fica bloqueada até a conclusão do processamento upstream e, em seguida, retorna as URLs dos resultados — ou use o modo assíncrono com "async": true ou um webhook_url.
Texto para imagem
Endpoint: POST /v1/images/generations. Use o método images.generate do SDK da OpenAI ou faça a chamada diretamente com curl.
img = client.images.generate(
model="nano-banana-pro",
prompt="a red origami crane on a white desk, soft window light",
size="1024x1024",
)
print(img.data[0].url)Parâmetros comuns
| Parâmetro | Tipo | Observações |
|---|---|---|
model | string | Qualquer slug de modelo de imagem de /v1/models. |
prompt | string | Prompt de texto. Sempre obrigatório. |
size | string | Formato no estilo OpenAI, como "1024x1024". Mapeado para a proporção do provedor upstream. |
quality | standard|hd | Quando compatível (gpt-image). |
resolution | 1K|2K|4K | Nível de resolução para modelos com níveis — veja abaixo Resolution tiers. A cobrança é feita por nível. |
n | int | Número de imagens. A maioria dos modelos retorna 1, independentemente do valor. |
input | object | Opção de escape — veja abaixo Raw input. |
files.kunavo.com: a Kunavo arquiva todas as imagens na própria CDN, então, ao contrário das URLs upstream diretas, elas nunca expiram. Se uma imagem não puder ser arquivada, a URL dela será a URL temporária do upstream, em outro host: baixe essa imagem e hospede-a novamente.Faixas de resolução
Vários modelos de imagem cobram preços escalonados de acordo com a resolução de saída. Informe resolution para escolher um nível; se omitir, será usado o nível padrão. A cobrança corresponde ao nível efetivamente produzido.
| Modelo (e sua variante -edit) | Níveis — preço de cada um | Padrão |
|---|---|---|
| nano-banana-2 | 1K $0.0469 · 2K $0.0707 · 4K $0.1057 | 1K |
| nano-banana-pro | 1K / 2K $0.067 · 4K $0.12 | 2K |
| gpt-image-2 | 1K / 2K / 4K — $0.0633 (valor fixo) | 1K |
A família veo-3 também tem níveis de resolução — os preços por nível estão na página de cada modelo em /models.
resolution = 4K com tamanho quadrado, a chamada será automaticamente reduzida para 2K, e a cobrança será feita nessa resolução.Edição de imagem/conversão de imagem em imagem
Endpoint: POST /v1/images/edits. Envie a imagem de origem como URL (HTTPS ou dados base64 em data:) por meio de image para edições de imagem única ou de image_urls para referências de várias imagens.
# Image edit / image-to-image: pass the source image URL
import requests
resp = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "gpt-image-2-edit",
"prompt": "recolor the crane to bright blue, keep composition",
"image": "https://your-cdn.com/source.png",
},
)
print(resp.json()["data"][0]["url"])Referências de várias imagens
Alguns modelos (Nano Banana Edit, GPT-Image-2 Edit) aceitam várias imagens de referência.
# nano-banana-edit accepts multiple reference images
resp = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "nano-banana-edit",
"prompt": "merge subject from img1 with background from img2",
"image_urls": [
"https://your-cdn.com/subject.png",
"https://your-cdn.com/background.png",
],
},
)Modelos de edição compatíveis
nano-banana-edit— edição do Google Nano Bananagpt-image-2-edit— conversão de imagem em imagem da OpenAI
Como fornecer uma imagem de origem
A edição de imagens e a conversão de imagem em vídeo precisam de uma imagem de origem que o modelo consiga acessar. Você tem três opções — escolha a que melhor se adapta ao seu aplicativo:
- Você já tem uma URL pública — informe-a diretamente em
image(ou emimage_urlpara vídeo). Pronto. - Você tem um arquivo local — envie-o uma vez por
POST /v1/filese reutilize a URL permanente retornada. - Você tem bytes brutos no código — inclua-os em uma URI base64
data:; a Kunavo os hospeda de forma transparente.
Opção A — enviar por POST /v1/files
Envie multipart/form-data com um campo file (ou um { "file": "data:..." } JSON). Você receberá uma URL files.kunavo.com permanente — arquivos de até 25 MB.
# Upload a local file → get a permanent Kunavo URL
import requests
with open("source.png", "rb") as f:
up = requests.post(
"https://api.kunavo.com/v1/files",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"file": f},
).json()
# up["url"] is now a permanent https://files.kunavo.com/... URL
edit = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "gpt-image-2-edit",
"prompt": "recolor the crane to bright blue",
"image": up["url"],
},
).json()
print(edit["data"][0]["url"])Opção B — incluir em base64
Ignore totalmente o envio separado: inclua uma URI data: no campo image / image_url. A Kunavo a decodifica, hospeda na CDN e fornece ao modelo a URL hospedada.
# Or skip the upload step — pass base64 inline, we host it for you.
import base64, requests
with open("source.png", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
resp = requests.post(
"https://api.kunavo.com/v1/images/edits",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "gpt-image-2-edit",
"prompt": "recolor the crane to bright blue",
"image": f"data:image/png;base64,{b64}",
},
)POST /v1/video/generations — image_url aceita uma URL HTTPS ou uma URI base64 data: para modelos de imagem para vídeo, como Veo.Formato da resposta
Ambos os endpoints retornam a resposta padrão de imagens da OpenAI:
{
"created": 1779360636,
"data": [
{ "url": "https://files.kunavo.com/image/.../result.png" }
]
}Latência e tempos limite
A geração de imagens costuma levar de 5 a 60 segundos, dependendo do modelo. No modo síncrono padrão, a Kunavo mantém a conexão aberta e consulta o provedor upstream por até 540 segundos antes de retornar um erro 504. Ajuste o tempo limite do cliente conforme necessário — ou use a API assíncrona para enviar a solicitação em segundos e consultar o status no seu próprio ritmo:
- Nano Banana/Nano Banana 2: geralmente menos de 10 s.
- Nano Banana Pro/GPT-Image-2: de 15 a 60 s.
- Referências múltiplas + nível premium: até cerca de 2 minutos.
API assíncrona (envio + consulta de status/webhook)
Por padrão, ambos os endpoints de imagem são síncronos — a chamada mantém a conexão aberta até o provedor upstream renderizar a imagem e, em seguida, retorna a resposta padrão de imagens da OpenAI. Para tarefas em lote, níveis premium lentos ou chamadas de ambientes serverless que não podem manter uma solicitação aberta por muito tempo, adicione "async": true (ou um webhook_url) a /v1/images/generations ou /v1/images/edits.
O envio retorna imediatamente um ID img_*; consulte GET /v1/images/{id} até que status seja completed ou failed — ou registre um webhook e dispense totalmente as consultas de status.
# Async: add "async": true (or a webhook_url) to either image endpoint.
# The call returns instantly with an img_ id instead of holding the connection.
import requests, time
API = "https://api.kunavo.com/v1"
H = {"Authorization": f"Bearer {API_KEY}"}
submit = requests.post(
f"{API}/images/generations",
headers=H,
json={"model": "gpt-image-2", "prompt": "a red panda", "async": True},
).json()
task_id = submit["id"] # "img_abc..."
status = submit["status"] # "queued"
# Poll GET /v1/images/{id} until terminal — or skip polling and use a webhook.
while status not in ("completed", "failed"):
time.sleep(3)
r = requests.get(f"{API}/images/{task_id}", headers=H).json()
status = r["status"]
if status == "completed":
print(r["output"]["url"])
else:
print("failed:", r["error"])Objeto da tarefa
| Campo | Tipo | Observações |
|---|---|---|
id | string | ID de tarefa img_* — passe-o para GET /v1/ |
status | string | queued | in_progress | completed | failed. |
output | object|null | Quando concluído: { url, urls, archived }. archived é false quando uma imagem não pôde ser arquivada e a URL dela é a URL temporária do upstream. |
error | object|null | Quando falha: { code, message }. |
expires_at | int|null | Segundos Unix, 30 dias após o envio: a tarefa pode ser consultada pelo menos até lá. As URLs dos resultados não expiram. |
GET /v1/images/{id} é restrito ao proprietário: consultar um ID que não é seu retorna 404, indistinguível de um ID que nunca foi emitido. Cadência recomendada para consultar o status: 3 s, com recuo exponencial até cerca de 30 s.Webhooks
Informe webhook_url (https) no envio, e a Kunavo enviará por POST um evento assinado image.completed / image.failed quando a tarefa terminar — com o mesmo envelope e assinatura dos webhooks de vídeo e música:
X-Kunavo-Webhook-Id— ID de evento estável, idêntico em todas as tentativas de entrega (use-o para eliminar duplicatas).X-Kunavo-Webhook-Timestamp— segundos Unix em que a assinatura foi calculada.X-Kunavo-Webhook-Signature— HMAC-SHA256 de{timestamp}.{rawBody}, assinado comsha256=usando seu segredo de webhook.
Opção de escape para entrada bruta
Para parâmetros específicos de cada modelo que a Kunavo não mapeia (seed, prompt negativo, formato de saída), informe input. Ele é enviado ao provedor upstream exatamente como foi escrito, no lugar da entrada que nosso adaptador criaria.
O campo que seleciona o nível de preço de um modelo é a exceção: resolution, ou rendering_speed no Ideogram. Em modelos com níveis, ele é sempre enviado como um dos níveis do modelo, e a cobrança corresponde a esse nível. Quando input o omite ou fornece um valor que não corresponde a nenhum dos níveis do modelo, o nível padrão é enviado e cobrado. O mesmo campo na raiz da solicitação não é lido quando input está definido.
# Raw upstream 'input': sent as written, in place of what our adapter builds.
# "resolution" sets the billed tier: 2K here, the default tier when left out.
resp = client.images.generate(
model="nano-banana-2",
prompt="", # ignored when input is set
extra_body={"input": {
"prompt": "a futuristic cyberpunk skyline at dusk",
"aspect_ratio": "16:9",
"resolution": "2K",
"output_format": "png",
}},
)input, você ignora a validação da Kunavo. Se o provedor upstream rejeitar seus campos, você receberá um erro 422 nosso — consulte a documentação de erros e a documentação upstream do modelo.