# Recall Parameters API

## Overview

:::tip
For the Video panel, see the [Video Recall API](/development/guides/video-recall-api/).
:::

The Recall Parameters API is a REST endpoint on the InvokeAI backend that
lets external processes set recallable generation parameters on the
frontend. Supported parameters include:

- Core text and numeric parameters (prompts, model, steps, CFG, dimensions, seed, ...)
- LoRAs
- Control Layers (ControlNet, T2I Adapter, Control LoRA) with optional control images
- IP Adapters and FLUX Redux reference images with optional images
- Model-free reference images (FLUX.2 Klein, FLUX Kontext, Qwen Image Edit)

When parameters are updated via the API, the backend stores them in client
state persistence for the target queue and broadcasts a `recall_parameters_updated`
WebSocket event. Any frontend client subscribed to that queue applies the
new values immediately — no manual reload required.

Typical use cases:

- An external image browser that wants to "recall" or "remix" the
  generation parameters saved into a PNG's metadata.
- A script that pre-populates parameters before the user runs generation.
- Automated testing or batch workflows that want to reuse existing model
  and adapter configurations.

## How It Works

1. **API request** — your client POSTs a JSON body of parameters to
   `/api/v1/recall/{queue_id}`.
2. **Storage** — non-null parameters are stored under
   `recall_*` keys in the client state persistence service, scoped to the
   given `queue_id`.
3. **Resolution** — models are resolved from human-readable names to the
   internal model keys used by the frontend, and image filenames are
   validated against `{INVOKEAI_ROOT}/outputs/images`.
4. **Broadcast** — a `recall_parameters_updated` event is emitted, once, to
   the calling user's room and the administrators' room. webv2 ignores events
   addressed to another user; the legacy frontend applies them, so an
   administrator using it also receives other users' recalls.
