> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bettertoken.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Comment utiliser 1K, 2K, 4K, Quality et Mask avec GPT Image : guide de tests BetterToken

> Guide fondé sur des tests réels de génération GPT Image : dimensions livrées, qualité, retouche par masque, routage, limites observées et tarifs BetterToken.

export const GptImageComparison = ({kind, labels, caption, label}) => {
  const comparisonPanels = {
    crops: [["comparison-crop-1k.png", 480, 480], ["comparison-crop-2k.png", 480, 480], ["comparison-crop-4k.png", 480, 480]],
    mask: [["comparison-mask-original.png", 476, 476], ["comparison-mask-overlay.png", 476, 476], ["comparison-mask-result.png", 476, 476]],
    boundary: [["comparison-boundary-original.png", 576, 256], ["comparison-boundary-result.png", 576, 256]],
    circles: [["comparison-circles-original.png", 416, 416], ["comparison-circles-overlay.png", 416, 416], ["comparison-circles-result.png", 416, 416]]
  };
  const panels = comparisonPanels[kind];
  return <div className="bt-image-comparison not-prose">
      <div className="bt-image-comparison-scroll" role="region" aria-label={label} tabIndex={0}>
        <div className="bt-image-comparison-grid" style={{
    gridTemplateColumns: `repeat(${panels.length}, minmax(0, 1fr))`,
    '--bt-comparison-min-width': `${panels.length * 176 + (panels.length - 1) * 16}px`
  }}>
          {labels.map((title, index) => <p className="bt-image-comparison-title" key={`title-${index}`}>{title}</p>)}
          {panels.map(([file, width, height], index) => <a key={file} href={`/images/gpt-image-guide/${file}`} target="_blank" rel="noreferrer">
              <img src={`/images/gpt-image-guide/${file}`} alt={labels[index]} width={width} height={height} loading="lazy" style={{
    borderRadius: '0.5rem'
  }} />
            </a>)}
        </div>
      </div>
      <p className="bt-image-comparison-caption">{caption}</p>
    </div>;
};

Lors de la génération d’images de produits, de créations publicitaires ou de maquettes avec `gpt-image-2`, `gpt-image-2.5-flare` et `gpt-image-2.5-sunburst`, les développeurs rencontrent souvent plusieurs questions épineuses :

* **Pourquoi les résultats diffèrent-ils d’un appel à l’autre avec le même modèle et les mêmes paramètres ?**
* **Pourquoi l’image reçue est-elle réduite à 1K alors que j’ai demandé 4K ou une dimension précise ?**
* **La retouche locale avec `Mask` ou `quality=high` a-t-elle réellement fonctionné ? Selon quel critère la facturation finale est-elle calculée ?**

Pour les appels API du quotidien, vérifier uniquement le code d’état HTTP `200 OK` est loin de suffire : trois conditions doivent être réunies en même temps : **obtenir une image, pouvoir l’utiliser dans la mise en page prévue et disposer de coûts transparents et prévisibles**.

Pour aider les développeurs à comprendre le comportement réel de ces trois modèles, BetterToken a mis en place au niveau inférieur **un routage intelligent selon les capacités, le nettoyage des paramètres par défaut, le blocage préalable des paramètres invalides et une facturation transparente fondée sur les pixels réellement livrés**. Ce guide s’appuie sur les résultats des tests les plus récents et sur un instantané des tarifs du 19 octobre 2026. À partir d’images originales générées et de factures réelles, il montre comment effectuer les appels, quels résultats obtenir et quelles limites objectives subsistent pour les modèles eux-mêmes.

> **Remarque** : ce guide porte sur `gpt-image-2`, `gpt-image-2.5-flare` et `gpt-image-2.5-sunburst`. Les paramètres et la facturation de la série Nano Banana sont différents ; ils feront l’objet d’un autre article afin d’éviter toute confusion.

## 1. Pourquoi les résultats peuvent-ils varier avec le même modèle et les mêmes paramètres ?

En pratique, les différents nœuds de service derrière un même nom de modèle présentent souvent des capacités et une stabilité différentes : certaines routes ne prennent en charge que la génération de base en 1K, tandis que d’autres livrent des images haute définition en `2048×2048` ou même en `3840×2160`. La prise en charge des valeurs de `quality`, de la retouche à partir d’une image de référence et des masques `Mask` varie également selon les nœuds.

Si la plateforme se contente de transférer aveuglément les requêtes selon le nom du modèle, les développeurs rencontrent souvent des situations comme « j’ai demandé 4K, mais j’ai reçu une petite image 1K », « j’ai envoyé une Mask et l’appel a échoué » ou « je dois ajuster les paramètres encore et encore ». C’est pourquoi il faut un protocole de test rigoureux qui vérifie séparément l’acceptation des paramètres par l’interface et le résultat réellement livré.

