Aller au contenu
Inscrivez-vous gratuitement
GPT Image

API d’édition d’images GPT Image

Retouchez des références GPT Image via l’API compatible OpenAI de BetterToken. Configurez multipart et masques, enregistrez et vérifiez coûts et erreurs.

POST /v1/images/edits

L’endpoint image à image utilise un corps de Request multipart/form-data. Téléversez une ou plusieurs images de référence et envoyez les champs de prompt et de paramètres sous forme de champs de formulaire.

Valeurs recommandées

Ces valeurs sont recommandées pour commencer, mais ne sont pas obligatoires. Commencez par n=1 ; le point de terminaison accepte de 1 à 10 images, mais peut en renvoyer moins.

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

Utilisez image pour une référence ou répétez image[] pour plusieurs. Une modification ordinaire avec des références ne nécessite pas de mask. quality est facultatif : gpt-image-2 accepte auto, low, medium, high ; les deux modèles 2.5 acceptent aussi xhigh et max. En multipart, la valeur doit être une chaîne non vide. Son acceptation ne garantit ni la disponibilité de la combinaison modèle-taille-édition ni une meilleure qualité à un niveau supérieur. Omettez le champ si vous ne souhaitez pas définir de préférence. size est également facultatif, mais ne peut pas être vide.

Une image de référence

Préparez reference.png et remplacez YOUR_API_KEY par votre BetterToken API Key. Une clé fonctionne avec tous les modèles disponibles. Laissez curl -F ou Python files générer le boundary de Content-Type.

Champ du formulaireExemple
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
imageSélectionnez reference.png
Fenêtre 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'

Plusieurs images de référence

Envoyez ces champs :

Champ du formulaireExemple
modelgpt-image-2
promptCombine these reference images into a promotional poster with a consistent style.
n1
size1024x1024
response_formatb64_json
output_formatpng
image[]Sélectionnez reference-1.png
image[]Sélectionnez reference-2.jpg
image[]Sélectionnez reference-3.png
Fenêtre 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'

Modifier une zone sélectionnée avec un masque

Ajoutez le champ de fichier facultatif mask pour orienter la modification vers une zone sélectionnée. Le point de terminaison BetterToken actuel lit un seul fichier dans mask. N’envoyez pas plusieurs champs mask[].

  • L’image d’origine et le masque doivent utiliser le même format et les mêmes dimensions en pixels. Chaque fichier doit faire moins de 50 MB. Pour une compatibilité maximale, utilisez un PNG avec canal Alpha pour les deux fichiers.
  • Le masque doit contenir un canal Alpha. Les pixels entièrement transparents (Alpha 0) indiquent la zone que le modèle peut redessiner. Les pixels entièrement opaques (Alpha 255) indiquent au modèle de préserver cette zone.
  • Une image RVB ordinaire en noir et blanc n’est pas un masque valide si elle ne contient pas réellement de canal Alpha.
  • Si vous envoyez plusieurs champs image[], le masque s’applique à la première image d’entrée.
  • Le masque guide le modèle. Il ne garantit pas que les pixels situés en dehors de la zone transparente resteront parfaitement identiques.
  • La disponibilité du masque dépend de la combinaison modèle-taille. Des tests avec GPT Image 2 et Flare ont montré des changements visibles hors de la zone cible ; le contrôle local de Sunburst n’a pas été vérifié. Vérifiez le résultat avant de l’utiliser pour des produits, des logos ou une retouche précise.
Fenêtre 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'

Édition avec masque en Python

Ouvrez les deux fichiers dans une seule instruction with afin que Python les ferme après la requête :

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()

Vérifier les fichiers avant l’envoi

Cette vérification minimale avec Pillow contrôle les exigences de format, de dimensions et de canal Alpha. Pour un masque local classique, elle affiche aussi un avertissement si le canal Alpha ne contient pas à la fois des zones entièrement transparentes et opaques :

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")

Exemple 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)

Tailles recommandées

sizeRatioCas d’utilisation
autoAutoSélection automatique de la taille
1024x10241:1Images carrées, avatars, couvertures, ressources
1536x10243:2Affiches, bannières et scènes au format paysage
1024x15362:3Couvertures et affiches mobiles au format portrait
1536x11524:3Images paysage standard, images de produit, illustrations de contenu
1152x15363:4Images portrait standard, couvertures mobiles, affiches verticales
2048x20481:1Images carrées haute résolution
2048x115216:9Images paysage haute résolution
3840x216016:9Images paysage 4K
2160x38409:16Images portrait 4K

Les valeurs du tableau sont des exemples, pas une liste exhaustive. Vous pouvez omettre size ou utiliser auto ; null en JSON déclenche aussi le choix automatique. Les dimensions explicites doivent être positives et multiples de 16, chacune au plus égale à 3840 ; le ratio ne dépasse pas 3:1 et le total est compris entre 655360 et 8294400 pixels. 2080x2080 est valide. Les dimensions livrées peuvent différer : vérifiez l’image et ne la recadrez pas de force.

Enregistrer l’image

Une réponse réussie suit la structure de réponse d’image OpenAI compatible. Les montants ci-dessous illustrent le format du reçu et ne sont pas des prix fixes :

{
"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"
}
]
}
}

Lisez chaque data[].b64_json et acceptez les champs supplémentaires comme revised_prompt. output_format demande un format, sans garantir l’encodage ni une conversion. Inspectez les octets et utilisez l’extension correspondante. La page Texte à image propose des exemples qui détectent la signature PNG, JPEG ou WebP de chaque résultat.

Lire le coût réel

