# Stable Diffusion with LoRAs API

> Texte-image avec n’importe quel modèle de base Stable Diffusion, ainsi que LoRA, plongements, ControlNets et adaptateurs IP

Génère des images à partir d’une invite texte en utilisant un modèle de base indiqué par URL ou identifiant HuggingFace dans `model_name`. Plusieurs `loras` peuvent être fusionnés, et les plongements, ControlNets, adaptateurs IP et entrées IC Light sont pris en charge. Les options d’échantillonneur comprennent de nombreux ordonnanceurs et de 1 à 150 étapes. Génère de 1 à 8 images en png ou jpeg.

- Model id: `lora`
- Made by: Open model
- Category: Text to Image
- Output: image
- Estimated price per run: $0.057 / image (cheapest run $0.057 (57 API credits))
- Run: `POST https://api.doitong.com/v1/run/lora`
- Quote: `POST https://api.doitong.com/v1/quote/lora`
- Docs page: https://doitong.com/fr-CA/developers/models/lora

## Pricing

Price: **$0.057 / image**. Estimated from the typical cost of one run, per output (`num_images`). The quote is exactly what the run charges.

The full example input below costs $0.057 = 57 API credits (1 image × 57 API credits).

Prices are the upstream price in USD, paid from the API balance in API credits (1000 API credits = 1 USD). `POST https://api.doitong.com/v1/quote/lora` with the same JSON body returns the exact price for that input; the quote is exactly what a run charges. Invalid input is never charged and failed or canceled requests are refunded automatically.

## Input parameters

Send either the canonical name or the native field name (not both). Canonical names are the same across models.