## 2. Notre méthode de test : que signifie « pris en charge » ?

Pour garantir des conclusions objectives et fiables, nous avons conçu **22 scénarios de test standard** pour la régression de la version stable (17 requêtes valides ont livré 18 images ; les 5 scénarios comportant des paramètres invalides ont été bloqués comme prévu et n’ont pas été facturés). Nous avons également généré des images de produits et des exemples d’édition avec Mask pour des usages fréquents du commerce en ligne.

Nos critères de vérification sont directs :

1. **Décoder les pixels du fichier original** : nous ne nous fions pas à la seule déclaration de l’API. Nous décodons les dimensions de chaque image livrée à partir du fichier d’origine, puis nous les comparons au niveau de facturation indiqué dans la réponse et au débit réel du compte.
2. **Vérifier que les dimensions sont atteintes** : nous comparons séparément la largeur et la hauteur explicitement demandées. Une dimension réelle supérieure est considérée comme conforme ; **si l’un des côtés est inférieur de plus de 5% à la dimension cible, le résultat n’est pas conforme** (remarque : ce critère sert à évaluer rigoureusement les résultats du test ; cela ne signifie pas que l’API rejette automatiquement les images valides qui n’atteignent pas la dimension demandée). Si la dimension est omise ou que `auto` est transmis, aucun canevas fixe n’est défini comme objectif.
3. **Distinguer l’acceptation des paramètres du résultat réel** : l’absence d’erreur signifie seulement que « le paramètre a été accepté ». Pour savoir si `Mask` isole strictement une zone ou si `quality=high` apporte un gain visuel, il faut examiner l’image finale.

## 3. Résultats des tests : quels paramètres sont le plus souvent mal compris ?

En comparant les paramètres de requête, les pixels réellement livrés et la facture finale, nous avons relevé plusieurs faits clés que les développeurs interprètent souvent mal :

| Scénario demandé | Dimensions réellement livrées | Niveau de facturation et tarif en CNY | Résultat du test et conséquence pratique |
| :- | :- | :- | :- |
| `gpt-image-2`, `2048x2048`, `quality` omis | 2048×2048 | 2K, ¥0.11 | Cette requête a généré avec succès une grande image 2K sans envoyer `quality` (qualité par défaut) |
| `flare`, `2048x2048`, `quality` omis | 2048×2048 | 2K, ¥0.15 | La livraison en 2048×2048 a été vérifiée |
| `sunburst`, `2048x2048`, `quality` omis | 2048×2048 | 2K, ¥0.15 | La livraison en 2048×2048 a été vérifiée |
| `gpt-image-2`, `1024x1024` | **1024×936** | 1K, ¥0.035 | Une image valide a été livrée, mais sa hauteur a diminué d’environ 8.6% ; elle ne satisfait pas au critère strict de dimension de cette série |
| `flare` / `sunburst`, `1024x1024` | **les deux : 1254×1254** | **2K, ¥0.15 pour chacun** | **Une demande 1K ne garantit pas une facturation 1K** ; les images carrées livrées dépassaient la demande et ont été classées en 2K |
| `gpt-image-2`, `1536x1024` | 1536×1024 | 1K, ¥0.035 | Une image horizontale au format courant relève également du niveau de facturation 1K |
| `gpt-image-2`, `3840x2160` | **3840×2159** | 4K, ¥0.13 | La hauteur ne diffère que d’un pixel (écart \< 0.05%) ; le critère d’acceptation 4K est respecté |
| `gpt-image-2`, Mask valide + `2048x2048` + `high` | 2048×2048 | 2K, ¥0.11 | Le flux d’édition Mask fonctionne, mais l’isolation précise de la zone doit être évaluée sur l’image |

Les tests ont également révélé les comportements suivants concernant la compatibilité des paramètres et la gestion des erreurs :

* **Tolérance aux paramètres par défaut** : la génération fonctionne normalement si `quality` et `size` sont omis, transmis comme `null` ou explicitement définis sur `"auto"`.
* **Comment demander correctement du 4K** : **« 4K » désigne un niveau de facturation et ne signifie pas que les images carrées `4096x4096` sont prises en charge**. Pour une grande image horizontale de niveau 4K, utilisez `3840x2160`.
* **Blocage des paramètres invalides sans frais** : les requêtes de test envoyant `4096x4096`, `stream=true`, une chaîne vide `quality=""`, une chaîne vide `size=""` ou `n=0` ont toutes renvoyé une erreur `HTTP 400` et **n’ont généré aucun frais**.

