API Pro : générer et retoucher des images
Une image coûte 1 crédit, quel que soit le mode. La génération à partir d'un prompt et la retouche d'une image que tu fournis passent toutes les deux par la même route.
POST /images/quote prend le même corps et renvoie le prix sans rien créer, toujours
{ "cost": 1, ... } ici. Il existe par symétrie avec les vidéos, où le prix varie.
Soumettre une image
POST /images
{ "prompt": "portrait of a woman in a rainy street at night, neon reflections, cinematic",
"width": 832, "height": 1216 }| Champ | Type | Défaut | Ce que ça fait |
|---|---|---|---|
prompt | string | required | La scène. L'anglais donne les résultats les plus précis. |
width, height | int | 1024 x 1024 | Taille en pixels. Bonnes proportions : 1024 x 1024 (carré), 832 x 1216 (portrait), 1216 x 832 (paysage). |
mode | string | generation | edit, img2img ou inpaint, voir ci-dessous. Absent signifie générer depuis le prompt. |
image_b64 | string | Image source en base64 (PNG ou JPEG), requise par les trois modes de retouche. 12 Mo décodés au maximum. | |
mask_b64 | string | Masque en base64 : requis par inpaint, facultatif pour edit. Peins en rouge les zones à retoucher, à la taille de l'image source. | |
lora | string | Un personnage entraîné sur le compte : le name renvoyé par GET /loras. Mets son trigger dans le prompt. | |
lora2, lora2_strength | string, number | Un second personnage et sa force (0 à 1, défaut 1) pour une scène à deux. | |
count | int | 1 | Nombre d'images à générer depuis cette requête, de 1 à 8. Chacune reçoit sa propre graine aléatoire ; avec seed, elles prennent seed, seed+1, seed+2... C'est le sélecteur Images par génération de l'app. |
seed | int | au hasard | Graine du rendu, de 0 à 4294967295. Même seed, même prompt et mêmes réglages : le même rendu, à de très légers écarts près si la carte graphique change. Garder la seed et retoucher le prompt décline le rendu en gardant sa composition. |
steps | int | engine | Laisse vide. Le moteur connaît sa propre valeur. |
La réponse :
{ "jobId": "test-79634842-4586-46d4-ad52-d9ea236ae00d", "seed": 178078967, "cost": 1 }La graine (seed) est renvoyée dans la réponse, qu'elle ait été donnée ou tirée au hasard : garde-la
pour refaire la même image, ou pour la décliner.
Demander plusieurs images à la fois
Avec count supérieur à 1, une seule requête lance plusieurs rendus, chacun avec sa propre graine, et
la réponse les liste tous :
{ "count": 4, "requested": 4, "cost_total": 4,
"jobs": [ { "jobId": "...", "seed": 178078967, "cost": 1 }, { "jobId": "...", "seed": 903412, "cost": 1 } ],
"errors": [],
"jobId": "...", "seed": 178078967, "cost": 1 }Deux points à lire attentivement.
Le jobId, le seed et le cost du premier rendu sont répétés au niveau supérieur. C'est là pour que
les clients écrits avant les batchs continuent de fonctionner sans modification, pas parce que le premier
compte davantage. Interroge chaque entrée de jobs, pas seulement celle-là.
Et compare count avec requested. Un refus en cours de route, faute de crédits ou parce que la clé
a atteint son plafond journalier, arrête le batch là où il en est : requested est ce que tu as demandé,
count est ce qui a réellement démarré, et errors explique pourquoi ça s'est arrêté. Un client qui suppose
que les deux sont égaux perd des rendus en silence.
POST /images/quote accepte aussi count et calcule le prix du batch entier. Les vidéos n'ont pas de count :
une requête, un clip.
Les trois modes de retouche
Les trois fonctionnent sur le même moteur d'édition piloté par instructions, qui préserve l'apparence de
l'image source. Quand tu fournis une image source, width et height sont lus depuis l'image elle-même
et n'ont pas besoin d'être envoyés.
mode | Entrées | Ce que le moteur fait |
|---|---|---|
edit | image_b64 + prompt (+ mask_b64 facultatif) | Applique l'instruction à l'image entière ("add sunglasses", "make it snow"). Avec un masque, la modification se concentre dans la zone rouge. |
inpaint | image_b64 + mask_b64 + prompt | Régénère uniquement la zone rouge du masque en suivant l'instruction. Le reste est recomposé pixel pour pixel. |
img2img | image_b64 + prompt | Retravaille l'image entière en suivant le prompt tout en conservant sa composition et son aspect : une variation. |
En edit, le serveur choisit seul la meilleure façon de traiter la retouche, comme l'application :
- avec un masque : il lit la consigne et choisit entre remplacer le contenu de la zone (un autre objet, un autre vêtement, un visage : la zone est redessinée d'après ce qui doit y apparaître) et modifier ce qui s'y trouve (couleur, matière, lumière). Avec un
lorade personnage, la zone est toujours redessinée, son visage compris ; - sans masque, avec un
lorade personnage (« replace the woman with kara... ») : le serveur trouve la personne de la photo et la redessine avec le personnage ; sans personne trouvée, la consigne s'applique à toute l'image, comme avant.
Même prix dans tous les cas (1 crédit par image). Le choix se voit au résultat, pas dans la réponse.
IMG=$(base64 -w0 photo.png)
curl -s $B/images -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d "{\"mode\":\"edit\",\"prompt\":\"add a red scarf, keep everything else identical\",\"image_b64\":\"$IMG\"}"Créer une image avec des personnages, des objets et un lieu
Ajoute l'objet multiref à POST /images : le serveur fait jouer tes personnages (Personnages), tes objets et animaux et un lieu (Sujets) dans une seule image, chacun reconnaissable, comme l'écran « Créer une image » de l'application. Désigne chacun par @Nom dans le prompt, en anglais.
{ "prompt": "@Mia hands a cup of coffee to @Tom on a sunny terrace, both smiling",
"multiref": {
"characters": [
{ "character_id": "chr_8f3a...", "name": "Mia", "view": 1 },
{ "character_id": "chr_21bc...", "name": "Tom", "lora": "tom_v1", "strength": 1.0, "lora_pass": 0.55 }
],
"subjects": [ { "subject_id": "sub_...", "name": "Mug" } ],
"location": { "subject_id": "sub_...", "name": "Terrace" }
},
"width": 1344, "height": 768, "seed": 42, "count": 1 }Champ de multiref | Ce que ça fait |
|---|---|
characters[].character_id, name | Un personnage de GET /characters ; name est le mot écrit après @ (lettres, chiffres, _). |
characters[].view | La vue de sa sheet qui le représente, 1 à 5 (1, le buste de face, par défaut). |
characters[].sheet_id | Facultatif : la sheet à utiliser (la plus récente par défaut). |
characters[].lora | Facultatif : son LoRA d'image, un nom de la liste image de GET /loras. Le personnage est alors joué par son LoRA, pas par sa vue. |
characters[].strength | Force du LoRA, 0 à 1,5 (1 par défaut). |
characters[].lora_pass | Part de l'image repeinte par sa passe LoRA, 0,3 à 0,9 (0,55 par défaut) ; utile avec plusieurs sujets. |
characters[].description | Facultatif, en anglais : tenue, âge... |
subjects[] | Objets et animaux de /subjects : subject_id, name (par défaut le premier mot de son nom), description, image (laquelle de ses images, 1 par défaut). |
location | Un lieu de /subjects (subject_id, name), ou un décor ponctuel : background_b64 et background_description. |
count | 1 ou 2 : les images sont rendues l'une après l'autre. |
- 4 sujets au plus (personnages, objets et animaux). Sans LoRA, par images seules : 4 références au plus, lieu compris. Le serveur choisit la méthode d'après les références, et place chacune dans l'ordre de
characterspuis desubjects, de gauche à droite. - Un
@Nomqui ne désigne aucune référence est refusé (unknown_mention) ; une référence absente du prompt part quand même. - Prix : une passe coûte le prix d'une image (1 crédit). Une image simple = 1 passe ; plusieurs personnages joués par un LoRA = 1 + une passe par LoRA (4 au plus) ; par images seules, une passe par référence au-delà de la première ; un mélange, les deux. Le total (passes x
count) est réservé à la soumission et débité une seule fois, à l'image finale : un échec ou une annulation ne coûte rien.POST /images/quoteavec le même corps donne le prix exact, la méthode et ses passes, sans rien lancer. - Réponse
202:{ "jobId": "mri_...", "seed", "cost", "method", "passes", "billed_passes" }(aveccount2 :jobsetcost_total). Suivi, téléchargement et annulation passent par les routes habituelles ci-dessous ; pendant le rendu,progressdit la passe en cours ("2/3"). Une image prend 1 à 3 minutes. - L'image finale reste disponible 1 heure, et 10 minutes après son premier téléchargement. Une passe ratée rend
status: "failed"avecreason: "render_failed"; une annulation,reason: "cancelled". - Erreurs :
invalid_count,invalid_view,invalid_lora_pass,invalid_subject_image,invalid_size,character_not_ready, plus celles du Multi-Ref (unknown_character,unknown_subject,unknown_lora,unknown_mention,multiref_too_many_references,invalid_strength...). Voir Limites et erreurs.
Polling
GET /images/{jobId}
| Réponse | Signification |
|---|---|
{ "status": "pending", "phase": "IN_QUEUE" } | En file d'attente |
{ "status": "pending", "phase": "IN_PROGRESS" } | En cours de rendu |
{ "status": "completed", "cost": 1, "file_url": "/pro/v1/images/{jobId}/file", ... } | Terminé, fichier prêt |
{ "status": "failed", "detail": "..." } | Échoué, et rien n'est débité |
Interroge toutes les 3 secondes, pas plus vite : la file est partagée.
Téléchargement
GET /images/{jobId}/file
Le PNG lui-même, comme corps de la réponse (Content-Type: image/png). Disponible dès que le
statut est completed, et 404 media_unavailable une fois le rendu supprimé. Télécharge-le
immédiatement, il n'est pas archivé.
Annulation
POST /images/{jobId}/cancel
Annule un rendu en file d'attente ou en cours. Renvoie { "ok": true }. Rien n'est débité, et le coût
réservé sur le plafond journalier de la clé est restitué.