| Parameter | Canonical name | Type | Required | Default | Allowed values / range | Description |
|---|---|---|---|---|---|---|
| `model_name` |  | string | yes |  |  | Modèle de base pour générer l’image, identifié par une URL ou un identifiant HuggingFace. |
| `unet_name` |  | string \| null | no |  |  | Sélection d’un U-Net personnalisé pour générer des images; fournissez son identifiant HuggingFace ou son URL. |
| `variant` |  | string \| null | no |  |  | Sélection de variante du modèle HuggingFace; 'fp16' en est un exemple. |
| `prompt` |  | string | yes |  |  | Décrivez l’image que vous souhaitez générer avec le plus de détails possible pour obtenir les meilleurs résultats. |
| `negative_prompt` |  | string | no | `` |  | Invite négative indiquant les détails d’image indésirables. Elle peut exclure les couleurs, les objets, le décor ou des caractéristiques et qualités plus fines, comme une moustache, du flou ou une faible résolution. |
| `prompt_weighting` |  | boolean | no | `false` |  | Interrupteur de pondération de l’invite : true supprime la limite de 77 jetons grâce à la moyenne des plongements et active la syntaxe de pondération. |
| `loras` |  | array of object {path, scale} | no | `[]` |  | LoRA dont l’effet combiné produit l’image générée, sans limite quant au nombre fourni. |
| `loras[].path` |  | string | yes |  |  | Emplacement des poids LoRA, indiqué par une URL ou un chemin. |
| `loras[].scale` |  | number | no | `1` | 0 – 4 | Multiplicateur appliqué au poids LoRA avant sa fusion avec le modèle de base. |
| `embeddings` |  | array of object {path, tokens} | no | `[]` |  | Plongements appliqués pendant la génération d’images pour associer les jetons de l’invite aux poids des plongements. Actuellement, un seul plongement est pris en charge. |
| `embeddings[].path` |  | string | yes |  |  | Poids de l’embedding spécifiés par URL ou chemin de fichier. |
| `embeddings[].tokens` |  | array of string \| null | no |  |  | Jetons de l’invite associés aux poids des plongements. Leur omission crée un jeton par vecteur du fichier de plongements, nommé <s0>, <s1>, ...; utilisez les jetons associés dans vos invites. |
| `controlnets` |  | array of object {path, config_url, variant, image_url, mask_url, conditioning_scale, start_percentage, end_percentage, ip_adapter_index} | no | `[]` |  | ControlNets planifiés pour être appliqués à l’image à des pas de temps précis pendant la génération, sans limite quant au nombre fourni. |
| `controlnets[].path` |  | string | yes |  |  | Emplacement des poids ControlNet, indiqué sous forme d’URL ou de chemin. |
| `controlnets[].config_url` |  | string \| null | no |  |  | URL facultative pointant vers le fichier config.json du ControlNet. |
| `controlnets[].variant` |  | string \| null | no |  |  | Variante facultative à utiliser avec une clé de dépôt Hugging Face. |
| `controlnets[].image_url` |  | string (image URL) | yes |  |  | URL de l’image fournie comme entrée du ControlNet. |
| `controlnets[].mask_url` |  | string (image URL) \| null | no |  |  | Masque du ControlNet, qui doit avoir la même taille que l’image de contrôle lorsqu’il est fourni; la largeur et la hauteur doivent chacune être divisibles par 32. |
| `controlnets[].conditioning_scale` |  | number | no | `1` | 0 – 2 | Mise à l’échelle appliquée aux poids ControlNet avant leur fusion avec le modèle de base. |
| `controlnets[].start_percentage` |  | number | no | `0` | 0 – 1 | Pourcentage du nombre total d’étapes temporelles auquel ControlNet commence à influencer la génération d’image. |
| `controlnets[].end_percentage` |  | number | no | `1` | 0 – 1 | Pourcentage du nombre total d’étapes temporelles auquel ControlNet cesse d’influencer la génération d’image. |
| `controlnets[].ip_adapter_index` |  | integer \| null | no |  |  | Sélection de l’adaptateur IP par index pour un ControlNet InstantID; les autres ControlNets n’ont pas besoin de ce réglage. |
| `controlnet_guess_mode` |  | boolean | no | `false` |  | Limite l’application du ControlNet aux prédictions conditionnelles lorsque la valeur est true. |
| `ip_adapter` |  | array of object {ip_adapter_image_url, ip_adapter_mask_url, path, model_subfolder, weight_name, insight_face_model_path, scale, scale_json, unconditional_noising_factor, image_projection_shortcut} | no | `[]` |  | Adaptateurs IP utilisés pour générer des images. La fourniture d’entrées nécessite image_encoder_path. |
| `ip_adapter[].ip_adapter_image_url` |  | string (image URL) \| array of image URL | yes |  |  | URL de l’image fournie comme entrée de l’adaptateur IP. |
| `ip_adapter[].ip_adapter_mask_url` |  | string (image URL) \| null | no |  |  | Masque de l’adaptateur IP, soumis à une contrainte de taille lorsqu’il est fourni : ses dimensions doivent être identiques à celles de l’image de l’adaptateur. |
| `ip_adapter[].path` |  | string | yes |  |  | Emplacement des poids de l’adaptateur IP, indiqué sous forme d’URL ou de chemin. |
| `ip_adapter[].model_subfolder` |  | string \| null | no |  |  | Emplacement des poids de l’adaptateur IP, indiqué comme sous-dossier du répertoire du modèle. |
| `ip_adapter[].weight_name` |  | string \| null | no |  |  | Nom de fichier des poids. |
| `ip_adapter[].insight_face_model_path` |  | string \| null | no |  |  | Emplacement des poids du modèle InsightFace, indiqué sous forme d’URL ou de chemin. |
| `ip_adapter[].scale` |  | number | no | `1` | ≥ 0 | Facteur d’échelle des poids de l’adaptateur IP, appliqué avant leur fusion dans le modèle de base. |
| `ip_adapter[].scale_json` |  | object \| null | no |  |  | Facteur d’échelle des poids de l’adaptateur IP, appliqué avant leur fusion dans le modèle de base. |
| `ip_adapter[].unconditional_noising_factor` |  | number | no | `0` | 0 – 1 | Facteur contrôlant le bruitage non conditionnel de l’adaptateur IP. |
| `ip_adapter[].image_projection_shortcut` |  | boolean | no | `true` |  | Réglage du raccourci de projection d’image, dont la valeur par défaut est True. Utilisez False pour les modèles FaceID plus V1 et True pour les modèles FaceID plus V2. |
| `image_encoder_path` |  | string \| null | no |  |  | Encodeur d’image indiqué par une URL HTTPS ou un identifiant Hugging Face, dont la compatibilité dépend des poids IP-Adapter : SD1.5 utilise image_encoder_subfolder='models/image_encoder', tandis que h94/IP-Adapter SDXL utilise h94/IP-Adapter et image_encoder_subfolder='sdxl_models/image_encoder'. Un encodeur est requis lorsque ip_adapter contient une valeur. |
| `image_encoder_subfolder` |  | string \| null | no |  |  | Sous-répertoire de image_encoder_path contenant les poids de l’encodeur d’image. |
| `image_encoder_weight_name` |  | string \| null | no | `pytorch_model.bin` |  | Sélectionnez par nom les poids de l’encodeur d’image à utiliser pour générer des images. |
| `ic_light_model_url` |  | string \| null | no |  |  | URL du modèle IC Light utilisée lors de la génération d’images. |
| `ic_light_model_background_image_url` |  | string (image URL) \| null | no |  |  | Arrière-plan compatible avec le modèle pour la génération d’images IC Light, fourni sous forme d’URL d’image. |
| `ic_light_image_url` |  | string (image URL) \| null | no |  |  | URL de l’image d’entrée pour la génération avec le modèle IC Light. |
| `seed` |  | integer \| null | no |  |  | Graine pour reproduire des images dans Stable Diffusion. Une image peut être reproduite exactement à chaque exécution en conservant la version du modèle, l’invite et la graine inchangées. |
| `image_size` |  | object {width, height} \| enum (string) \| null | no | `square_hd` | `square_hd`, `square`, `portrait_4_3`, `portrait_16_9`, `landscape_4_3`, `landscape_16_9` | Dimensions de l’image de sortie, sélectionnées parmi des préréglages ou définies par une largeur et une hauteur personnalisées. Les deux dimensions personnalisées doivent être divisibles par 8. |
| `num_inference_steps` |  | integer | no | `30` | 1 – 150 | Contrôle le nombre d’étapes de génération effectuées par Stable Diffusion; des étapes supplémentaires peuvent produire une image finale plus détaillée. |
| `guidance_scale` |  | number | no | `7.5` | 0 – 20 | Intensité d’adhésion à l’invite pour la sélection d’images, exprimée comme CFG (Classifier Free Guidance). |
| `clip_skip` |  | integer | no | `0` | 0 – 2 | Ignore une partie de la génération d’image pour accélérer le rendu, ce qui produit des résultats légèrement différents. |
| `scheduler` |  | enum (string) \| null | no |  | `DPM++ 2M`, `DPM++ 2M Karras`, `DPM++ 2M SDE`, `DPM++ 2M SDE Karras`, `Euler`, `Euler A`, `Euler (trailing timesteps)`, `LCM`, `LCM (trailing timesteps)`, `DDIM`, `TCD` | Planificateur ou échantillonneur utilisé pour débruiter l’image. |
| `timesteps` |  | object {method, array} | no | `{"array":[],"method":"default"}` |  | Remplacement du calendrier des pas de temps de débruitage, mutuellement exclusif avec sigmas. Sans remplacement — le comportement par défaut — le planificateur calcule les pas de temps à partir de num_inference_steps; un calendrier personnalisé rend num_inference_steps sans effet. Un remplacement nécessite que le planificateur prenne en charge l’argument timesteps pour set_timesteps. |
| `timesteps.method` |  | enum (string) | no | `default` | `default`, `array` | Choisissez comment les pas de temps sont déterminés : 'default', le réglage par défaut, permet au planificateur d’utiliser `num_inference_steps`. Pour fournir vous-même un calendrier de pas de temps, sélectionnez 'array' et placez le calendrier dans le champ `array`. |
| `timesteps.array` |  | array of integer | no | `[]` |  | Calendrier des pas de temps appliqué lorsque la méthode sélectionnée est 'custom'. |
| `sigmas` |  | object {method, array} | no | `{"array":[],"method":"default"}` |  | Remplacement du calendrier des sigmas de débruitage, mutuellement exclusif avec timesteps. Sans remplacement — le comportement par défaut — le planificateur calcule les sigmas à partir de num_inference_steps; un calendrier personnalisé rend num_inference_steps sans effet. Un remplacement nécessite que le planificateur prenne en charge l’argument sigmas pour set_sigmas. |
| `sigmas.method` |  | enum (string) | no | `default` | `default`, `array` | Choisissez comment les sigmas sont déterminés : 'default', le réglage par défaut, utilise les valeurs sigma propres au planificateur. Pour fournir vous-même un calendrier sigma, sélectionnez 'custom' et placez le calendrier dans le champ `array`. |
| `sigmas.array` |  | array of number | no | `[]` |  | Calendrier sigma appliqué lorsque la méthode sélectionnée est 'custom'. |
| `prediction_type` |  | enum (string) | no | `epsilon` | `v_prediction`, `epsilon` | Choisissez le type de prédiction utilisé pour générer des images; sans autre sélection, `epsilon` est utilisé. |
| `rescale_betas_snr_zero` |  | boolean | no | `false` |  | Contrôle si l’échantillonneur active rescale_betas_snr_zero. |
| `image_format` |  | enum (string) | no | `png` | `jpeg`, `png` | Format de fichier de l’image obtenue. |
| `num_images` | `num_outputs` | integer | no | `1` | 1 – 8 | Définissez le nombre d’images produites par une seule requête, en accordant davantage de temps de génération aux lots plus volumineux. |
| `enable_safety_checker` |  | boolean | no | `false` |  | Activation du vérificateur de sécurité; true active la vérification. |
| `tile_width` |  | integer | no | `4096` | 128 – 4,096 | Définissez la taille de chaque tuile pendant la génération d’images. |
| `tile_height` |  | integer | no | `4096` | 128 – 4,096 | Définissez la taille de chaque tuile pendant la génération d’images. |
| `tile_stride_width` |  | integer | no | `2048` | 64 – 2,048 | Définissez l’espacement entre les positions successives des tuiles pendant la génération d’images. |
| `tile_stride_height` |  | integer | no | `2048` | 64 – 2,048 | Définissez l’espacement entre les positions successives des tuiles pendant la génération d’images. |
| `eta` |  | number | no | `0` | 0 – 1 | Réglage Eta utilisé lors de la génération d’images. |
| `debug_latents` |  | boolean | no | `false` |  | Enregistre les latents à des fins de débogage lorsque la valeur est true. |
| `debug_per_pass_latents` |  | boolean | no | `false` |  | Activez le débogage par passe en définissant cette valeur à true; les latents de chaque passe sont alors enregistrés. |