## 4. Ce que propose BetterToken : pas besoin d’adapter chaque route

Face aux variations de dimensions et aux différences entre les nœuds des modèles sous-jacents, BetterToken prend en charge quatre aspects au niveau de la passerelle afin que vous n’ayez pas à écrire un code d’adaptation pour chaque route :

1. **Routage intelligent selon les capacités** : le système sélectionne automatiquement un service disponible doté des capacités correspondantes selon le modèle transmis, la dimension cible (par exemple 2K/4K) et la présence de paramètres d’édition d’image ou de `Mask`.
2. **Interface unifiée et valeurs de repli pour les paramètres** : les interfaces standard `POST /v1/images/generations` (génération d’image) et `POST /v1/images/edits` (édition à partir d’une image de référence/Mask) traitent automatiquement `null`, `auto` et les paramètres omis, et bloquent les entrées invalides au niveau de la passerelle.
3. **Retour transparent des dimensions réelles et du détail de facturation** : en plus des données d’image, le champ `bettertoken_image_billing` du corps de réponse indique directement la **largeur et la hauteur décodées réelles (`width`/`height`), le niveau de facturation (`billing_resolution`), la devise et le montant réglé (`settled_amount`)**.
4. **Distinction claire entre deux notions essentielles** :
   * **La prise en charge du paramètre `Mask` ≠ une retouche précise au pixel près** : l’interface permet de charger une image de référence et une Mask pour effectuer une édition, mais certains résultats de test ont également modifié des zones protégées à l’extérieur du masque. Par exemple, lors de notre test géométrique des deux cercles, le cercle gauche transparent devait changer de couleur et le cercle droit opaque devait être protégé ; les deux cercles ont finalement changé de couleur. Ainsi, **nous confirmons la prise en charge du paramètre Mask, mais ne garantissons pas un isolement strict au pixel près à chaque appel**.
   * **La prise en charge du paramètre `quality` ≠ une amélioration de qualité garantie et fixe** : l’interface accepte des valeurs comme `"auto"` ou `"high"` et les route correctement. Toutefois, la génération étant aléatoire, nous ne promettons pas, sur la base d’un seul échantillon, que `high` produira une amélioration d’un pourcentage donné.

> ⚠️ **Deux limites réelles à connaître avant l’intégration** :
>
> 1. **Le routage par capacité ne garantit pas un nombre de pixels strictement fixe à chaque appel** : en raison des différences de sortie des services sous-jacents, les pixels peuvent varier même si la requête est dirigée vers le bon nœud (par exemple, certaines requêtes `1024x1024` ont aujourd’hui renvoyé `1024×936` et certains échantillons demandant `3840x2160` ont renvoyé `3840×2161`). Si le rapport du canevas est essentiel à votre activité, utilisez les dimensions réelles renvoyées pour recadrer ou post-traiter l’image.
> 2. **Demander du 1K ne signifie pas nécessairement payer le tarif 1K** : le système classe l’image selon les **dimensions valides réellement livrées**. Aujourd’hui, les deux modèles 2.5 (et certains cas de `gpt-image-2`) ont renvoyé `1254×1254` pour des demandes `1024x1024` ; le système les a donc classées au niveau **2K** et a appliqué le tarif correspondant.

## 5. Prise en charge des trois modèles : lequel appeler et quelles valeurs transmettre ?

La configuration des capacités et la couverture actuelle des tests de `gpt-image-2`, `gpt-image-2.5-flare` et `gpt-image-2.5-sunburst` sont les suivantes :

| Dimension de capacité | `gpt-image-2` | `gpt-image-2.5-flare` | `gpt-image-2.5-sunburst` |
| :- | :- | :- | :- |
| **Demande de génération 1K** | Pris en charge (testé ; la dimension réelle peut différer de la cible, par exemple 1024×936 ou 1254×1254) | Pris en charge (testé ; cette série a renvoyé une dimension supérieure de 1254×1254, facturée en 2K) | Pris en charge (testé ; cette série a renvoyé une dimension supérieure de 1254×1254, facturée en 2K) |
| **Génération 2K (`2048x2048`)** | **Livraison testée lors de cette série** | **Livraison testée lors de cette série** | **Livraison testée lors de cette série** |
| **Génération 4K (`3840x2160`)** | **Livraison horizontale testée lors de cette série** | Configuration de routage alignée pour la prise en charge | Configuration de routage alignée pour la prise en charge |
| **Édition classique d’une image de référence (sans Mask)** | **Prise en charge testée lors de cette série** (l’omission d’une Mask ou l’envoi d’une Mask vide déclenche l’édition classique) | Pas encore confirmée séparément (la prise en charge de Mask ne prouve pas celle de l’édition classique) | Pas encore confirmée séparément (la prise en charge de Mask ne prouve pas celle de l’édition classique) |
| **Édition locale avec Mask** | **Livraison 2K testée lors de cette série** | Configuré pour prendre en charge l’édition Mask en 4K (autres niveaux non confirmés) | Configuré pour prendre en charge l’édition Mask en 4K (autres niveaux non confirmés) |
| **Paramètre de qualité (`quality`)** | Valeurs par défaut/`auto`/`high` **toutes vérifiées par les tests** | Valeurs par défaut/`auto` testées ; routage de `high` aligné dans la configuration | Valeurs par défaut/`auto` testées ; routage de `high` aligné dans la configuration |

