Ir al contenido
Regístrate gratis
GPT Image

API de edición de imágenes de GPT Image

Edita referencias GPT Image con la API compatible con OpenAI de BetterToken. Configura multipart y máscaras; guarda resultados y revisa costes y errores.

POST /v1/images/edits

El endpoint de imagen a imagen usa un cuerpo de solicitud multipart/form-data. Sube una o varias imágenes de referencia y envía el prompt y los parámetros como campos de formulario.

Valores recomendados

Son valores iniciales recomendados, no requisitos fijos. Empieza con n=1; el endpoint acepta de 1 a 10, pero puede devolver menos imágenes.

model=gpt-image-2
n=1
response_format=b64_json
output_format=png

Usa image para una sola imagen de referencia. Para varias imágenes, repite image[]. La edición normal con referencias no requiere mask. quality es opcional: gpt-image-2 acepta auto, low, medium, high; los dos modelos 2.5 también aceptan xhigh y max. En multipart debe ser una cadena no vacía. Que se acepte no garantiza disponibilidad para la combinación de modelo, tamaño y edición ni que un nivel superior mejore la calidad. Omítela si no necesitas fijar una preferencia. size también es opcional, pero no puede ser una cadena vacía.

Una imagen de referencia

Prepara reference.png y sustituye YOUR_API_KEY por tu BetterToken API Key. Una clave funciona con todos los modelos disponibles. Deja que curl -F o Python files genere el boundary de Content-Type.

Campo del formularioEjemplo
modelgpt-image-2
promptUsing this reference image, create a more polished square product key visual while preserving the subject style.
n1
size1024x1024
response_formatb64_json
output_formatpng
imageSelecciona el archivo reference.png
Ventana de terminal
curl --max-time 300 'https://bettertoken.ai/v1/images/edits' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-F 'model=gpt-image-2' \
-F 'prompt=Using this reference image, create a more polished square product key visual while preserving the subject style.' \
-F 'n=1' \
-F 'size=1024x1024' \
-F 'response_format=b64_json' \
-F 'output_format=png' \
-F 'image=@reference.png'

Varias imágenes de referencia

Envía estos campos:

Campo del formularioEjemplo
modelgpt-image-2
promptCombine these reference images into a promotional poster with a consistent style.
n1
size1024x1024
response_formatb64_json
output_formatpng
image[]Selecciona reference-1.png
image[]Selecciona reference-2.jpg
image[]Selecciona reference-3.png
Ventana de terminal
curl --max-time 300 'https://bettertoken.ai/v1/images/edits' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-F 'model=gpt-image-2' \
-F 'prompt=Combine these reference images into a promotional poster with a consistent style.' \
-F 'n=1' \
-F 'size=1024x1024' \
-F 'response_format=b64_json' \
-F 'output_format=png' \
-F 'image[]=@reference-1.png' \
-F 'image[]=@reference-2.jpg' \
-F 'image[]=@reference-3.png'

Edita una zona seleccionada con una máscara

Añade el campo de archivo opcional mask cuando quieras orientar la edición a una zona seleccionada. El endpoint actual de BetterToken admite un solo archivo en mask. No envíes campos mask[] repetidos.

  • La imagen original y la máscara deben tener el mismo formato y las mismas dimensiones en píxeles. Cada archivo debe pesar menos de 50 MB. Para obtener la máxima compatibilidad, usa PNG con canal Alpha en ambos archivos.
  • La máscara debe incluir un canal Alpha. Los píxeles totalmente transparentes (Alpha 0) marcan la zona que el modelo puede volver a dibujar. Los píxeles totalmente opacos (Alpha 255) indican al modelo que conserve esa zona.
  • Una imagen RGB normal en blanco y negro no es una máscara válida si no contiene realmente un canal Alpha.
  • Si envías varios campos image[], la máscara se aplica a la primera imagen de entrada.
  • La máscara orienta al modelo. No garantiza que los píxeles fuera de la zona transparente permanezcan exactamente iguales.
  • La disponibilidad de la máscara depende de la combinación de modelo y tamaño. En pruebas con GPT Image 2 y Flare se observaron cambios visibles fuera de la zona objetivo; el control local de Sunburst no se ha verificado. Revisa el resultado antes de usarlo en productos, logotipos o retoques precisos.