File parameters (`ic_light_model_background_image_url`, `ic_light_image_url`) take a public `https://` URL, a `data:` URI up to 10 MB, or the `file_url` of an upload from `POST /files`.

## Example input

Required parameters only:

```json
{
  "model_name": "stabilityai/stable-diffusion-xl-base-1.0",
  "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
}
```

A fuller example:

```json
{
  "model_name": "stabilityai/stable-diffusion-xl-base-1.0",
  "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
}
```

## Run it

Set `DOITONG_API_KEY` to a key from https://doitong.com/developers/dashboard#keys. `?wait=20` returns the finished request in the same call when it is ready within 20 seconds; otherwise poll `GET /requests/{id}` (it also accepts `?wait=`), or pass `webhook_url`.

### curl

```bash
# Run the model; wait up to 20 s for the finished result in the same call
curl -X POST "https://api.doitong.com/v1/run/lora?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model_name": "stabilityai/stable-diffusion-xl-base-1.0",
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
  }'

# Still "queued" or "running"? Poll with the id from the response:
curl "https://api.doitong.com/v1/requests/REQUEST_ID?wait=20" \
  -H "Authorization: Bearer $DOITONG_API_KEY"
```

### JavaScript

```javascript
const API = "https://api.doitong.com/v1";
const headers = {
  "Authorization": "Bearer " + process.env.DOITONG_API_KEY,
  "Content-Type": "application/json",
};

// Run the model; wait up to 20 s for the finished result in the same call
let res = await fetch(API + "/run/lora?wait=20", {
  method: "POST",
  headers,
  body: JSON.stringify({
    "model_name": "stabilityai/stable-diffusion-xl-base-1.0",
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
  }),
});
let request = await res.json();
if (!res.ok) throw new Error(request.error.code + ": " + request.error.message);

// Not finished yet: long-poll until it is
while (request.status === "queued" || request.status === "running") {
  res = await fetch(API + "/requests/" + request.id + "?wait=20", { headers });
  request = await res.json();
}
if (request.status !== "succeeded") throw new Error(JSON.stringify(request.error));
console.log(request.outputs.map((o) => o.url), request.cost.credits + " API credits ($" + request.cost.usd + ")");
```