*Remarque : « testé lors de cette série » signifie que les régressions et les exemples générés aujourd’hui ont directement livré des images et des exemples de facturation. « Configuration de routage alignée pour la prise en charge » signifie que la plateforme a aligné la configuration du canal pour la capacité concernée, mais n’a pas répété aujourd’hui les appels pour toutes les combinaisons possibles.*

## 6. Deux exemples d’images réelles : quels sont les résultats ?

Pour montrer le niveau de génération le plus réaliste possible, nous avons suivi la structure **« sujet explicite + texture du matériau + direction de la lumière + proportions de la composition + éléments à exclure »** du [guide officiel d’OpenAI sur les prompts d’image](https://developers.openai.com/api/docs/guides/image-prompting) et généré les deux exemples de commerce en ligne ci-dessous avec l’interface réelle de BetterToken (les sorties originales sont conservées, sans retouche ultérieure).

### Exemple A : photographie de produit pour le commerce en ligne, dimensions et détails en 1K / 2K / 4K

**Description de la scène (conception originale en chinois)** :

> Générer une véritable photo de studio pour le commerce en ligne : un mug en céramique rouge corail (anse orientée vers la droite) posé sur un plan de travail en pierre gris clair, avec un linge en lin beige plié à gauche. Le mug porte le texte blanc bien net « BETTER DAY ». Lumière latérale douce venant du haut à gauche ; conserver les reflets subtils de l’émail céramique, les fibres du lin et les ombres de contact naturelles. Le mug est entièrement visible et centré ; arrière-plan neutre et simple, sans autres objets, filigrane ni texte supplémentaire.

**Prompt réel envoyé en anglais** :

```text theme={null}
Photorealistic ecommerce studio photograph. A coral-red ceramic mug with a handle on the right sits on a pale gray stone tabletop, with a folded beige linen cloth to its left. The mug reads "BETTER DAY" in clear white lettering. Soft directional light from upper left, subtle glaze reflections, visible linen fibers and natural contact shadows. Entire mug in frame, centered composition, simple neutral background. No other objects, no watermark, no additional text.
```

Nous avons utilisé `gpt-image-2` (`quality="high"`, 1 image par génération), conservé exactement le même Prompt et demandé trois dimensions différentes uniquement via le paramètre `size`, sans ajouter « 4K » au prompt pour forcer le résultat :

| Dimension demandée (`size`) | Dimensions réellement livrées | Niveau de facturation / coût réel | Durée d’un appel |
| :- | :- | :- | :- |
| `1024x1024` | **1254×1254** | **2K / ¥0.11** | 34.35 secondes |
| `2048x2048` | **2048×2048** | **2K / ¥0.11** | 31.97 secondes |
| `3840x2160` | **3840×2161** | **4K / ¥0.13** | 24.36 secondes |

**1. Image originale livrée pour la demande `1024x1024` (retour réel de 1254×1254) :**

<Frame>
  <img src="https://mintcdn.com/bettertoken-d796114e/hPGTCgdK9IohJYOA/images/gpt-image-guide/product-1k-0.png?fit=max&auto=format&n=hPGTCgdK9IohJYOA&q=85&s=975ebb5653a1a0e6847310d8448a56d9" alt="Image de produit GPT Image 2 : demande de 1024×1024, livraison réelle de 1254×1254" style={{ borderRadius: '0.5rem' }} width="1254" height="1254" data-path="images/gpt-image-guide/product-1k-0.png" />
</Frame>

**2. Image originale livrée pour la demande `2048x2048` (retour réel de 2048×2048) :**

<Frame>
  <img src="https://mintcdn.com/bettertoken-d796114e/hPGTCgdK9IohJYOA/images/gpt-image-guide/product-2k-0.png?fit=max&auto=format&n=hPGTCgdK9IohJYOA&q=85&s=a290e92bd7db319ed801c06640c7ba8d" alt="Image de produit GPT Image 2 : demande et livraison réelle de 2048×2048" style={{ borderRadius: '0.5rem' }} width="2048" height="2048" data-path="images/gpt-image-guide/product-2k-0.png" />
</Frame>

**3. Image horizontale originale livrée pour la demande `3840x2160` (retour réel de 3840×2161) :**

<Frame>
  <img src="https://mintcdn.com/bettertoken-d796114e/hPGTCgdK9IohJYOA/images/gpt-image-guide/product-4k-0.png?fit=max&auto=format&n=hPGTCgdK9IohJYOA&q=85&s=1e68f4d96829d9e52f9fa88aceac3c27" alt="Image de produit horizontale GPT Image 2 : demande de 3840×2160, livraison réelle de 3840×2161" style={{ borderRadius: '0.5rem' }} width="3840" height="2161" data-path="images/gpt-image-guide/product-4k-0.png" />
</Frame>

**4. Comparaison des recadrages à taille originale des zones correspondantes des trois images (texte du mug et détails du matériau) :**

<Frame>
  <GptImageComparison kind="crops" label="Comparaison à 100% des recadrages en pixels d’origine des trois images de produit" labels={["Demande 1K · Résultat 1254²","Demande 2K · Résultat 2048²","Demande 4K · Résultat 3840×2161"]} caption="Chaque panneau est un recadrage de 480×480 pixels d’origine. Les images ont été générées indépendamment, avec des compositions différentes. L’échelle de la page ne change pas les pixels du fichier." />
</Frame>

**Observations des tests** :

* **Rendu soigné** : les trois images montrent les reflets de l’émail rouge corail, l’anse à droite, le plan de travail en pierre gris clair, les fibres du linge en lin beige et le texte blanc « BETTER DAY » bien lisible.
* **Différences entre échantillons indépendants** : chaque génération est un échantillon indépendant ; les proportions du mug, l’épaisseur de la police et le pliage du tissu varient naturellement (par exemple, le texte est disposé sur deux lignes dans l’image horizontale 4K). Les recadrages montrent donc les détails réels de chaque image et ne constituent pas une expérience optique de netteté avec une composition strictement identique.
* **Limite de facturation illustrée directement** : bien que la première image ait été demandée en `1024x1024`, elle a été livrée en image carrée haute définition `1254×1254` et facturée **au niveau 2K (¥0.11)**, comme la deuxième image en `2048×2048`.

### Exemple B : changement local de couleur d’un produit, résultat réel et limites de Mask

Nous avons utilisé comme image d’origine la première image du produit de l’exemple A (`1254×1254`) et créé un masque avec canal Alpha de mêmes dimensions [mask-mug.png](/images/gpt-image-guide/mask-mug.png) : **seul le polygone du corps du mug est transparent (retouche autorisée), tandis que l’anse, la paroi intérieure du bord et l’arrière-plan restent opaques (à préserver) ; le texte du mug se trouve dans la zone transparente et le prompt demande de le conserver**.

<Frame>
  <GptImageComparison kind="mask" label="Image d’origine, aperçu superposé du masque et résultat de la retouche" labels={["Original","Zone verte : retouche autorisée","Résultat réel de la retouche"]} caption="Images réduites uniquement pour la comparaison. Le bord de la tasse hors du masque a aussi changé de couleur. Les sorties originales de l’API sont conservées séparément." />
</Frame>

<Frame>
  <img src="https://mintcdn.com/bettertoken-d796114e/hPGTCgdK9IohJYOA/images/gpt-image-guide/mask-diagram.png?fit=max&auto=format&n=hPGTCgdK9IohJYOA&q=85&s=7d648791e31a2358ee47907bc3755fae" alt="Illustration de la zone Mask : le noir représente la zone transparente modifiable et le blanc la zone opaque à préserver" style={{ borderRadius: '0.5rem' }} width="1254" height="1254" data-path="images/gpt-image-guide/mask-diagram.png" />
</Frame>

*(Remarque : l’image ci-dessus est une visualisation en noir et blanc ; le noir indique la zone modifiable et le blanc la zone à préserver. Le fichier réellement envoyé à l’API est `mask-mug.png`, doté d’un canal de transparence.)*

**Description de la scène (conception originale en chinois)** :

> Remplacer uniquement le corps rouge corail du mug dans la zone transparente du masque par un bleu marine foncé. Préserver la matière céramique, l’éclairage et les reflets. Garder inchangés le texte blanc « BETTER DAY », l’anse rouge, le linge en lin, le plan de travail, l’arrière-plan et la composition générale. N’ajouter ni supprimer aucun objet.

**Prompt réel de retouche (modèle : `gpt-image-2`, `size="2048x2048"`, `quality="high"`)** :

```text theme={null}
Change only the coral-red mug body inside the transparent mask to deep navy blue. Preserve ceramic texture, lighting and reflections. Keep the white "BETTER DAY" lettering, red handle, linen cloth, tabletop, background and composition unchanged. Do not add or remove any objects. Do not change anything outside the transparent mask.
```

**Résultat réel de la retouche (2048×2048, durée de 38.51 secondes, coût de ¥0.11) :**

<Frame>
  <img src="https://mintcdn.com/bettertoken-d796114e/hPGTCgdK9IohJYOA/images/gpt-image-guide/product-mask-0.png?fit=max&auto=format&n=hPGTCgdK9IohJYOA&q=85&s=1a3ba294610d624bd6a09bc7c03aa228" alt="Résultat de la retouche Mask avec GPT Image 2 : le corps du mug devient bleu foncé et l’anse reste rouge, mais la paroi intérieure du bord change également" style={{ borderRadius: '0.5rem' }} width="2048" height="2048" data-path="images/gpt-image-guide/product-mask-0.png" />
</Frame>

**Comparaison détaillée du débordement dans la zone protégée :**

<Frame>
  <GptImageComparison kind="boundary" label="Agrandissement de la zone protégée par Mask : le bord et la paroi intérieure n’étaient pas dans la zone transparente, mais sont également devenus bleus" labels={["Original : bord et paroi intérieure rouges","Après retouche : bord et paroi intérieure également bleus"]} caption="Les zones correspondantes sont agrandies ou redimensionnées pour l’affichage, pas pour une comparaison pixel par pixel. Toutes deux sont hors du masque transparent." />
</Frame>

**Contre-exemple : échantillon de recoloration des « deux cercles » lors du test de régression (Mask accepté ≠ isolation précise)**

<Frame>
  <GptImageComparison kind="circles" label="Contre-exemple des deux cercles en régression : seul le cercle gauche était transparent pour être recoloré, mais le cercle droit de la zone protégée a également changé" labels={["Original : deux cercles rouges","Vert : seule la gauche peut être modifiée","Résultat : les deux cercles sont devenus bleus"]} caption="Exemples existants de BetterToken API. L’objet protégé à droite a aussi été modifié. Les images sont réduites uniquement pour la mise en page." />
</Frame>

**Observations des tests (limites exposées clairement)** :

* **L’objectif principal de recoloration est atteint** : le corps extérieur du mug devient bleu marine foncé et conserve son éclat céramique ; **l’anse rouge hors masque, le linge en lin à gauche et l’arrière-plan sont préservés, et le texte « BETTER DAY » dans le masque reste lisible**.
* **La limite stricte de Mask n’est pas respectée (débordement)** : en observant le bord et la paroi intérieure du mug, on constate que **la partie rouge corail initialement dans la zone protégée opaque a elle aussi été recolorée en bleu foncé**. Dans le test géométrique plus extrême des « deux cercles », le cercle droit non masqué a également changé de couleur.
* **Conseil d’utilisation** : lors de l’envoi d’une image de référence et d’une Mask, assurez-vous qu’elles ont les mêmes dimensions de canevas (zone à modifier transparente, zone à préserver opaque) et indiquez dans le Prompt à la fois « ce qui doit changer » et « ce qui doit être conservé ». Pour les images commerciales industrielles avec logo de marque, petits textes d’emballage ou exigences strictes sur les contours, **agrandissez l’image après génération et vérifiez les limites de la zone protégée**.

## 7. Tarifs et coût réel d’utilisation : quel est le montant facturé ?

BetterToken maintient une tarification transparente. Voici l’instantané des prix publics au **19 octobre 2026** (CNY pour les comptes professionnels en renminbi, USD pour les comptes ordinaires en dollars ; ces tarifs sont indépendants et ne sont pas convertis selon le taux de change en temps réel) :

| Nom du modèle | Tarif 1K / image | Tarif 2K / image | Tarif 4K / image |
| :- | :- | :- | :- |
| **`gpt-image-2`** (CNY / USD) | ¥0.035 / \$0.0062 | ¥0.11 / \$0.0194 | ¥0.13 / \$0.0229 |
| **`gpt-image-2.5-flare`** (CNY / USD) | ¥0.035 / \$0.0062 | ¥0.15 / \$0.0265 | ¥0.18 / \$0.0318 |
| **`gpt-image-2.5-sunburst`** (CNY / USD) | ¥0.035 / \$0.0062 | ¥0.15 / \$0.0265 | ¥0.18 / \$0.0318 |

Selon ces prix publics, le coût indicatif pour 100 appels est le suivant, en supposant que les 100 images livrées relèvent effectivement du niveau de facturation concerné (estimation arithmétique) :

| Nom du modèle | Coût de 100 images 1K | Coût de 100 images 2K | Coût de 100 images 4K |
| :- | :- | :- | :- |
| **`gpt-image-2`** (CNY / USD) | ¥3.50 / \$0.62 | ¥11.00 / \$1.94 | ¥13.00 / \$2.29 |
| **`flare` ou `sunburst`** (CNY / USD) | ¥3.50 / \$0.62 | ¥15.00 / \$2.65 | ¥18.00 / \$3.18 |

> 💡 **Point essentiel pour le budget : calculez selon le « niveau réellement livré », et non selon les « paramètres demandés ».**
>
> Comme le montrent les tests ci-dessus, certaines requêtes `1024x1024` (1K) envoyées aujourd’hui à `flare`, `sunburst` ou `gpt-image-2` ont livré des images `1254×1254`. Le système les classe alors au niveau **2K** selon la dimension réelle (soit ¥0.15 ou ¥0.11, et non le tarif 1K de ¥0.035). Si les 100 requêtes `1024x1024` envoyées à `flare` renvoyaient toutes `1254×1254`, le coût des 100 images aux tarifs actuels serait de **¥15.00 (estimation arithmétique)**.
>
> En outre, la classification tient compte de la dimension cible et d’un seuil d’écart raisonnable (par exemple, `3840×2159` est normalement classé en 4K, et `1536×1024` en 1K). Ne recalculez pas les frais côté application selon une règle simpliste telle que « le côté le plus long dépasse 1024 » ; **le règlement est toujours déterminé par le champ `bettertoken_image_billing` du corps de réponse**.

### Pourquoi ne pas se fier uniquement au « faible prix par image » ?

Pour comparer les coûts des API d’image entre différentes plateformes, il est utile de calculer trois éléments :

1. **Le tarif n’est comparable que si la réponse réelle atteint la dimension visée** : une requête annoncée comme « compatible 4K à très bas prix », mais qui ne renvoie qu’une petite image réduite en 1024, ne peut pas être utilisée en production nécessitant des images haute définition et ne doit pas être comparée comme un tarif 4K valable.
2. **Intégrez les échecs et le coût des nouvelles tentatives dans le total** : les tests de paramètres invalides de cette série n’ont pas été facturés ; lorsqu’une image est bien livrée mais ne répond pas au besoin, la soumettre à nouveau constitue une nouvelle requête à budgéter séparément. Les 4 images des exemples de produits et Mask de ce guide (3 générations + 1 retouche) ont chacune été livrées en un seul appel. L’échantillon Mask présente le débordement de couleur mentionné ci-dessus. Les tarifs unitaires étaient ¥0.11, ¥0.11, ¥0.13 et ¥0.11, soit **un coût réel total de seulement ¥0.46 pour les 4 images** ; la facture correspond exactement aux débits du compte. Si l’instabilité de la route ou l’incompatibilité des paramètres oblige à répéter les générations, le coût réel d’obtention d’un visuel utilisable peut augmenter même si le prix affiché par image est faible.
3. **Réduisez les coûts d’ingénierie d’adaptation cachés** : grâce à la normalisation des paramètres, au routage intelligent selon les capacités et au retour en temps réel des pixels et champs de facturation réels, BetterToken réduit le travail consistant à adapter chaque service et à compiler séparément les dimensions et les coûts.

## 8. Exemples d’appels prêts à copier

Enregistrez votre BetterToken API Key dans la variable d’environnement `BETTERTOKEN_API_KEY` pour copier directement les commandes suivantes et commencer vos appels.

### Exemple 1 : requête JSON pour générer une image de produit haute définition (`POST /v1/images/generations`)

L’exemple appelle `gpt-image-2` pour générer une image de produit haute définition en `2048x2048` (`model` peut être remplacé directement par `gpt-image-2.5-flare` ou `gpt-image-2.5-sunburst`) :

```bash theme={null}
curl https://bettertoken.ai/v1/images/generations -o response.json \
  -H "Authorization: Bearer $BETTERTOKEN_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "model": "gpt-image-2",
  "prompt": "Photorealistic ecommerce studio photograph. A coral-red ceramic mug with a handle on the right sits on a pale gray stone tabletop, with a folded beige linen cloth to its left. The mug reads \"BETTER DAY\" in clear white lettering. Soft directional light from upper left, subtle glaze reflections, visible linen fibers and natural contact shadows. Entire mug in frame, centered composition, simple neutral background. No other objects, no watermark, no additional text.",
  "size": "2048x2048",
  "quality": "high",
  "n": 1,
  "response_format": "b64_json",
  "output_format": "png"
}
JSON
```

* **Remarque sur les dimensions** : pour une image horizontale 4K, remplacez `"size"` par `"3840x2160"` (n’utilisez pas `"4096x4096"`). Les dimensions valides doivent actuellement respecter les critères suivants : largeur et hauteur multiples de 16, côté le plus long inférieur ou égal à 3840, rapport entre le côté long et le côté court inférieur ou égal à 3:1, et nombre total de pixels compris entre `655,360` et `8,294,400`.
* **Remarque sur l’identification du format de fichier** : même si la requête spécifie `"output_format": "png"`, certains nœuds sous-jacents peuvent renvoyer des données binaires au format JPEG. Lors de l’enregistrement ou du traitement de l’image, identifiez le format réel à partir de l’en-tête du fichier (Magic Bytes) plutôt que de coder l’extension en dur.

### Exemple 2 : retouche locale Multipart avec image de référence et Mask (`POST /v1/images/edits`)

Préparez l’image d’origine `product-1k-0.png` et le masque transparent `mask-mug.png` de mêmes dimensions (si vous souhaitez uniquement une retouche classique à partir d’une image de référence, supprimez directement la ligne `-F "mask=..."`) :

```bash theme={null}
curl https://bettertoken.ai/v1/images/edits -o response.json \
  -H "Authorization: Bearer $BETTERTOKEN_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image=@product-1k-0.png;type=image/png" \
  -F "mask=@mask-mug.png;type=image/png" \
  -F 'prompt=Change only the coral-red mug body inside the transparent mask to deep navy blue. Preserve ceramic texture, lighting and reflections. Keep the white "BETTER DAY" lettering, red handle, linen cloth, tabletop, background and composition unchanged. Do not add or remove any objects. Do not change anything outside the transparent mask.' \
  -F "size=2048x2048" \
  -F "quality=high" \
  -F "n=1" \
  -F "response_format=b64_json"
```

### Exemple 3 : lecture des pixels livrés et des informations de facturation (structure de réponse et code d’analyse)

En plus de `data[].b64_json`, le corps de réponse BetterToken contient aussi le nœud de champ étendu `bettertoken_image_billing` :

```json theme={null}
{
  "created": 1792398084,
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAAANSUhEUgAA..."
    }
  ],
  "bettertoken_image_billing": {
    "currency": "CNY",
    "settled_amount": "0.11",
    "outputs": [
      {
        "index": 0,
        "width": 2048,
        "height": 2048,
        "billing_resolution": "2K",
        "currency": "CNY",
        "amount": "0.11"
      }
    ]
  }
}
```

Vous pouvez utiliser l’extrait Python suivant pour effectuer en une seule étape le **décodage de l’image, l’identification du format réel, la lecture des dimensions et la vérification de la facture** :

```python theme={null}
import base64
import io
import json
from pathlib import Path
from PIL import Image  # 需要 Pillow

# 将 API 的 JSON 响应保存为 response.json 后执行。
resp_json = json.loads(Path("response.json").read_text())
if "error" in resp_json:
    raise RuntimeError(resp_json["error"])

billing = resp_json["bettertoken_image_billing"]
outputs = {item["index"]: item for item in billing["outputs"]}
for index, item in enumerate(resp_json["data"]):
    img_bytes = base64.b64decode(item["b64_json"], validate=True)
    with Image.open(io.BytesIO(img_bytes)) as image:
        image.load()
        width, height = image.size
        ext = {"PNG": "png", "JPEG": "jpg", "WEBP": "webp"}.get(image.format)
        if ext is None:
            raise ValueError(f"未处理的图片格式：{image.format}")
    Path(f"output_{index}.{ext}").write_bytes(img_bytes)
    info = outputs[index]
    print(f"图片 {index}：原图 {width}×{height}；计费档位 {info['billing_resolution']}")
    print(f"单张费用：{info['amount']} {info['currency']}")
    if (width, height) != (info["width"], info["height"]):
        print("图片像素与响应尺寸不一致，请保留结果并联系支持。")
print(f"本次结算：{billing['settled_amount']} {billing['currency']}")

```

***

**Références** :

* [Documentation officielle d’OpenAI : guide de rédaction des prompts d’image (Image Prompting Guide)](https://developers.openai.com/api/docs/guides/image-prompting)
* [OpenAI Cookbook : exemple de génération et de retouche d’images avec haute fidélité d’entrée](https://developers.openai.com/cookbook/examples/generate_images_with_high_input_fidelity)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.