API de generación de imágenes
Genera imágenes GPT Image con la API compatible con OpenAI de BetterToken. Configura API Key, Base URL y parámetros; revisa ejemplos, costes y errores.
POST /v1/images/generations
El endpoint de texto a imagen usa un cuerpo application/json. Envía un prompt, mantén abierta la solicitud HTTP y procesa cada imagen de data[].b64_json en la misma respuesta.
Elige el flujo adecuado
- Generar una imagen desde texto y guardar el resultado: continúa en esta página. Empieza con el ejemplo de
curly decodifica cada elemento dedata[]en Guardar la imagen. - Editar una imagen existente: sube una o varias imágenes de referencia mediante la API de edición de imágenes. La edición normal con referencias no requiere máscara; añádela solo para editar una zona cuando el modelo y el tamaño elegidos lo admitan.
- Elegir un modelo, revisar parámetros y estimar el presupuesto: consulta los Model ID disponibles y los precios actuales en la model plaza. La guía de GPT Image 2 describe el flujo completo.
Inicio rápido con curl
Usa https://bettertoken.ai/v1 como Base URL y envía una solicitud a https://bettertoken.ai/v1/images/generations:
curl --max-time 300 -X POST "https://bettertoken.ai/v1/images/generations" \ -o response.json \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-image-2", "prompt": "A product photo of a green ceramic mug on a studio table", "size": "1024x1024", "n": 1, "response_format": "b64_json", "output_format": "png" }'Valores recomendados
Estos son valores iniciales recomendados, no requisitos fijos. Se recomienda n=1; el endpoint acepta un entero de 1 a 10, pero puede devolver menos imágenes.
{ "model": "gpt-image-2", "n": 1, "response_format": "b64_json", "output_format": "png"}| Parámetro | Valor | Función |
|---|---|---|
model | gpt-image-2, gpt-image-2.5-flare o gpt-image-2.5-sunburst | Elige un Model ID disponible en model plaza. Un ID válido no garantiza que modelo, tamaño u operación estén disponibles para la solicitud. |
prompt | Una descripción de texto | Descripción obligatoria de la imagen. Incluye el sujeto, el estilo, la composición y las restricciones importantes. |
size | Omitirlo, usar auto o indicar dimensiones como 1024x1024 | Solicita tamaño y proporción; las dimensiones entregadas pueden variar. |
n | Entero de 1 a 10 | Máximo solicitado. Se recomienda 1; pueden devolverse menos imágenes. |
quality | auto, low, medium, high para gpt-image-2; los dos modelos 2.5 también aceptan xhigh y max | Preferencia opcional. Omite el campo o usa JSON null para el valor predeterminado. Aceptar el parámetro no garantiza que un nivel superior mejore la calidad. |
response_format | b64_json | Devuelve cada imagen en base64 en data[].b64_json. |
output_format | Por ejemplo, png | Solicita un formato, pero no garantiza la codificación del archivo. Identifica el formato por sus bytes antes de guardarlo. |
La respuesta puede incluir menos imágenes que n. Procesa todos los elementos de data[]; recomendar n=1 no significa que sea un límite del servidor.
Tamaños recomendados
size | Proporción | Uso |
|---|---|---|
auto | Automática | Selección automática del tamaño |
1024x1024 | 1:1 | Imágenes cuadradas, avatares, portadas y recursos |
1536x1024 | 3:2 | Pósteres horizontales, banners y escenas |
1024x1536 | 2:3 | Portadas móviles y pósteres verticales |
1536x1152 | 4:3 | Imágenes horizontales estándar, productos y gráficos de contenido |
1152x1536 | 3:4 | Imágenes verticales estándar, portadas móviles y pósteres verticales |
2048x2048 | 1:1 | Imágenes cuadradas de alta resolución |
2048x1152 | 16:9 | Imágenes horizontales de alta resolución |
3840x2160 | 16:9 | Imágenes horizontales 4K |
2160x3840 | 9:16 | Imágenes verticales 4K |
La tabla contiene ejemplos, no una lista cerrada. Puedes omitir size o usar auto; null en JSON activa el tamaño automático. Las dimensiones explícitas deben ser positivas, múltiplos de 16 y no mayores de 3840; la proporción no puede superar 3:1 y el total debe estar entre 655360 y 8294400 píxeles. 2080x2080 es válido. Comprueba las dimensiones entregadas y no recortes la imagen a la fuerza.
Guarda la imagen
Una respuesta correcta sigue la estructura de imagen compatible con OpenAI. Los importes siguientes ilustran el formato del recibo y no son precios fijos:
{ "created": 1710000000, "data": [ { "b64_json": "iVBORw0KGgoAAAANSUhEUgAA...(truncated)", "revised_prompt": "Optional revised prompt" } ], "bettertoken_image_billing": { "currency": "CNY", "settled_amount": "0.15", "outputs": [ { "index": 0, "width": 1254, "height": 1254, "billing_resolution": "2K", "currency": "CNY", "amount": "0.15" } ] }}Lee todos los data[].b64_json y permite campos adicionales como revised_prompt. BetterToken incluye la facturación en el objeto raíz bettertoken_image_billing: settled_amount y cada amount son cadenas decimales, y outputs[].index empieza en 0. Las dimensiones y billing_resolution del objeto describen el resultado facturado.
output_format solicita un formato, pero no garantiza codificación ni conversión. Inspecciona los bytes y usa la extensión correspondiente. Los ejemplos con bibliotecas estándar detectan PNG, JPEG y WebP sin dependencias adicionales.
import base64import jsonfrom pathlib import Path
result = json.loads(Path("response.json").read_text(encoding="utf-8"))for index, item in enumerate(result["data"], start=1): encoded = item["b64_json"] if "," in encoded and "base64" in encoded.split(",", 1)[0]: encoded = encoded.split(",", 1)[1] image_bytes = base64.b64decode(encoded) if image_bytes.startswith(b"\x89PNG\r\n\x1a\n"): extension = "png" elif image_bytes.startswith(b"\xff\xd8\xff"): extension = "jpg" elif image_bytes.startswith(b"RIFF") and image_bytes[8:12] == b"WEBP": extension = "webp" else: raise ValueError("Unsupported image signature") Path(f"output-{index}.{extension}").write_bytes(image_bytes)Ejemplo con JavaScript (Node.js)
import { writeFile } from "node:fs/promises";
const response = await fetch("https://bettertoken.ai/v1/images/generations", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ model: "gpt-image-2", prompt: "A green ceramic mug on a studio table", size: "1024x1024", n: 1, response_format: "b64_json", output_format: "png", }),});
if (!response.ok) { throw new Error(await response.text());}
const result = await response.json();const { data } = result;for (const [index, item] of data.entries()) { const b64Json = item.b64_json.replace(/^data:.*;base64,/, ""); const imageBytes = Buffer.from(b64Json, "base64"); let extension; if (imageBytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) { extension = "png"; } else if (imageBytes[0] === 0xff && imageBytes[1] === 0xd8 && imageBytes[2] === 0xff) { extension = "jpg"; } else if (imageBytes.toString("ascii", 0, 4) === "RIFF" && imageBytes.toString("ascii", 8, 12) === "WEBP") { extension = "webp"; } else { throw new Error("Unsupported image signature"); } await writeFile(`output-${index + 1}.${extension}`, imageBytes);}Si tu aplicación necesita una codificación fija PNG, JPEG o WebP, identifica primero el formato real y convierte la imagen cuando sea necesario. Cambiar solo la extensión del archivo no convierte la imagen.
Consulta el coste real
bettertoken_image_billing se devuelve con el resultado; no necesitas una consulta aparte.
| Campo | Significado |
|---|---|
currency | Moneda liquidada; no siempre es USD o CNY. |
settled_amount | Importe total de la solicitud como cadena decimal. |
requested_resolution | Nivel de resolución deducido de la solicitud. |
outputs[].index | Índice desde cero correspondiente a data[]. |
outputs[].width, height | Ancho y alto reales en píxeles. |
outputs[].billing_resolution | Nivel final de facturación de la imagen. |
outputs[].currency, amount | Moneda e importe liquidados por imagen. |
El tamaño solicitado y el nivel facturado pueden diferir: una solicitud 1024x1024 ha devuelto 1254x1254 con facturación 2K. Usa el importe del recibo y consulta los precios actuales en el model plaza. Conserva los importes como cadenas para mostrarlos y usa aritmética decimal al calcular. Un recibo ausente no equivale a coste cero.
from decimal import Decimal
billing = result.get("bettertoken_image_billing")if billing is None: print("Billing receipt unavailable; check your usage records.")else: total = Decimal(billing["settled_amount"]) print(f"Total: {billing['currency']} {total}") for output in billing.get("outputs", []): print( f"Image {output['index'] + 1}: " f"{output['width']}x{output['height']}, " f"{output['billing_resolution']}, " f"{output['currency']} {output['amount']}" )Flujo de respuesta
Este endpoint es síncrono. Después de enviar POST /images/generations, mantén abierta la solicitud HTTP hasta recibir respuesta. Si se completa, cada imagen aparece en data[].b64_json con sus datos de entrega y facturación.
El endpoint no devuelve un task_id, y no existe un endpoint separado para consultar el estado o descargar el resultado.
Tiempos de espera, reintentos y facturación
Configura varios minutos de timeout. Un timeout, una desconexión o un 5xx ambiguo no confirma si la generación se ejecutó o se cobró. No repitas automáticamente un POST de generación o edición. Primero consulta los registros de consumo o de solicitudes y conserva cualquier request ID devuelto. Un request ID creado por el cliente no hace idempotente al servidor; un reenvío deliberado puede crear otra solicitud y otro cargo.
Corrige primero los errores de entrada, autenticación o cuota. Reintenta un 429 con backoff solo cuando se confirme el rechazo. No asumas que todos los errores 5xx o de transporte son seguros para repetir.
Antes de procesar la solicitud, BetterToken puede preautorizar un límite igual al mayor precio unitario aplicable multiplicado por n. El saldo puede alcanzar para la imagen 1K entregada y aun así no cubrir esa retención; en ese caso, la solicitud se rechaza con 403 y error.code=insufficient_user_quota. El cargo final se calcula según las imágenes entregadas. El objeto raíz bettertoken_image_billing informa el settled_amount, la divisa y el amount, billing_resolution y las dimensiones de cada resultado. Los importes son cadenas decimales y pueden entregarse menos imágenes que n.
Gestión de errores
Los errores suelen devolver JSON. Al mostrar un error, lee primero error.message, después message y, por último, el texto del estado HTTP.
| Estado HTTP | Significado | Qué hacer |
|---|---|---|
400 | JSON mal formado, parámetro ausente o tamaño no admitido | Comprueba el cuerpo de la solicitud. No reintentes automáticamente. |
401 | Falta la API Key o no es válida | Comprueba la cabecera Authorization: Bearer YOUR_API_KEY. |
402 o 403 | Cuota o saldo insuficientes, incluida una retención | Comprueba error.code y el saldo/cuota. 403 con error.code=insufficient_user_quota indica que el saldo puede ser inferior al límite de preautorización. |
429 | Límite de frecuencia, concurrencia o servicio ocupado | Reintenta con backoff solo tras confirmar el rechazo. |
5xx | Fallo del gateway o del servicio original | La ejecución y el cobro pueden ser desconocidos. Consulta los registros antes de reenviar deliberadamente. |
Lista de integración
- La Base URL es
https://bettertoken.ai/v1. - La cabecera incluye
Authorization: Bearer sk-.... - La solicitud usa
application/json. - Elige un Model ID disponible para esta solicitud:
gpt-image-2,gpt-image-2.5-flareogpt-image-2.5-sunburst. - Usa
response_format=b64_json.output_formates un valor solicitado; identifica el formato real por los bytes antes de guardar. nacepta enteros de1a10. Empieza con1; pueden devolverse menos imágenes.- Omite
size, usaautoo indica dimensiones válidas. La tabla anterior no es una lista cerrada. - El cliente HTTP permite esperar varios minutos a que termine la generación.
- Los registros y las capturas de errores no revelan la API Key ni el contenido base64 completo.
Documentación relacionada
/v1/images/generationsAutorizaciones
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Cuerpo application/json
GPT Image Model ID. One BetterToken API Key works with all available models.
"gpt-image-2"A detailed description of the image to generate.
"A futuristic AI product poster on a light background, with glass textures, a clean composition, and a premium technology aesthetic."Allowed range: 1–10; start with 1. Fewer images may be delivered than requested. Iterate data[] and use actual-delivery billing.
1Omit or use auto for automatic sizing. For WxH, both dimensions must be positive multiples of 16, each at most 3840, aspect ratio at most 3:1, total pixels 655360–8294400. Examples are not an exhaustive enum; 2080x2080 also meets the geometry rules. Inspect actual decoded dimensions. Valid parameters do not guarantee an available service.
"1024x1024"["auto","1024x1024","2048x2048","2080x2080","3840x2160"]Requested output format; png is recommended, but the response is not guaranteed to have been transcoded to PNG. Detect PNG, JPEG, or WebP from actual bytes before choosing an extension. Convert locally if a specific format is required.
"png"gpt-image-2 accepts auto, low, medium, high. The two 2.5 models also accept xhigh and max. Omit for the model default; JSON null is treated as omitted, while multipart requires a nonempty string. Valid values do not guarantee an available service for every model, size, and editing combination. Acceptance does not guarantee that a higher setting improves image quality.
"auto"Respuesta
200BetterToken billing extension. Settlement follows the actual delivered pixels and billing tier, which can differ from the requested tier. Amounts are decimal strings; use the returned values.
OpenAI-compatible image response. Iterate data[] and read each image from b64_json. Fewer images may be delivered than requested.
1710000000Show child attributes
BetterToken billing extension. Settlement follows the actual delivered pixels and billing tier, which can differ from the requested tier. Amounts are decimal strings; use the returned values.
Show child attributes
Settlement currency; do not assume a fixed currency.
Final request amount as a decimal string; use decimal arithmetic for calculations.
Delivered image indices, actual dimensions, billing tiers, and per-image amounts. index is zero-based and corresponds to data[].
Settled amount for this image as a decimal string.
Resolution tier inferred from the request; it may differ from the actual billing tier.
{
"created": 1710000000,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAA...(truncated)",
"revised_prompt": "<string>"
}
],
"bettertoken_image_billing": {
"currency": "<string>",
"settled_amount": "<string>",
"outputs": [
{
"index": 0,
"width": 1,
"height": 1,
"billing_resolution": "1K",
"currency": "<string>",
"amount": "<string>"
}
],
"partial": false,
"requested_resolution": "<string>"
}
}400Invalid request format, missing parameters, malformed JSON or multipart data, or invalid dimensions.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}401The BetterToken API Key is missing or invalid.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}402The account has insufficient credit or balance.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}403Insufficient balance or token quota: error.code is insufficient_user_quota. Funds must also cover the reservation of the highest-tier unit price times the image-count upper bound, before actual-delivery settlement. Inspect error.code rather than treating every 403 as an authorization error.
{
"error": {
"code": "insufficient_user_quota",
"message": "Insufficient balance or token quota."
}
}429A rate or concurrency limit was reached, or the upstream service is busy.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}500The gateway or upstream service returned an error.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}