### Python

```python
import os
import requests

API = "https://api.doitong.com/v1"
headers = {"Authorization": "Bearer " + os.environ["DOITONG_API_KEY"]}

payload = {
    "model_name": "stabilityai/stable-diffusion-xl-base-1.0",
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field",
}

# Run the model; wait up to 20 s for the finished result in the same call
r = requests.post(API + "/run/lora", params={"wait": 20}, json=payload, headers=headers)
request = r.json()
if not r.ok:
    raise RuntimeError(request["error"]["code"] + ": " + request["error"]["message"])

# Not finished yet: long-poll until it is
while request["status"] in ("queued", "running"):
    request = requests.get(API + "/requests/" + request["id"], params={"wait": 20}, headers=headers).json()
if request["status"] != "succeeded":
    raise RuntimeError(request["error"])
print([o["url"] for o in request["outputs"]], request["cost"]["credits"], "API credits", "$" + request["cost"]["usd"])
```

### MCP

The MCP server at `https://api.doitong.com/v1/mcp` exposes the tools `search_models`, `get_model`, `quote`, `run`, `get_request`, `cancel_request`, `list_requests`, `create_upload` and `get_account`. A `run` call for this model:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "run",
    "arguments": {
      "model_id": "lora",
      "input": {
        "model_name": "stabilityai/stable-diffusion-xl-base-1.0",
        "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
      },
      "wait_seconds": 20
    }
  }
}
```

## Response

Every call returns a request object. `status` is one of `queued`, `running`, `succeeded`, `failed`, `canceled`. `outputs` lists the generated files with URLs on our storage (kept forever, or 7 days with `?storage=temporary`; `storage` says which); `output` is the model's own result object with the same URLs.

```json
{
  "id": "req_8k2m4q7x1z9c3v5b6n0p2r4t",
  "object": "request",
  "model": "lora",
  "status": "succeeded",
  "created_at": "2026-10-20T12:00:00Z",
  "started_at": "2026-10-20T12:00:02Z",
  "completed_at": "2026-10-20T12:00:09Z",
  "queue_position": null,
  "cost": {
    "credits": 57,
    "usd": "0.057",
    "charged": 57,
    "refunded": 0
  },
  "input": {
    "model_name": "stabilityai/stable-diffusion-xl-base-1.0",
    "prompt": "A red fox trots through fresh snow at sunrise, soft golden light, shallow depth of field"
  },
  "output": {
    "images": [
      {
        "url": "https://content.doitong.com/dev-api/2026/10/20/req_8k2m4q7x1z9c3v5b6n0p2r4t/0-output.jpeg",
        "content_type": "image/jpeg",
        "file_name": "0-output.jpeg",
        "file_size": 1843200,
        "width": 1024,
        "height": 768
      }
    ],
    "seed": 42,
    "has_nsfw_concepts": [
      false
    ],
    "debug_latents": {
      "url": "https://content.doitong.com/dev-api/2026/10/20/req_8k2m4q7x1z9c3v5b6n0p2r4t/0-output.jpeg",
      "content_type": "image/jpeg",
      "file_name": "0-output.jpeg",
      "file_size": 1843200
    },
    "debug_per_pass_latents": {
      "url": "https://content.doitong.com/dev-api/2026/10/20/req_8k2m4q7x1z9c3v5b6n0p2r4t/0-output.jpeg",
      "content_type": "image/jpeg",
      "file_name": "0-output.jpeg",
      "file_size": 1843200
    }
  },
  "outputs": [
    {
      "type": "image",
      "url": "https://content.doitong.com/dev-api/2026/10/20/req_8k2m4q7x1z9c3v5b6n0p2r4t/0-output.jpeg",
      "content_type": "image/jpeg",
      "file_size": 1843200,
      "width": 1024,
      "height": 768,
      "stored": true
    }
  ],
  "error": null,
  "metrics": {
    "inference_seconds": 6.8
  },
  "urls": {
    "self": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t",
    "cancel": "https://api.doitong.com/v1/requests/req_8k2m4q7x1z9c3v5b6n0p2r4t/cancel"
  }
}
```

### Output fields (`output`)

| Field | Type | Description |
|---|---|---|
| `images` | array of object {url, content_type, file_name, file_size, width, height} | Informations de fichier pour les images générées. |
| `seed` | integer | Graine de génération d’image, incluant la valeur choisie aléatoirement si l’entrée n’a pas fourni de graine; sinon, elle répète la valeur fournie. |
| `has_nsfw_concepts` | array of boolean | Indique si des concepts NSFW apparaissent dans les images générées. |
| `debug_latents` | object {url, content_type, file_name, file_size} \| null | Données latentes enregistrées à des fins de débogage. |
| `debug_per_pass_latents` | object {url, content_type, file_name, file_size} \| null | Données latentes par passe enregistrées à des fins de débogage. |

## Related models

- [Stable Diffusion with LoRAs · Image to Image](https://doitong.com/developers/models/lora/image-to-image.md) (`lora/image-to-image`): $0.264 / image
- [Stable Diffusion with LoRAs · Inpaint](https://doitong.com/developers/models/lora/inpaint.md) (`lora/inpaint`): $0.184 / image
- [FLUX.1 \[dev\]](https://doitong.com/developers/models/flux/dev.md) (`flux/dev`): $0.025 / megapixel
- [FLUX.1 \[schnell\]](https://doitong.com/developers/models/flux/schnell.md) (`flux/schnell`): $0.003 / megapixel
- [FLUX.2 \[dev\]](https://doitong.com/developers/models/flux-2.md) (`flux-2`): $0.012 / megapixel
- [FLUX.2 \[pro\]](https://doitong.com/developers/models/flux-2-pro.md) (`flux-2-pro`): $0.015 / megapixel of output image
- [GPT Image 2.5 Text to Image](https://doitong.com/developers/models/openai/gpt-image-2.5/flare/text-to-image.md) (`openai/gpt-image-2.5/flare/text-to-image`): from $0.008 / image
- [Ideogram V4.5](https://doitong.com/developers/models/ideogram/v4.5.md) (`ideogram/v4.5`): from $0.03 / image

## Links

- HTML page: https://doitong.com/developers/models/lora
- All models and guides for AI agents: https://doitong.com/developers/llms.txt
- OpenAPI 3.1 with this model's typed request body: https://doitong.com/developers/openapi.json?model=lora
- Errors: https://doitong.com/developers/docs/errors
- Model details as JSON: https://api.doitong.com/v1/models/lora