5. **Frontend update** — the calling user's connected clients
   apply the update to their generation settings, so UI fields, LoRAs,
   reference images and (in the legacy frontend) control layers populate
   immediately. See [Frontend behavior](#frontend-behavior) for what each
   frontend applies.

## Endpoint

**Base URL:** `http://localhost:9090/api/v1/recall/{queue_id}`

The queue id is usually `default`.

### POST — Update Recall Parameters

Updates recallable parameters for the given `queue_id`.

```http
POST /api/v1/recall/{queue_id}
Content-Type: application/json

{
  "positive_prompt": "a beautiful landscape",
  "negative_prompt": "blurry, low quality",
  "model": "sd-1.5",
  "steps": 20,
  "cfg_scale": 7.5,
  "width": 512,
  "height": 512,
  "seed": 12345
}
```

All parameters are optional — only send the fields you want to update.

#### Query parameters

The POST endpoint accepts two optional boolean query parameters that control
how reference images are merged into the frontend state:

| Parameter | Default | Description |
|-----------|---------|-------------|
| `strict` | `false` | When `true`, parameters **not** included in the request body are reset to their defaults (cleared on the frontend). When `false`, only the parameters you send are updated and everything else is left as-is. |
| `append` | `false` | When `true`, recalled reference images (`ip_adapters` and `reference_images`) are **appended** to the frontend's existing reference-image list instead of replacing it. When `false` (or omitted), the recalled reference images **replace** the existing list. |

`strict` and `append` are mutually exclusive — `strict` clears omitted
parameters while `append` preserves and extends the existing list, so the two
cannot be combined. Sending `?strict=true&append=true` returns
**400 Bad Request**:

```json
{
  "detail": "The 'strict' and 'append' query parameters are mutually exclusive"
}
```

`append` only affects the reference-image collections (`ip_adapters` and
`reference_images`). All other parameters (prompts, model, LoRAs, control
layers, etc.) are updated the same way regardless of the flag.

### GET — Retrieve Recall Parameters

```http
GET /api/v1/recall/{queue_id}
```

```json
{
  "status": "success",
  "queue_id": "queue_123",
  "note": "Use the frontend to access stored recall parameters, or set specific parameters using POST"
}
```

## Request Schema

### Core parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `positive_prompt` | string | Positive prompt text |
| `negative_prompt` | string | Negative prompt text |
| `model` | string | Main model name/identifier |
| `refiner_model` | string | Refiner model name/identifier |
| `vae_model` | string | VAE model name/identifier |
| `scheduler` | string | Scheduler name |
| `steps` | integer | Number of generation steps (≥1) |
| `refiner_steps` | integer | Number of refiner steps (≥0) |
| `cfg_scale` | number | CFG scale for guidance |
| `cfg_rescale_multiplier` | number | CFG rescale multiplier |
| `refiner_cfg_scale` | number | Refiner CFG scale |
| `guidance` | number | Guidance scale |
| `width` | integer | Image width in pixels (≥64) |
| `height` | integer | Image height in pixels (≥64) |
| `seed` | integer | Random seed (≥0) |
| `denoise_strength` | number | Denoising strength (0–1) |
| `refiner_denoise_start` | number | Refiner denoising start (0–1) |
| `clip_skip` | integer | CLIP skip layers (≥0) |
| `seamless_x` | boolean | Enable seamless X tiling |
| `seamless_y` | boolean | Enable seamless Y tiling |
| `refiner_positive_aesthetic_score` | number | Refiner positive aesthetic score |
| `refiner_negative_aesthetic_score` | number | Refiner negative aesthetic score |

### Collection parameters

```typescript
{
  // LoRAs
  loras?: Array<{
    model_name: string;     // LoRA model name
    weight?: number;        // Default: 0.75, Range: -10 to 10
    is_enabled?: boolean;   // Default: true
  }>;

  // Control Layers (ControlNet, T2I Adapter, Control LoRA)
  control_layers?: Array<{
    model_name: string;            // Control adapter model name
    image_name?: string;           // Optional image filename from outputs/images
    weight?: number;               // Default: 1.0, Range: -1 to 2
    begin_step_percent?: number;   // Default: 0.0, Range: 0 to 1
    end_step_percent?: number;     // Default: 1.0, Range: 0 to 1
    control_mode?: "balanced" | "more_prompt" | "more_control"; // ControlNet only
  }>;

  // IP Adapters (includes FLUX Redux)
  ip_adapters?: Array<{
    model_name: string;            // IP Adapter / FLUX Redux model name
    image_name?: string;           // Optional reference image filename from outputs/images
    weight?: number;               // Default: 1.0, Range: -1 to 2
    begin_step_percent?: number;   // Default: 0.0, Range: 0 to 1
    end_step_percent?: number;     // Default: 1.0, Range: 0 to 1
    method?: "full" | "style" | "composition"; // Default: "full"
    image_influence?: "lowest" | "low" | "medium" | "high" | "highest"; // FLUX Redux only
  }>;

  // Model-free reference images (FLUX.2 Klein, FLUX Kontext, Qwen Image Edit)
  reference_images?: Array<{
    image_name: string;            // Reference image filename from outputs/images
  }>;
}
```

## Model Name Resolution

The backend resolves model names to their internal keys:

1. **Main models** — resolved from the name to the model key.
2. **LoRAs** — searched in the LoRA model database.
3. **Control adapters** — tried in order: ControlNet → T2I Adapter → Control LoRA.
4. **IP Adapters** — searched in the IP Adapter database; falls back to FLUX Redux.

Models that cannot be resolved are skipped with a warning in the logs —
the rest of the parameters are still applied.

## Image File Handling

When an `image_name` is supplied, the backend:

1. Resolves `{INVOKEAI_ROOT}/outputs/images/{image_name}` via the image
   files service (which also validates the path).
2. Opens the image to extract width/height.
3. Includes the image metadata in the event sent to the frontend.
4. Logs whether the image was found.

Images must be referenced by their filename as it appears in the
outputs/images directory:

- ✅ `"image_name": "example.png"`
- ✅ `"image_name": "my_control_image_20240110.jpg"`
- ❌ `"image_name": "outputs/images/example.png"` (no prefix)
- ❌ `"image_name": "/full/path/to/example.png"` (no absolute paths)

Missing images are logged as warnings but **do not** fail the request —
remaining parameters are still applied.

## Feature Details

### LoRAs

- Existing LoRAs are cleared before new ones are added.
- Each LoRA's model config is fetched and applied with the specified weight.
- LoRAs appear in the LoRA selector panel.

### Control Layers

- Fully supported with optional images from `outputs/images`.
- Configuration includes model, weights, step percentages, control mode,
  and an image reference.
- Image availability is logged in the frontend console.

### IP Adapters / FLUX Redux

- Reference images loaded from `outputs/images` are validated and passed
  through.
- Configuration includes model, weights, step percentages, method, and an
  image reference.
- FLUX Redux uses `image_influence` instead of a numeric weight.

### Model-free reference images

Used by architectures that consume a reference image directly, with no
separate adapter model:

- **FLUX.2 Klein** — built-in reference image support.
- **FLUX Kontext** — reference image associated with the main model.
- **Qwen Image Edit** — reference image associated with the main model.
- **Qwen-Image-2.1** — reference images read by its own encoder, on the Diffusers model only.

Because there is no adapter model to resolve, these entries carry only
`image_name`. When the frontend receives them, it picks the appropriate
config flavor (`flux2_reference_image`, `flux_kontext_reference_image`,
`qwen_image_reference_image` or `qwen_image_2_1_reference_image`) based on
the currently-selected main model, matching the behavior of a manual drag-and-drop.

## Usage Examples

### cURL

```bash
# Core parameters
curl -X POST http://localhost:9090/api/v1/recall/default \
  -H "Content-Type: application/json" \
  -d '{
    "positive_prompt": "a cyberpunk city at night",
    "negative_prompt": "dark, unclear",
    "model": "sd-1.5",
    "steps": 30
  }'

# Just the seed
curl -X POST http://localhost:9090/api/v1/recall/default \
  -H "Content-Type: application/json" \
  -d '{"seed": 99999}'
```

### LoRAs only

```bash
curl -X POST http://localhost:9090/api/v1/recall/default \
  -H "Content-Type: application/json" \
  -d '{
    "loras": [
      {"model_name": "add-detail-xl", "weight": 0.8, "is_enabled": true},
      {"model_name": "sd_xl_offset_example-lora_1.0", "weight": 0.5}
    ]
  }'
```

### Control layers with an image

```bash
curl -X POST http://localhost:9090/api/v1/recall/default \
  -H "Content-Type: application/json" \
  -d '{
    "control_layers": [
      {
        "model_name": "controlnet-canny-sdxl-1.0",
        "image_name": "my_control_image.png",
        "weight": 0.75,
        "begin_step_percent": 0.0,
        "end_step_percent": 0.8,
        "control_mode": "balanced"
      }
    ]
  }'
```

### IP adapters with a reference image

```bash
curl -X POST http://localhost:9090/api/v1/recall/default \
  -H "Content-Type: application/json" \
  -d '{
    "ip_adapters": [
      {
        "model_name": "ip-adapter-plus-face_sd15",
        "image_name": "reference_face.png",
        "weight": 0.7,
        "method": "composition"
      }
    ]
  }'
```

### Appending reference images (append mode)

By default, recalled reference images **replace** whatever the frontend
already has. Pass `?append=true` to **add** the recalled `ip_adapters` and
`reference_images` to the existing list instead:

```bash
# Add a reference image without clearing the ones already on the frontend
curl -X POST 'http://localhost:9090/api/v1/recall/default?append=true' \
  -H "Content-Type: application/json" \
  -d '{
    "reference_images": [
      {"image_name": "extra_reference.png"}
    ]
  }'
```

Combining `append=true` with `strict=true` is invalid and returns
**400 Bad Request** (see [Query parameters](#query-parameters)).

### Model-free reference images (FLUX.2 Klein / FLUX Kontext / Qwen Image Edit)

```bash
curl -X POST http://localhost:9090/api/v1/recall/default \
  -H "Content-Type: application/json" \
  -d '{
    "model": "FLUX.2 Klein",
    "reference_images": [
      {"image_name": "style_reference.png"}
    ]
  }'
```

### Complete configuration

```bash
curl -X POST http://localhost:9090/api/v1/recall/default \
  -H "Content-Type: application/json" \
  -d '{
    "positive_prompt": "masterpiece, detailed photo with specific style",
    "negative_prompt": "blurry, low quality",
    "model": "FLUX Schnell",
    "steps": 25,
    "cfg_scale": 8.0,
    "width": 1024,
    "height": 768,
    "seed": 42,
    "loras": [
      {"model_name": "add-detail-xl", "weight": 0.6}
    ],
    "control_layers": [
      {
        "model_name": "controlnet-depth-sdxl-1.0",
        "image_name": "depth_map.png",
        "weight": 1.0,
        "end_step_percent": 0.7
      }
    ],
    "ip_adapters": [
      {
        "model_name": "ip-adapter-plus-face_sd15",
        "image_name": "style_reference.png",
        "weight": 0.5,
        "method": "style"
      }
    ]
  }'
```

### Python

```python
import requests

API_URL = "http://localhost:9090/api/v1/recall/default"

params = {
    "positive_prompt": "a serene forest",
    "negative_prompt": "people, buildings",
    "steps": 25,
    "cfg_scale": 7.0,
    "seed": 42,
}

response = requests.post(API_URL, json=params)
result = response.json()
print(f"Status: {result['status']}")
print(f"Updated {result['updated_count']} parameters")
```

### JavaScript

```javascript
const API_URL = 'http://localhost:9090/api/v1/recall/default';

fetch(API_URL, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    positive_prompt: 'a beautiful sunset',
    steps: 20,
    width: 768,
    height: 768,
    seed: 12345,
  }),
})
  .then((res) => res.json())
  .then((data) => console.log(data));
```

## Response Format

```json
{
  "status": "success",
  "queue_id": "default",
  "updated_count": 15,
  "parameters": {
    "positive_prompt": "...",
    "steps": 25,
    "loras": [
      {"model_key": "abc123...", "weight": 0.6, "is_enabled": true}
    ],
    "control_layers": [
      {
        "model_key": "controlnet-xyz...",
        "weight": 1.0,
        "image": {"image_name": "depth_map.png", "width": 1024, "height": 768}
      }
    ],
    "ip_adapters": [
      {
        "model_key": "ip-adapter-xyz...",
        "weight": 0.5,
        "image": {"image_name": "style_reference.png", "width": 1024, "height": 1024}
      }
    ],
    "reference_images": [
      {"image": {"image_name": "style_reference.png", "width": 1024, "height": 1024}}
    ]
  }
}
```

## WebSocket Events

Parameter updates emit a `recall_parameters_updated` event to the calling
user's room and the administrators' room. The calling user's connected frontend
clients automatically:

1. Apply standard parameters (prompts, steps, dimensions, etc.).
2. Load and add LoRAs to the LoRA list.
3. Apply control-layer configurations (legacy frontend only).
4. Merge the recalled reference images — IP Adapter / FLUX Redux entries and
   model-free reference images both feed the same reference-image list, using
   the config flavor that matches the currently-selected main model. By
   default this **replaces** the existing list; with `append=true` it is
   **added** to whatever is already there (see
   [Query parameters](#query-parameters)).

## Frontend behavior

### webv2 (default UI)

The update lands in the **Generate** panel of the project that was active when
the event arrived, and shows a notification summarizing how many fields were
applied. If that project is still on screen, the Generate widget is brought to the
front the same way the [Video Recall API](/development/guides/video-recall-api/#frontend-behavior)
brings the Video widget forward: its tab is selected, a floating window is raised
(and unrolled if shaded),
and nothing moves while the user is typing. Parameters the Generate panel has no home for, and entries that could
not be resolved, are left out and named in a second notification so the caller
can tell what did not land. The editor must be open: events that arrive while
the user is on the Launchpad are dropped even though the request returns 200.
In multi-user mode only the requesting user's own sessions apply the update;
administrators' sessions ignore other users' recalls.

| Parameter                                                                                              | webv2 behavior                                                                                                                          |
| ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `positive_prompt`, `negative_prompt`, `seed`, `steps`, `cfg_scale`, `cfg_rescale_multiplier`, `scheduler`, `width`, `height`, `clip_skip`, `seamless_x`, `seamless_y` | Applied. A recalled `seed` also turns off seed randomization; `clip_skip` applies only to model families that expose it (SD 1.x / 2.x). |
| `model`                                                                                                | Switches the Generate model. Changing model applies that model's defaults (steps, CFG, CFG rescale, scheduler, size, VAE precision) and runs the same compatibility pass as the model selector (incompatible LoRAs, VAE and component selections are cleared; reference images are retargeted) before the explicit values in the same request are applied. |
| `vae_model`                                                                                            | Matched by key or name and applied when compatible with the effective model.                                                             |
| `guidance`                                                                                             | Applied as the CFG/guidance value for FLUX, FLUX.2, Qwen Image and Z-Image models when `cfg_scale` is not also given; reported as not applied otherwise. |
| `loras`                                                                                                | Replaces the LoRA list. Entries that are not installed or not compatible with the effective model are dropped and reported.              |
| `ip_adapters`, `reference_images`                                                                      | Feed the reference image list, retargeted to the effective model's reference-image type. Files no longer in the gallery are dropped and reported; if none of the recalled images exist the project keeps its current list. `append=true` adds behind the existing entries without re-checking them; the model's reference-image limit is enforced (newest entries are dropped first). |
| `control_layers`                                                                                       | **Not applied.** Control layers live on the Canvas in webv2, not in the Generate panel.                                                  |
| `refiner_model`, `refiner_steps`, `refiner_cfg_scale`, `refiner_denoise_start`, `refiner_positive_aesthetic_score`, `refiner_negative_aesthetic_score` | Applied for an effective SDXL main model. The refiner must be an installed `sdxl-refiner` main model, matched by key or name. Steps must be a whole number ≥1, CFG ≥1, denoising start 0–1, and aesthetic scores 1–10. |
| `denoise_strength`                                                                                    | **Not applied.** The Generate panel has no image-to-image strength setting.                                                              |

A refiner identifier that reaches the frontend but is missing, invalid or
incompatible is reported; after any main-model compatibility transition, the
current refiner selection and tuning are kept together, and the request's
refiner tuning is skipped. Invalid tuning values
are reported and leave their current values unchanged. If a requested main-model
key is unavailable in the frontend catalog, its refiner selection and tuning are
also skipped. This differs from an unresolved main-model name dropped by the
backend: as described in [Model Name Resolution](#model-name-resolution), the
remaining parameters then apply to the current model.

In `strict` mode, omitted scalar parameters reset to the effective model's
defaults (empty prompts, randomized seed, default steps/CFG/scheduler/size),
and omitted lists clear. An omitted `model` keeps the current model. An omitted
`refiner_model` clears the refiner slot, and the five omitted refiner tuning
fields listed above reset to their defaults, unless a failed model lookup
prevents the refiner update. The refiner scheduler is unchanged; this API has no
`refiner_scheduler` parameter.

Events are applied in arrival order; an `append` request that overlaps a
still-loading replace sees the replaced list. The handler is loaded on the
first event of a session; if that load fails, the event is dropped, an error is
recorded in the notification center, and the next event retries the load.

### Legacy web

The legacy frontend applies prompts, steps, CFG, size, seed, model, LoRAs,
control layers and reference images to its Redux store. It ignores `null`
scalar values, so `strict` mode only clears the list-typed parameters there.

## Error Handling

- **400 Bad Request** — invalid parameters or parameter values, or the
  mutually exclusive `strict=true&append=true` combination (see
  [Query parameters](#query-parameters)).
- **500 Internal Server Error** — server-side storage or retrieval failure.

Errors include detailed messages. Missing images and unresolved model
names are **not** errors — they are logged and the remaining parameters
are still applied.

## Logging

### Backend

```
INFO: Resolved ControlNet model name 'controlnet-canny-sdxl-1.0' to key 'controlnet-xyz...'
INFO: Found image file: depth_map.png (1024x768)
INFO: Updated 12 recall parameters for queue default
INFO: Resolved 1 LoRA(s)
INFO: Resolved 1 control layer(s)
INFO: Resolved 1 IP adapter(s)
INFO: Resolved 1 reference image(s)
```

### Frontend

webv2 reports each applied update, and any parameters it could not apply, in
the notification center; failures are recorded as errors there as well.

In the legacy frontend, set `localStorage.ROARR_FILTER = 'debug'` in the
browser to see all debug messages under the `events` namespace.

```
INFO: Applied 5 recall parameters to store
INFO: Applied 2 reference image(s) (IP adapters + model-free), replacing existing list
DEBUG: Built IP adapter ref image state: ip-adapter-xyz... (weight: 0.7)
DEBUG: IP adapter image: outputs/images/depth_map.png (1024x768)
```

## Implementation Details

- Parameters are stored in the client state persistence service under
  `recall_*` keys, scoped to the `queue_id`.
- Numeric validation runs at the FastAPI layer (e.g. `steps ≥ 1`, `width ≥ 64`).
- Only non-null parameters are processed, stored, and broadcast.
- Model-key resolution runs **after** the raw parameters are stored, so
  an unresolvable model name simply drops out of the broadcast but does
  not corrupt the persisted state.
- The broadcast payload contains resolved model keys and image metadata
  (width/height) so the frontend can populate its store without extra
  round-trips.

## Troubleshooting

### Image not found

If you see "Image file not found" in the logs:

1. Verify the filename matches exactly (case-sensitive).
2. Ensure the image is in `{INVOKEAI_ROOT}/outputs/images/`.
3. Check that the filename does not include the `outputs/images/` prefix.

### Model not found

If you see "Could not find model":

1. Verify the model name matches exactly (case-sensitive).
2. Ensure the model is installed.
3. Check the name via the Models Manager panel.

### Event not received

1. Check the browser console for socket connection errors.
2. Verify the `queue_id` matches the frontend's queue (usually `default`).
3. Check backend logs for event emission errors.

## Limitations

- **Model availability** — models referenced in the payload must be installed.
- **Image availability** — images must exist in `outputs/images`; remote
  URLs are not supported.
- **Canvas auto-layer creation** — control layers and IP adapters with
  images populate the recall state, but creating a canvas layer from
  them still happens through the UI.

## Future enhancements

Potential improvements not yet implemented:

1. Auto-create canvas layers from control-layer images in the payload.
2. Auto-create reference-image layers from IP Adapter images in the payload.
3. Support remote image URLs in addition to local `outputs/images` filenames.
4. Image upload capability (accept base64 or file upload directly via the API).
5. Batch operations that target multiple `queue_id`s in a single request.