Referencia de la API

Imagen

Genera una imagen a partir de un prompt, o edita imágenes existentes con hasta cuatro referencias.

POST/v1/images/generations

Dos rutas sobre el mismo modelo: una parte solo de un prompt, la otra parte de imágenes que tú envías. Ambas devuelven la imagen en base64 en el cuerpo de la respuesta.

POST/v1/images/generations
POST/v1/images/edits

Generación

application/json. Entra un prompt, sale un PNG.

curl -X POST "https://api.trystac.com/v1/images/generations" \
  -H "Authorization: Bearer $STAC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "a white dress shirt folded on a wooden table",
    "size": "1024x1024",
    "seed": 42
  }'

Esta ruta no acepta imagen de entrada. Enviar una devuelve 400 wrong_route_for_reference_image — usa /v1/images/edits.

Edición

multipart/form-data. De una a cuatro imágenes de referencia, más un prompt que describa el cambio.

curl -X POST "https://api.trystac.com/v1/images/edits" \
  -H "Authorization: Bearer $STAC_API_KEY" \
  -F "prompt=make it black and white" \
  -F "size=1024x1024" \
  -F "image[]=@photo.png"

El campo de archivo acepta tanto image como image[] — el segundo es el que usan los propios ejemplos de OpenAI para múltiples archivos. Hasta 4 imágenes, de 5 MiB cada una, en PNG, JPEG o WEBP. El formato se lee del contenido del archivo, no de su extensión ni del Content-Type de la parte. El cuerpo multipart completo tiene un tope de 21 MiB.

Las imágenes de referencia se convierten a RGB al llegar, lo que descarta el canal alfa, los perfiles de color y los metadatos EXIF — incluido cualquier dato de ubicación que llevara el archivo original.

mask no está soportado y devuelve 400. El pod carga un único pipeline, y aplicar la edición a la imagen completa fingiendo respetar la máscara sería peor que rechazarla.

Parámetros

Los mismos campos en ambas rutas — como JSON en /generations, como campos de formulario en /edits.

promptstringObligatorio

Qué generar, o qué cambiar en las imágenes que enviaste. Puede omitirse si tu clave tiene un prompt configurado — ver Prompt en la clave. Lee Longitud del prompt antes de escribir uno largo.

sizestringOpcionalPredeterminado: 1024x1024

Dimensiones de salida — cuadrada, horizontal o vertical. Es una lista cerrada; cualquier otro valor devuelve 400.

1024x10241536x10241024x1536
stepsintegerOpcionalPredeterminado: 4

Pasos de difusión, de 1 a 8. El checkpoint es destilado, así que está afinado para producir una imagen terminada en muy pocos pasos — por eso el tope es 8 y no 50.

guidance_scalenumberOpcionalPredeterminado: 1.0

Con qué rigor seguir el prompt, de 0 a 20.

seedintegerOpcional

De 0 a 2^64−1. Si la omites, el servidor sortea una y la devuelve en meta.seed — ese valor es el que reproduce la misma imagen después.

nintegerOpcionalPredeterminado: 1

Imágenes por petición. Hoy 1 es el único valor aceptado.

response_formatstringOpcionalPredeterminado: b64_json

Solo b64_json. url se rechaza — la imagen viene en el cuerpo de la respuesta.

Respuesta

Idéntica en ambas rutas.

200 OKjson
{
  "created": 1767225600,
  "data": [{ "b64_json": "iVBORw0KGgo..." }],
  "meta": {
    "prompt": "a white dress shirt folded on a wooden table",
    "width": 1024,
    "height": 1024,
    "steps": 4,
    "guidance_scale": 1.0,
    "seed": 8151234567890123456,
    "n": 1,
    "model": "flux2-klein-4b",
    "timings": {
      "queue_wait_s": 0.0100,
      "decode_s": null,
      "gpu_s": 4.1000,
      "encode_s": 0.1800,
      "worker_s": 4.2800
    }
  }
}

meta trae los parámetros efectivos — lo que el servidor usó de verdad, después de los valores por defecto y después de sortear una seed, si no enviaste ninguna.

data[].b64_jsonstringOpcional

El PNG, codificado en base64.

meta.seedintegerOpcional

La seed que produjo este resultado. Es del lote, no de cada imagen: reproducir la imagen i exige la misma seed y el mismo n.

meta.timingsobjectOpcional

A dónde se fue el tiempo, en segundos, con cuatro decimales. queue_wait_s es la espera por un espacio libre; decode_s es la lectura de tus imágenes de referencia (null en /generations, que no tiene ninguna); gpu_s es la difusión en sí; encode_s es la producción del PNG. worker_s es la suma de los tres últimos y no incluye la espera en la cola.