Ventana de terminal
curl --max-time 300 'https://bettertoken.ai/v1/images/edits' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-F 'model=gpt-image-2' \
-F 'prompt=Replace only the masked area with a blue circle. Preserve everything else.' \
-F 'n=1' \
-F 'size=1024x1024' \
-F 'response_format=b64_json' \
-F 'output_format=png' \
-F 'image=@original.png' \
-F 'mask=@mask.png'

Edición con máscara en Python

Abre ambos archivos en una sola sentencia with para que Python los cierre después de la solicitud:

import requests
url = "https://bettertoken.ai/v1/images/edits"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
data = {
"model": "gpt-image-2",
"prompt": "Replace only the masked area with a blue circle. Preserve everything else.",
"n": "1",
"size": "1024x1024",
"response_format": "b64_json",
"output_format": "png",
}
with open("original.png", "rb") as image_file, open("mask.png", "rb") as mask_file:
files = {
"image": ("original.png", image_file, "image/png"),
"mask": ("mask.png", mask_file, "image/png"),
}
response = requests.post(url, headers=headers, data=data, files=files, timeout=300)
response.raise_for_status()
result = response.json()

Comprueba los archivos antes de subirlos

Esta comprobación mínima con Pillow verifica los requisitos de formato, dimensiones y canal Alpha. Para una máscara local típica, también muestra una advertencia si el canal Alpha no incluye zonas totalmente transparentes y opacas:

from pathlib import Path
from PIL import Image
image_path = Path("original.png")
mask_path = Path("mask.png")
if image_path.stat().st_size >= 50 * 1024 * 1024 or mask_path.stat().st_size >= 50 * 1024 * 1024:
raise ValueError("Each file must be smaller than 50 MB")
with Image.open(image_path) as image, Image.open(mask_path) as mask:
if image.format != mask.format:
raise ValueError("The image and mask formats must match")
if image.size != mask.size:
raise ValueError("The image and mask dimensions must match")
if "A" not in mask.getbands():
raise ValueError("The mask must contain an Alpha channel")
alpha_min, alpha_max = mask.getchannel("A").getextrema()
if alpha_min > 0 or alpha_max < 255:
print("Warning: for a typical local mask, include fully transparent and fully opaque areas")

Ejemplo con Python

import base64
from pathlib import Path
import requests
url = "https://bettertoken.ai/v1/images/edits"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
}
data = {
"model": "gpt-image-2",
"prompt": "Using this reference image, create a more polished square product key visual while preserving the subject style.",
"n": "1",
"size": "1024x1024",
"response_format": "b64_json",
"output_format": "png",
}
with open("reference.png", "rb") as image_file:
files = {
"image": ("reference.png", image_file, "image/png"),
}
response = requests.post(url, headers=headers, data=data, files=files, timeout=300)
response.raise_for_status()
result = response.json()
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)

Tamaños recomendados

sizeProporciónUso
autoAutomáticaSelección automática del tamaño
1024x10241:1Imágenes cuadradas, avatares, portadas y recursos
1536x10243:2Pósteres horizontales, banners y escenas
1024x15362:3Portadas móviles y pósteres verticales
1536x11524:3Imágenes horizontales estándar, productos y gráficos de contenido
1152x15363:4Imágenes verticales estándar, portadas móviles y pósteres verticales
2048x20481:1Imágenes cuadradas de alta resolución
2048x115216:9Imágenes horizontales de alta resolución
3840x216016:9Imágenes horizontales 4K
2160x38409:16Imágenes verticales 4K

