OpenRouter unifie la génération d’images via une API
OpenRouter centralise la génération d'images derrière `POST /api/v1/images` : plusieurs modèles, une seule clé, un format commun, des images de référence et un routage configurable selon les providers.
En bref
- OpenRouter expose un endpoint unique
POST /api/v1/imagespour interroger plusieurs modèles de génération d'images avec une seule clé APIApplication Programming Interface : contrat machine pour consommer un service (HTTP, SDK, webhooks). et un format commun. - La réponse standard renvoie les images en base64 dans
data[].b64_json;media_typeprécise le format quand il est identifiable etusage.costindique le coût quand disponible. input_referencespermet de guider la génération avec une ou plusieurs images de référence, selon les capacités du provider.GET /api/v1/images/modelset les fiches par endpoint exposent modèles, paramètres supportés, streaming et tarification.- Le routage peut être piloté avec
provider.only,order,ignore,sort,allow_fallbacksetprovider.options;allowed_passthrough_parametersindique les options spécifiques acceptées par endpoint. - La facturation des générations d'images est tout-ou-rien : une génération réussie est facturée intégralement ; un échec, une annulation ou un flux interrompu n'entraîne pas de facturation partielle.
Sommaire · 8 sections
Pourquoi un endpoint unique change la donne pour les intégrations multi-modèles
Intégrer la génération d'images dans un produit oblige souvent à jongler entre plusieurs fournisseurs, chacun avec son endpoint, son format de données, ses contrôles et son modèle de facturation. OpenRouter propose de réduire cette complexité avec une API dédiée à la génération d'images : un seul format de requête, une seule clé et plusieurs modèles accessibles derrière POST /api/v1/images.
Pour celles et ceux qui suivent l'écosystème OpenRouter, cette brique s'ajoute aux outils d'observabilité pour agents IA déjà documentés sur 404 Mates.
Le workflow complet : du prompt au fichier local
Le tutoriel officiel détaille un parcours simple, de la création de clé à la requête réutilisable. Voici l'essentiel.
Authentification et choix du modèle
La clé se crée depuis la page dédiée et s'exporte en variable d'environnement :
export OPENROUTER_API_KEY="sk-or-v1-..."
Le modèle se choisit dans la collection de modèles image. Le tutoriel utilise bytedance-seed/seedream-4.5 comme exemple. Il suffit ensuite de changer la valeur de model pour basculer vers un autre modèle compatible.
Les contrôles optionnels — résolution, ratio, qualité, nombre de sorties, images de référence ou streaming — dépendent toutefois du modèle et du provider. La source la plus fiable reste donc la fiche de capacités de l'endpoint concerné.
Pour la découverte à l'exécution, GET /api/v1/images/models renvoie les modèles compatibles, leurs paramètres supportés et l'indication supports_streaming. Les fiches par endpoint permettent ensuite d'obtenir les capacités définitives et les informations de tarification.
Envoi d'une requête et structure de la réponse
La requête minimale ne demande que deux champs dans le body : model et prompt. Voici un exemple Python :
import base64
import os
import requests
response = requests.post(
"https://openrouter.ai/api/v1/images",
headers={
"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
"Content-Type": "application/json",
},
json={
"model": "bytedance-seed/seedream-4.5",
"prompt": "A studio product photo of a matte black travel mug on a light gray background",
},
timeout=120,
)
if not response.ok:
raise RuntimeError(f"{response.status_code}: {response.text}")
result = response.json()
images = result.get("data") or []
if not images or not images[0].get("b64_json"):
raise RuntimeError("The response did not contain image data")
image_bytes = base64.b64decode(images[0]["b64_json"])
with open("output.png", "wb") as output_file:
output_file.write(image_bytes)
print("Saved output.png")
La réponse suit cette structure simplifiée :
{
"data": [
{
"b64_json": "iVBORw0KGgoAAA...",
"media_type": "image/png"
}
],
"usage": {
"cost": 0.0123
}
}
Quelques points à retenir :
dataest un tableau : une requête peut renvoyer plusieurs résultats si le modèle et le provider le permettent.- L'image est renvoyée en base64, pas sous forme d'URL hébergée ; il faut la décoder côté client.
media_typeindique le format lorsqu'il est identifiable, par exemple PNG, JPEG, WebP ou SVG.usage.costindique le coût de la requête quand l'information est disponible. Le chiffre0.0123ci-dessus illustre uniquement la forme du champ, pas un tarif en vigueur.
Passer une image de référence avec input_references
Certains modèles acceptent une ou plusieurs images de référence via input_references. Le principe consiste à fournir une URL HTTP(S) ou, pour un fichier local, une data URL encodée en base64.
Le tutoriel utilise openai/gpt-image-1 dans ce type de workflow :
import base64
import os
import requests
with open("product.jpg", "rb") as reference_file:
reference_base64 = base64.b64encode(reference_file.read()).decode("utf-8")
reference_data_url = f"data:image/jpeg;base64,{reference_base64}"
response = requests.post(
"https://openrouter.ai/api/v1/images",
headers={
"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
"Content-Type": "application/json",
},
json={
"model": "openai/gpt-image-1",
"prompt": (
"Keep the product shape and materials. Place it on a warm stone "
"surface with soft morning light and a clean commercial style."
),
"input_references": [
{
"type": "image_url",
"image_url": {
"url": reference_data_url,
},
}
],
},
timeout=120,
)
Ce pattern est particulièrement utile pour les variations de photos produit : l'image source sert de référence tandis que le promptConsigne / contexte fourni au modèle pour orienter sa génération (system, user, exemples, outils). pilote le décor, l'éclairage ou la mise en scène.
Le nombre de références et les paramètres réellement acceptés varient selon le provider. Avant d'en faire dépendre un workflow de production, mieux vaut vérifier les supported_parameters de l'endpoint concerné.
Routage provider et failover
L'API image ne se contente pas d'unifier la syntaxe. Quand plusieurs providers servent un même modèle, l'objet provider permet aussi de contrôler le routage :
{
"model": "google/gemini-2.5-flash-image",
"prompt": "A minimalist logo for a coffee roaster",
"provider": {
"order": ["google-ai-studio", "google-vertex"],
"allow_fallbacks": true
}
}
Les champs only, order, ignore, sort et allow_fallbacks permettent respectivement de restreindre les providers, fixer un ordre de préférence, en exclure certains, trier les endpoints ou autoriser un repli vers un autre provider.
Un sixième mécanisme complète ce routage : provider.options permet de transmettre des paramètres spécifiques à un provider, indexés par slug. Le provider_tag exposé dans les fiches endpoint sert de slug de base pour cibler ou épingler un provider, tandis que allowed_passthrough_parameters indique les clés que l'endpoint autorise à transmettre.
Pour une intégration en production, c'est un point important : l'API devient une couche de routage et de résilience, mais aussi un moyen d'exploiter certaines capacités propres aux providers sans abandonner le format commun d'OpenRouter.
Streaming : disponible sur certains endpoints
Contrairement à une réponse systématiquement bufferisée, OpenRouter documente aussi un mode SSE pour les endpoints qui supportent nativement le streaming. Le champ supports_streaming permet de les identifier via l'API de découverte, puis stream: true active l'envoi d'images partielles lorsque le provider le permet.
Tous les providers ne le prennent pas en charge. Le comportement doit donc être traité comme une capacité de l'endpoint, au même titre que la résolution ou le nombre d'images.
Facturation : une génération réussit et est facturée, ou échoue sans coût
Pour les générations d'images, OpenRouter applique un modèle de facturation tout-ou-rien. Une génération terminée avec succès est facturée intégralement. À l'inverse, une génération qui échoue ou qui est annulée renvoie une erreur 502 et n'est pas facturée.
Cette règle vaut également pour le streaming : les images partielles reçues pendant un flux SSE ne déclenchent pas de coût partiel. Si le flux est interrompu avant la réussite de la génération, la requête est traitée comme un échec et n'est pas facturée.
Pour une agence ou un produit qui lance de nombreux batchs, c'est une nuance importante : un retry après un échec ne vient pas s'ajouter à une facture déjà partiellement consommée. Le coût reste attaché à la génération finalisée, et non au travail intermédiaire effectué avant un échec.
Dépannage et coûts
| Symptôme | Piste |
|---|---|
data[0].b64_json absent | Vérifier le body de la réponse et confirmer que la requête cible /api/v1/images avec un modèle compatible image |
| Réponse 401 | S'assurer que OPENROUTER_API_KEY est bien exportée dans l'environnement qui exécute le script |
| Réponse 502 | Une génération échouée ou annulée n'est pas facturée ; journaliser l'erreur avant de décider d'un retry |
| Échec avec image de référence | Confirmer que l'endpoint supporte input_references et vérifier le format de l'URL ou de la data URL |
| Coût inattendu | Consulter la tarification de l'endpoint avant un batch et journaliser usage.cost avec le slug du modèle |
| Streaming absent | Vérifier supports_streaming pour le modèle et le provider sélectionnés |
Ce qu'il reste à mesurer avant la production
La documentation décrit précisément l'interface et les capacités déclarées, mais elle ne remplace pas un benchmarkJeu de référence public ou interne pour comparer des modèles (MMLU, HumanEval, etc.) — à lire avec prudence hors domaine. sur le cas d'usage réel. Trois points méritent encore d'être testés :
- Latence réelle selon les modèles, les providers, les formats et la résolution.
- Qualité de sortie sur un jeu de prompts représentatif du produit.
- Comportement sous charge, notamment les erreurs 429, les timeouts et l'efficacité du failover.
Pour le détail des paramètres, des capacités et du comportement de streaming, la documentation officielle de génération d'images et la référence API restent les sources de vérité à consulter.
Lecture 404 Mates
L'intérêt principal pour les agences et les builders réside dans la réduction du coût d'intégration multi-modèles. Quand un produit doit proposer plusieurs options de génération d'images — ou pouvoir basculer d'un fournisseur à l'autre sans réécrire la couche d'accès — maintenir des intégrations séparées devient vite coûteux. Un endpoint commun réduit cette dette, tout en laissant les différences de capacités visibles au niveau de chaque endpoint.
Le champ input_references ouvre un cas d'usage concret pour les agences e-commerce : générer des variations de photos produit à partir d'une image existante. Le support et le nombre de références acceptées variant selon les providers, il faut toutefois interroger les capacités de l'endpoint avant de figer un workflow de production.
Le routage provider est probablement la brique la plus intéressante pour un produit multi-modèles : OpenRouter permet de privilégier, exclure ou ordonner certains providers, d'autoriser le failover et de transmettre des options spécifiques à un provider via provider.options. Cela transforme l'API unifiée en couche d'abstraction opérationnelle, pas seulement en façade syntaxique.
La facturation tout-ou-rien est également intéressante pour des workflows automatisés : une génération échouée, annulée ou interrompue en streaming n'est pas partiellement facturée. Pour les batchs ou les pipelines agents, cela rend le coût d'un retry plus prévisible que dans des systèmes où des unités déjà consommées restent facturées.
Enfin, le streaming SSE existe pour les endpoints qui l'annoncent via supports_streaming. Il ne faut donc pas supposer que toutes les générations sont entièrement bufferisées. Les points qui restent à mesurer côté produit sont surtout la latenceDélai avant (ou pendant) la réponse d’un modèle. Le TTFT mesure le temps jusqu’au premier token. réelle, la qualité des sorties et le comportement sous charge pour les modèles retenus.


