# Nano Banana 2.1 — /images/generations

Generación de imágenes (asíncrona, por trabajos) con Google Nano Banana 2.1, la versión mejorada de Nano Banana 2 lanzada en octubre de 2026. Para texto a imagen basta el prompt; para editar, pon las referencias en image o images (URL, data: URI o base64) o llama a /v1/images/edits. Al enviar recibes al instante un id de trabajo (HTTP 202); consulta GET /v1/images/jobs/{id} para obtener la imagen. Proporciones como 1:1, 3:4, 2:3, 9:16, 4:3, 3:2 y 16:9 en 1K / 2K / 4K, y también formatos anchos 4:1, 1:4, 8:1 y 1:8. Se cobra por imagen; las solicitudes fallidas no se cobran.

**Endpoint:** `POST https://nezhagate.com/v1/images/generations`

## Inicio rápido

Tres pasos: enviar el trabajo, consultarlo y quedarte con el enlace de la imagen. Sustituye YOUR_API_KEY por tu clave y los comandos de abajo funcionan tal cual.

Paso 1 · Enviar (devuelve un id de trabajo al instante, HTTP 202)

```bash
curl https://nezhagate.com/v1/images/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "nano-banana-2.1", "prompt": "An orange cat on a windowsill watching the rain, warm desk lamp, cinematic, shallow depth of field", "size": "16:9", "resolution": "2K"}'
```

Respuesta (HTTP 202)

```json
{
  "id": "img_7f3c9a1e2b4d6f8a0c1e3b5d",
  "object": "image.generation.job",
  "status": "queued",
  "created": 1791281500,
  "model": "nano-banana-2.1"
}
```

Paso 2 · Consulta cada 2-3 segundos hasta que status sea succeeded o failed

```bash
curl https://nezhagate.com/v1/images/jobs/img_7f3c9a1e2b4d6f8a0c1e3b5d \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Respuesta cuando termina bien

```json
{
  "id": "img_7f3c9a1e2b4d6f8a0c1e3b5d",
  "object": "image.generation.job",
  "status": "succeeded",
  "created": 1791281500,
  "model": "nano-banana-2.1",
  "data": [
    {"url": "https://img.nezhagate.com/i/2be8cd16d37f3a4b9c0e1f2a3b4c5d6e.png"}
  ],
  "usage": {"images": 1, "resolution": "2K", "model": "nano-banana-2.1"}
}
```

Paso 3 · data[0].url es la imagen (PNG). Se guarda 60 días; descárgala a tu propio almacenamiento si la necesitas más tiempo.

### Ejemplo completo (Python: enviar, esperar y guardar en disco)

```python
import time
import requests

BASE = "https://nezhagate.com/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

# 1. enviar
job = requests.post(f"{BASE}/images/generations", headers=HEADERS, json={
    "model": "nano-banana-2.1",
    "prompt": "An orange cat on a windowsill watching the rain, warm desk lamp, cinematic, shallow depth of field",
    "size": "16:9",
    "resolution": "2K",
}).json()
if "error" in job:
    raise SystemExit(job["error"]["message"])

# 2. consultar cada 3 segundos hasta que termine
while job["status"] not in ("succeeded", "failed"):
    time.sleep(3)
    job = requests.get(f"{BASE}/images/jobs/{job['id']}", headers=HEADERS).json()

# 3. descargar la imagen
if job["status"] == "succeeded":
    url = job["data"][0]["url"]
    with open("nano-banana-2.1.png", "wb") as f:
        f.write(requests.get(url).content)
    print("saved", url)
else:
    print("failed:", job["error"]["message"])
```

## Autenticación
```
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

## Cuerpo de la petición
| Parámetro | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `model` | string | Sí | ID del modelo; aquí nano-banana-2.1. |
| `prompt` | string | Sí | Prompt de texto que describe la imagen. |
| `size` | string | No | Relación de aspecto de salida. Recomendado: pasa una relación (1:1, 3:4, 2:3, 9:16, 4:3, 3:2, 16:9) y el modelo renderiza de forma nativa con esa proporción, sin recortar el sujeto. También se aceptan tamaños en píxeles (p. ej. 1024x1024, 1024x1536, 1536x1024). Por defecto 1:1 (cuadrada). |
| `resolution` | string | No | Nivel de resolución: 1K (por defecto) / 2K / 4K, con cobro según el nivel. Úsalo con una proporción en size, p. ej. {"size": "16:9", "resolution": "2K"}; los píxeles exactos de cada nivel están en «Proporción, resolución y tamaño de salida», más abajo. Si size es un tamaño en píxeles (p. ej. 2048x1152), el nivel lo decide su lado más largo. |
| `n` | integer | No | Siempre 1: cada trabajo devuelve una imagen. Un valor mayor sigue devolviendo una imagen y cobrando una; para varias imágenes envía varios trabajos a la vez. |
| `image` | string | No | Imagen a imagen: una imagen de referencia como URL pública, data: URI o base64 en bruto. Si está presente, la petición ejecuta una verdadera transformación imagen a imagen que preserva la identidad en el tamaño y la proporción elegidos, equivalente a llamar a /v1/images/edits. |
| `images` | array | No | Varias imágenes de referencia, hasta 8 (si mandas más, solo se usan las 8 primeras): un array de cadenas o de objetos {"image_url": "..."}; cada una es una URL pública, un data: URI o base64, de hasta 16 MB. Enviarlas activa imagen a imagen, igual que /v1/images/edits. Para una sola referencia también sirve el campo image de arriba. |