Longitud del prompt

Esta es la causa más común de "la imagen ignoró la mitad de lo que pedí". Un prompt largo y detallado no solo se desperdicia después del corte, sino que además diluye la parte que sí cabe. Empieza por el sujeto y por los detalles que más importan.

Prompt en la clave

El prompt puede vivir en tu clave de API, como el system prompt en las rutas de texto — y vale la misma precedencia.

En el cuerpo de la peticiónEn la claveLo que recibe el modelo
prompt con textocualquier cosael de la petición
ausente o en blancoconfiguradoel de la clave
ausente o en blanconada400 missing_prompt

Es lo que permite enviar solo la URL, la clave y la imagen:

curl -X POST "https://api.trystac.com/v1/images/edits" \
  -H "Authorization: Bearer $STAC_API_KEY" \
  -F "image[]=@photo.png"

Rendimiento

La generación de imágenes no tiene cuota diaria — la difusión no produce tokens, así que el presupuesto de tokens que aplica a las rutas de chat no aplica aquí. Lo que limita es la GPU, que renderiza una imagen a la vez.

LímiteQué significa
Envíos10 por minutoCompartido entre generations y edits
En vuelo3 a la vez1 renderizando y hasta 2 esperando
Espera en cola60 segundosPasado eso la petición devuelve 504

Ambos límites son del stack, no de la clave. Emitir más claves no los sube, porque es la misma GPU la que hace el trabajo de todos modos.

Observado de extremo a extremo: alrededor de 6–9s para texto → imagen y 7–21s para una edición, variando con la cantidad, las dimensiones y el peso de las imágenes de referencia. "10 por minuto" es un tope de envío, no una promesa de diez imágenes terminadas por minuto.

Almacenamiento y retención

Cada imagen generada se almacena, vinculada a la cuenta, al stack y a la clave que la creó. Esto ocurre en el servidor y no cambia nada en tu código — la respuesta sigue siendo b64_json.

Dos consecuencias que vale la pena conocer:

  • Un 200 significa que la imagen fue almacenada. La escritura ocurre antes de que salga la respuesta y añade unos cientos de milisegundos a una llamada que ya tarda segundos.
  • Un 502 puede ocurrir con la imagen ya generada. Si el almacenamiento falla, devolvemos el error en lugar de entregarte la imagen afirmando que quedó guardada. Reintentar es seguro — pero ten en cuenta que genera de nuevo, con una seed nueva si no fijaste ninguna.

Los archivos se conservan 30 días. Si necesitas una imagen por más tiempo, guarda el b64_json de tu lado: este almacenamiento existe para trazabilidad y para verla en la plataforma, no como alojamiento permanente.

Errores

Dos formatos de error te llegan en estas rutas. Los rechazos del propio gateway usan el formato { "detail": "..." } común a toda la API; lo que rechaza el servidor de imágenes vuelve en el formato de OpenAI, con un code estable sobre el que sí puedes ramificar:

400 Bad Requestjson
{
  "error": {
    "message": "size must be one of: 1024x1024, 1536x1024, 1024x1536",
    "type": "invalid_request_error",
    "code": "invalid_size"
  }
}
StatuscodeSignificado
400invalid_size, invalid_steps, invalid_n, invalid_guidance_scale, invalid_seedCampo fuera del rango aceptado, o con el tipo equivocado
400missing_promptprompt ausente o vacío, y sin prompt configurado en la clave
400mask_not_supportedmask no está soportado en esta versión
400wrong_route_for_reference_imageEnviaste una imagen a /generations — usa /edits
400missing_image/edits llamado sin archivo
400too_many_reference_imagesMás de 4 referencias
400unsupported_image_formatUna referencia no es PNG, JPEG ni WEBP
403La clave no es de un stack del plan image
404model_not_foundmodel distinto del modelo servido (solo en /edits)
413image_too_largeReferencia por encima de 5 MiB, o cuerpo por encima del tope de la ruta
429queue_fullYa hay 3 en vuelo — respeta el Retry-After
429Por encima de 10 envíos por minuto — respeta el Retry-After
502La imagen se generó, pero no se pudo almacenar
503model_not_readyInfraestructura aún arrancando, o degradada
504queue_timeoutEsperó más de 60s por un espacio libre

Reintenta 429, 503 y 504 tras el tiempo indicado en Retry-After. Un 502 también merece un intento, teniendo en cuenta que renderiza de nuevo desde cero.