Los valores de la tabla son ejemplos, no una lista cerrada. Puedes omitir size o usar auto; null en JSON también activa la selección automática. Las dimensiones explícitas deben ser positivas y múltiplos de 16, cada una de hasta 3840; la proporción no puede superar 3:1 y el total debe estar entre 655360 y 8294400 píxeles. 2080x2080 también es válido. Las dimensiones entregadas pueden variar; comprueba la imagen y no la recortes 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 cada data[].b64_json y permite campos adicionales como revised_prompt. output_format solicita un formato, pero no garantiza la codificación ni la conversión. Inspecciona los bytes y usa la extensión correspondiente. La página De texto a imagen incluye ejemplos que detectan la firma PNG, JPEG o WebP de cada resultado.

Consulta el coste real

bettertoken_image_billing se devuelve con el resultado; no necesitas una consulta aparte.

CampoSignificado
currencyMoneda liquidada; no siempre es USD o CNY.
settled_amountImporte total de la solicitud como cadena decimal.
requested_resolutionNivel de resolución deducido de la solicitud.
outputs[].indexÍndice desde cero correspondiente a data[].
outputs[].width, heightAncho y alto reales en píxeles.
outputs[].billing_resolutionNivel final de facturación de la imagen.
outputs[].currency, amountMoneda 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/edits, mantén abierta la solicitud HTTP hasta que responda el servidor. Si se completa, todas las imágenes aparecen en data[].b64_json.

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 el timeout del cliente HTTP en varios minutos. Un timeout, una desconexión o un 5xx ambiguo no indica si la edición se ejecutó o se cobró; la conexión puede fallar al escribir el resultado después del cobro. No repitas automáticamente el POST. Revisa primero el consumo o los registros de solicitudes y conserva el request ID recibido y, si existen, las cabeceras X-BetterToken-Image-Receipt y X-BetterToken-Billing-State. Un request ID generado por el cliente no aporta idempotencia y no hay un endpoint de consulta de estado.

Corrige los datos, la autenticación o la cuota rechazados antes de volver a enviar. Reintenta 429 con backoff solo tras confirmar el rechazo. BetterToken puede preautorizar el mayor precio unitario aplicable multiplicado por n; el saldo puede cubrir la imagen 1K entregada y no la retención, que produce 403 con error.code=insufficient_user_quota. El importe final depende de las imágenes entregadas.

Lista de comprobación de integración

  • La Base URL es https://bettertoken.ai/v1.
  • La cabecera incluye Authorization: Bearer sk-....
  • La solicitud usa multipart/form-data.
  • Elige un Model ID disponible para esta solicitud: gpt-image-2, gpt-image-2.5-flare o gpt-image-2.5-sunburst.
  • Usa image para una referencia y campos image[] repetidos para varias.
  • Para editar con máscara, envía una sola mask con el mismo formato y dimensiones que la imagen y con canal Alpha.
  • Usa response_format=b64_json. output_format es un valor solicitado; identifica el formato real por los bytes antes de guardar.
  • n acepta enteros de 1 a 10. Empieza con 1; pueden devolverse menos imágenes.
  • Omite size, usa auto o indica dimensiones que cumplan las restricciones.
  • 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

POST/v1/images/edits

Autorizaciones

Authorizationstringheaderrequerido

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Cuerpo multipart/form-data

modelenum<string>predeterminado: gpt-image-2requerido

GPT Image Model ID. One BetterToken API Key works with all available models.

Opciones disponibles: gpt-image-2, gpt-image-2.5-flare, gpt-image-2.5-sunburst

Ejemplo:"gpt-image-2"
promptstringrequerido

Instructions for editing the image or generating from reference images.

Ejemplo:"Use this reference image to create a more polished square product hero image while preserving the main style."
imagestring<binary>

The reference image field for a single input image.

image[]string[]