bettertoken_image_billing est renvoyé avec le résultat ; aucune requête séparée n’est nécessaire.

ChampSignification
currencyDevise du règlement, qui n’est pas toujours USD ou CNY.
settled_amountTotal réglé pour la requête, sous forme de chaîne décimale.
requested_resolutionNiveau de résolution déduit de la requête.
outputs[].indexIndex à partir de 0 correspondant à data[].
outputs[].width, heightLargeur et hauteur réelles, en pixels.
outputs[].billing_resolutionNiveau de facturation final de l’image.
outputs[].currency, amountDevise et montant réglés par image.

Les dimensions demandées et le niveau facturé peuvent différer : une requête 1024x1024 a renvoyé 1254x1254 avec une facturation 2K. Utilisez le montant du reçu et consultez les tarifs actuels dans le model plaza. Gardez les montants sous forme de chaînes à l’affichage et utilisez l’arithmétique décimale pour les calculs. Un reçu absent ne vaut pas zéro.

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']}"
)

Flux de réponse

Cet endpoint est synchrone. Après l’envoi de POST /images/edits, gardez la Request HTTP actuelle ouverte jusqu’à la réponse du serveur. En cas de succès, toutes les images sont renvoyées dans data[].b64_json.

L’endpoint ne renvoie pas de task_id, et il n’existe pas d’endpoint distinct de requête de statut ou de téléchargement de résultat.

Délais d’attente, nouvelles tentatives et facturation

Réglez le délai d’attente du client HTTP sur plusieurs minutes. Un délai dépassé, une déconnexion ou un 5xx ambigu ne permet pas de savoir si l’édition a été exécutée ou facturée ; la connexion peut échouer pendant l’écriture du résultat après le règlement. Ne renvoyez pas automatiquement le POST. Vérifiez d’abord la consommation ou les journaux et conservez le request ID reçu ainsi que, s’ils sont présents, les en-têtes X-BetterToken-Image-Receipt et X-BetterToken-Billing-State. Un request ID généré par le client ne rend pas la requête idempotente et aucun endpoint de statut n’existe.

Corrigez les données, l’authentification ou le quota refusés avant un nouvel envoi. Ne réessayez 429 avec backoff qu’après avoir confirmé le rejet. BetterToken peut préautoriser le prix unitaire applicable le plus élevé multiplié par n ; le solde peut couvrir l’image 1K livrée sans couvrir cette retenue, ce qui entraîne 403 et error.code=insufficient_user_quota. Le montant final dépend des images livrées.

Liste de vérification de l’intégration

  • La Base URL est https://bettertoken.ai/v1.
  • L’en-tête contient Authorization: Bearer sk-....
  • La requête utilise multipart/form-data.
  • Choisissez un Model ID disponible pour cette requête : gpt-image-2, gpt-image-2.5-flare ou gpt-image-2.5-sunburst.
  • Utilisez image pour une référence et répétez les champs image[] pour plusieurs références.
  • Pour une retouche masquée, envoyez un seul mask avec le même format et les mêmes dimensions que la source et un canal Alpha.
  • Utilisez response_format=b64_json. output_format est une valeur demandée ; identifiez le format réel par les octets avant l’enregistrement.
  • n accepte des entiers de 1 à 10. Commencez par 1 ; moins d’images peuvent être renvoyées.
  • Omettez size, utilisez auto ou indiquez des dimensions conformes aux contraintes.
  • Le client HTTP autorise plusieurs minutes d’attente pour la génération.
  • Les journaux et captures d’erreurs ne révèlent pas la clé API ni le contenu base64 complet de l’image.

Documents associés

POST/v1/images/edits

Autorisations

Authorizationstringheaderrequis

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

Corps multipart/form-data

modelenum<string>défaut: gpt-image-2requis

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

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

Exemple:"gpt-image-2"
promptstringrequis

Instructions for editing the image or generating from reference images.

Exemple:"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 | stringdéfaut: 1

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

Exemple:"1"
sizestringdéfaut: 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.

Exemple:"1024x1024"
Exemple: ["auto","1024x1024","2048x2048","2080x2080","3840x2160"]
response_formatenum<string>défaut: b64_json

Use b64_json.

Options disponibles: b64_json

Exemple:"b64_json"
output_formatstringdéfaut: 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.

Exemple:"png"
qualityenum<string>défaut: 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.

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

Exemple:"auto"

Réponse

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
Exemple:1710000000
dataobject[]
Show child attributes

Base64-encoded image content.

Exemple:"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[].

Plage requise: x >= 0

Plage requise: x >= 1

Plage requise: x >= 1

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

Exemple
{
  "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
Exemple:"invalid request"
Exemple:"invalid_request_error"
Exemple:"invalid_request"
messagestring
Exemple:"insufficient quota"
Exemple
{
  "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
Exemple:"invalid request"
Exemple:"invalid_request_error"
Exemple:"invalid_request"
messagestring
Exemple:"insufficient quota"
Exemple
{
  "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
Exemple:"invalid request"
Exemple:"invalid_request_error"
Exemple:"invalid_request"
messagestring
Exemple:"insufficient quota"
Exemple
{
  "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
Exemple
{
  "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
Exemple:"invalid request"
Exemple:"invalid_request_error"
Exemple:"invalid_request"
messagestring
Exemple:"insufficient quota"
Exemple
{
  "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
Exemple:"invalid request"
Exemple:"invalid_request_error"
Exemple:"invalid_request"
messagestring
Exemple:"insufficient quota"
Exemple
{
  "error": {
    "message": "invalid request",
    "type": "invalid_request_error",
    "code": "invalid_request"
  },
  "message": "insufficient quota"
}