## Ejemplo de petición
```bash
# 1) submit -> 202 {"id":"img_...","status":"queued"}
curl https://nezhagate.com/v1/images/generations -H 'Authorization: Bearer YOUR_API_KEY' -H 'Content-Type: application/json' -d '{"model": "nano-banana-2.1", "prompt": "a serene ink-wash poster, lots of negative space", "size": "16:9", "resolution": "2K"}'
# 2) poll until status=succeeded
curl https://nezhagate.com/v1/images/jobs/img_3f9a...c2 -H 'Authorization: Bearer YOUR_API_KEY'
```

## Respuesta
```json
{
  "id": "img_3f9a...c2",
  "object": "image.generation.job",
  "status": "queued",
  "model": "nano-banana-2.1"
}
```

## Precio

Se cobra por imagen y el precio depende solo del nivel de resolución: la proporción y si es texto a imagen o imagen a imagen no cambian nada. Al enviar se retiene el precio del nivel y, si el trabajo falla, se reembolsa por completo. 1 crédito = $0.005.

| Nivel | Créditos por imagen | USD por imagen |
| --- | --- | --- |
| 1K | 3 | $0.015 |
| 2K | 5 | $0.025 |
| 4K | 8 | $0.04 |

Cada trabajo devuelve exactamente una imagen: envíes el n que envíes, recibes una imagen y pagas una. Para varias imágenes, envía varios trabajos a la vez (una cuenta genera hasta 50 al mismo tiempo).

## Proporción, resolución y tamaño de salida

Pon la proporción en size y el nivel en resolution (1K por defecto, 2K o 4K). El modelo dibuja directamente en la proporción elegida; no dibuja un cuadrado para recortarlo después. La imagen entregada tiene un lado largo de 1024 / 2048 / 4096 píxeles y el otro sigue la proporción. Proporciones habituales:

| Proporción | 1K | 2K | 4K |
| --- | --- | --- | --- |
| 1:1 | 1024x1024 | 2048x2048 | 4096x4096 |
| 3:4 | 768x1024 | 1536x2048 | 3072x4096 |
| 2:3 | 683x1024 | 1365x2048 | 2731x4096 |
| 9:16 | 576x1024 | 1152x2048 | 2304x4096 |
| 4:3 | 1024x768 | 2048x1536 | 4096x3072 |
| 3:2 | 1024x683 | 2048x1365 | 4096x2731 |
| 16:9 | 1024x576 | 2048x1152 | 4096x2304 |

Además de estas siete, 4:5, 5:4, 21:9, 1:4, 4:1, 1:8 y 8:1 también se dibujan de forma nativa (con la misma regla del lado largo). Cualquier otra proporción se dibuja en la forma horizontal, vertical o cuadrada más cercana y luego se recorta a la tuya, lo que puede cortar parte de la imagen.

size también puede ser un tamaño en píxeles (p. ej. 1536x1024): la imagen se entrega exactamente con ese tamaño y el nivel lo decide el lado más largo: hasta 1536 es 1K, hasta 2048 es 2K y por encima es 4K. resolution solo acepta 1K / 2K / 4K (en mayúsculas o minúsculas); cualquier otro valor se ignora y el nivel sale de size, 1K por defecto. Sin size obtienes un cuadrado 1:1.

## Imagen a imagen e imágenes de referencia

- Envía image (una imagen) o images (varias, hasta 8; si mandas más, solo se usan las 8 primeras) y el trabajo pasa a ser imagen a imagen; explica en el prompt qué quieres cambiar. POST /v1/images/edits admite los mismos parámetros.
- Cada referencia puede ser una URL pública de imagen (http o https), un data: URI o base64 sin más, de hasta 16 MB cada una, en un formato común como JPEG, PNG o WebP.
- La URL tiene que descargar la imagen en sí: no una página web, ni una dirección que pida iniciar sesión o bloquee el hotlinking. Una referencia que no podemos leer se rechaza al enviar con un 400 y el motivo; no se crea ningún trabajo ni se cobra nada.
- La proporción de salida la decide size, no la referencia. Para mantener la proporción original, pon en size la de la imagen.
- Alojamos las referencias por ti y las guardamos 7 días.