Repeat this field for each input when sending multiple reference images.

maskstring<binary>

An optional single mask file. The mask and original image must have the same format and dimensions, each file must be smaller than 50 MB, and the mask must contain an Alpha channel. For maximum compatibility, use PNG with an Alpha channel for both files. With multiple image[] inputs, the mask applies to the first image. Availability depends on the model and size combination. Ordinary reference-image edits do not require a mask. A mask guides generation but does not guarantee that pixels outside the target area remain unchanged; review the result.

ninteger | stringpredeterminado: 1

Allowed range: 1–10; start with 1. Fewer images may be delivered than requested. Iterate data[] and use actual-delivery billing.

Ejemplo:"1"
sizestringpredeterminado: 1024x1024

Omit 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.

Ejemplo:"1024x1024"
Ejemplo: ["auto","1024x1024","2048x2048","2080x2080","3840x2160"]
response_formatenum<string>predeterminado: b64_json

Use b64_json.

Opciones disponibles: b64_json

Ejemplo:"b64_json"
output_formatstringpredeterminado: png

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.

Ejemplo:"png"
qualityenum<string>predeterminado: auto

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.

Opciones disponibles: auto, low, medium, high, xhigh, max

Ejemplo:"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.

createdinteger
Ejemplo:1710000000
dataobject[]
Show child attributes

Base64-encoded image content.

Ejemplo:"iVBORw0KGgoAAAANSUhEUgAA...(truncated)"

An optional revised prompt.

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[].

Rango requerido: x >= 0

Rango requerido: x >= 1

Rango requerido: x >= 1

Opciones disponibles: 1K, 2K, 4K

Settled amount for this image as a decimal string.

Resolution tier inferred from the request; it may differ from the actual billing tier.

Ejemplo
{
  "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.
errorobject
Show child attributes
Ejemplo:"invalid request"
Ejemplo:"invalid_request_error"
Ejemplo:"invalid_request"
messagestring
Ejemplo:"insufficient quota"
Ejemplo
{
  "error": {
    "message": "invalid request",
    "type": "invalid_request_error",
    "code": "invalid_request"
  },
  "message": "insufficient quota"
}
401The BetterToken API Key is missing or invalid.
errorobject
Show child attributes
Ejemplo:"invalid request"
Ejemplo:"invalid_request_error"
Ejemplo:"invalid_request"
messagestring
Ejemplo:"insufficient quota"
Ejemplo
{
  "error": {
    "message": "invalid request",
    "type": "invalid_request_error",
    "code": "invalid_request"
  },
  "message": "insufficient quota"
}
402The account has insufficient credit or balance.
errorobject
Show child attributes
Ejemplo:"invalid request"
Ejemplo:"invalid_request_error"
Ejemplo:"invalid_request"
messagestring
Ejemplo:"insufficient quota"
Ejemplo
{
  "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.
errorobject
Show child attributes
Ejemplo
{
  "error": {
    "code": "insufficient_user_quota",
    "message": "Insufficient balance or token quota."
  }
}
429A rate or concurrency limit was reached, or the upstream service is busy.
errorobject
Show child attributes
Ejemplo:"invalid request"
Ejemplo:"invalid_request_error"
Ejemplo:"invalid_request"
messagestring
Ejemplo:"insufficient quota"
Ejemplo
{
  "error": {
    "message": "invalid request",
    "type": "invalid_request_error",
    "code": "invalid_request"
  },
  "message": "insufficient quota"
}
500The gateway or upstream service returned an error.
errorobject
Show child attributes
Ejemplo:"invalid request"
Ejemplo:"invalid_request_error"
Ejemplo:"invalid_request"
messagestring
Ejemplo:"insufficient quota"
Ejemplo
{
  "error": {
    "message": "invalid request",
    "type": "invalid_request_error",
    "code": "invalid_request"
  },
  "message": "insufficient quota"
}