**Imagen a imagen con dos referencias**

```bash
curl https://nezhagate.com/v1/images/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "nano-banana-2.1", "prompt": "Keep the people, change the background to a beach at night with warm string lights", "images": ["https://example.com/people.jpg", "https://example.com/beach.jpg"], "size": "3:4", "resolution": "2K"}'
```

## Estado del trabajo y campos

GET /v1/images/jobs/{id} siempre devuelve id, object (image.generation.job), status, created (segundos Unix) y model; los demás campos dependen del estado:

| status | Significado | Campos adicionales |
| --- | --- | --- |
| `queued` | En cola | queue_position (trabajos por delante del tuyo), eta_seconds (espera estimada en segundos, orientativa) |
| `processing` | Generando | — |
| `succeeded` | Listo | data[].url (el enlace de la imagen; nuestro alojamiento la guarda 60 días); usage.images (imágenes entregadas), usage.resolution (nivel cobrado) |
| `failed` | Fallido; el importe retenido al enviar se ha reembolsado por completo | error.message, error.type, error.code |

Consulta cada 2-3 segundos. Una cuenta genera hasta 50 imágenes a la vez; los demás trabajos esperan en orden de envío, y un trabajo que no ha empezado a los 15 minutos falla y se reembolsa por completo. Los registros de los trabajos se guardan 3 días; después, el id devuelve 404, pero el enlace de la imagen sigue siendo válido durante sus 60 días. Solo la cuenta que envió un trabajo puede consultarlo.

## Cuánto tarda

Tiempo habitual desde el envío hasta el resultado, como referencia. Imagen a imagen tarda de unos segundos a una docena más; un trabajo que la pasarela repite en otra línea puede tardar 1-2 minutos.

| Nivel | Tiempo habitual |
| --- | --- |
| 1K | 25–40 s |
| 2K | 25–50 s |
| 4K | 35–80 s |

## Errores y reembolsos

Todos los errores tienen la misma forma, {"error": {"message", "type", "code", "param"}}; decide según code.

### Errores devueltos al enviar (no se crea ningún trabajo ni se cobra nada)

| HTTP | code | Causa | Qué hacer |
| --- | --- | --- | --- |
| 400 | `missing_prompt` | prompt está vacío | Añade un prompt |
| 400 | `model_not_found` | El id del modelo es incorrecto o no está disponible ahora | Revisa el id; /v1/models lista los disponibles |
| 400 | `invalid_request` | No se puede leer una imagen de referencia (enlace roto, no es una imagen, más de 16 MB...); message dice cuál y por qué | Usa un enlace directo a la imagen o envíala en base64 |
| 401 | `invalid_api_key` | La clave es incorrecta, se ha borrado o está desactivada | Revisa la clave en la consola |
| 402 | `insufficient_quota` | No hay saldo suficiente para retener este trabajo | Recarga y vuelve a intentarlo |
| 429 | `rate_limit_exceeded` | Se superó el límite por minuto fijado en esta clave | Reduce la frecuencia o sube el límite de la clave en la consola |
| 503 | `model_maintenance` | El modelo está en mantenimiento | Inténtalo más tarde; consulta la página de estado |
| 503 | `service_unavailable` | Un error temporal de nuestro lado (p. ej. al guardar tu referencia) | Vuelve a intentarlo en un momento |

### Trabajos fallidos (el trabajo se aceptó y terminó con status failed; la retención se reembolsa por completo)

| Situación | Qué verás | Qué hacer |
| --- | --- | --- |
| El prompt o una referencia no pasó la revisión de seguridad de Google | error.message como Content blocked | Reescribe el prompt o cambia la referencia; reenviarlo sin cambios suele volver a rechazarse |
| Una línea de generación falló o agotó el tiempo (antes reintentamos en otras líneas y solo devolvemos el fallo si fallan todas) | error.code como upstream_error o upstream_timeout, con el motivo en message | Vuelve a enviarlo |
| El trabajo esperó 15 minutos sin empezar | error.message lo indica | Vuelve a enviarlo más tarde |

## Usa un webhook en lugar de consultar

En producción, añade callback_url al enviar. Cuando el trabajo termine, bien o mal, enviaremos por POST a esa URL el mismo JSON que devuelve la consulta, como image.completed o image.failed, con cabeceras de firma que puedes verificar. También puedes fijar una URL para toda la cuenta en Ajustes > Webhook. [Documentación de webhooks](https://nezhagate.com/es/docs/webhooks)

```bash
curl https://nezhagate.com/v1/images/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "nano-banana-2.1", "prompt": "An orange cat on a windowsill watching the rain, warm desk lamp, cinematic, shallow depth of field", "size": "1:1", "callback_url": "https://your-domain.com/webhook"}'
```