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

# Edit an image with an instruction

> Use a written instruction to edit one to four reference images on hosted diffusion models. Swap a background, restyle, or compose.

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{
__html: JSON.stringify({
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "@id": "https://rendobar.com/docs/jobs/image-edit/#article",
  "headline": "Edit an image with an instruction",
  "description": "Use a written instruction to edit one to four reference images on hosted diffusion models. Swap a background, restyle, or compose.",
  "datePublished": "2026-07-26",
  "dateModified": "2026-07-31",
  "author": { "@type": "Organization", "@id": "https://rendobar.com/#organization" },
  "publisher": { "@type": "Organization", "@id": "https://rendobar.com/#organization" },
  "isPartOf": { "@id": "https://rendobar.com/#website" }
})
}}
/>

`image.edit` takes one to four reference images and a written instruction, then produces a new image on a hosted diffusion model. No masks and no coordinates. You describe the change in plain language and the model applies it. The result is a webp file returned as a signed URL.

This is one product in [Rendobar's Generation API](/docs/concepts/generation).

## Edit an image

Reference images go in `inputs.images` as an array of URLs. The instruction goes in `params.prompt`.

<CodeGroup>
  ```ts SDK theme={null}
  import { createClient, outputUrl } from "@rendobar/sdk";

  const client = createClient({ apiKey: "rb_YOUR_KEY" });

  const job = await client.jobs.run({
    type: "image.edit",
    inputs: { images: ["https://cdn.rendobar.com/assets/examples/photo.jpg"] },
    params: {
      prompt: "Place the product on a pale grey studio backdrop with a soft shadow underneath",
    },
  });

  console.log(outputUrl(job)); // signed URL to the edited webp
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.rendobar.com/jobs" \
    -H "Authorization: Bearer rb_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "image.edit",
      "inputs": { "images": ["https://cdn.rendobar.com/assets/examples/photo.jpg"] },
      "params": { "prompt": "Place the product on a pale grey studio backdrop with a soft shadow underneath" }
    }'
  # Returns { "data": { "id": "job_...", "status": "waiting" } }.
  # Poll GET /jobs/{id} until "status": "complete".
  ```

  ```python Python theme={null}
  import requests, time

  base = "https://api.rendobar.com"
  headers = {"Authorization": "Bearer rb_YOUR_KEY"}

  job = requests.post(
      f"{base}/jobs",
      headers=headers,
      json={
          "type": "image.edit",
          "inputs": {"images": ["https://cdn.rendobar.com/assets/examples/photo.jpg"]},
          "params": {"prompt": "Place the product on a pale grey studio backdrop with a soft shadow underneath"},
      },
  ).json()["data"]

  while job["status"] not in ("complete", "failed", "cancelled"):
      time.sleep(1)
      job = requests.get(f"{base}/jobs/{job['id']}", headers=headers).json()["data"]

  print(job["output"]["file"]["url"])  # the edited webp
  ```
</CodeGroup>

Each URL can be a public link or an [uploaded asset's](/docs/sdk#uploads) content URL. The output size follows the first reference image unless you set `width` and `height`.

## Reference images

`inputs.images` accepts one to four URLs. The per-model cap is tighter than the schema ceiling, so a request that clears the schema can still be rejected against the resolved model.

| Model                                       | Reference images |
| ------------------------------------------- | ---------------- |
| `flux-2-klein-4b` (economy)                 | Up to 4          |
| `qwen-image-edit-2511-lightning` (standard) | Up to 3          |
| `qwen-image-edit-2511` (premium)            | Up to 3          |

Passing more images than the resolved model accepts returns `VALIDATION_ERROR` before anything is billed. Multiple references let you compose a scene, for example a product from one image on a background from another.

## Tiers and models

Set `model` to a tier alias or pin an exact model id. Omit it and you get the `economy` tier. Aliases can be re-pointed as the catalog grows, so pin an exact id when you need a result to stay stable.

| Tier                | Model                            | Price  | Reference images | Controls when pinned                        |
| ------------------- | -------------------------------- | ------ | ---------------- | ------------------------------------------- |
| `economy` (default) | `flux-2-klein-4b`                | `$`    | Up to 4          | prompt only                                 |
| `standard`          | `qwen-image-edit-2511-lightning` | `$$$`  | Up to 3          | steps (4 to 8)                              |
| `premium`           | `qwen-image-edit-2511`           | `$$$$` | Up to 3          | steps (20 to 40), guidance, negative prompt |

Every `image.edit` model is reachable through a tier. There is no pin-only model on this job type today.

<Info>
  `Price` is the model's `priceTier`, a relative comparison from `$` to `$$$$`. It is not a per-image charge. Jobs bill on the compute they actually use, cost-plus. See [credits and billing](/docs/concepts/credits).
</Info>

## Model-specific controls

Tier aliases accept the base fields only. To use `steps`, `guidance`, or `negativePrompt`, pin an exact model id. Only `qwen-image-edit-2511` accepts `guidance` and `negativePrompt`. `flux-2-klein-4b` fixes its own step count and exposes the base fields only.

<CodeGroup>
  ```ts SDK theme={null}
  await client.jobs.run({
    type: "image.edit",
    inputs: { images: ["https://cdn.rendobar.com/assets/examples/photo.jpg"] },
    params: {
      prompt: "Turn the daytime sky into a clear starry night",
      model: "qwen-image-edit-2511",
      steps: 30,
      guidance: 4,
      negativePrompt: "artifacts, halos",
    },
  });
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.rendobar.com/jobs" \
    -H "Authorization: Bearer rb_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "image.edit",
      "inputs": { "images": ["https://cdn.rendobar.com/assets/examples/photo.jpg"] },
      "params": {
        "prompt": "Turn the daytime sky into a clear starry night",
        "model": "qwen-image-edit-2511",
        "steps": 30,
        "guidance": 4,
        "negativePrompt": "artifacts, halos"
      }
    }'
  ```

  ```python Python theme={null}
  requests.post(
      f"{base}/jobs",
      headers=headers,
      json={
          "type": "image.edit",
          "inputs": {"images": ["https://cdn.rendobar.com/assets/examples/photo.jpg"]},
          "params": {
              "prompt": "Turn the daytime sky into a clear starry night",
              "model": "qwen-image-edit-2511",
              "steps": 30,
              "guidance": 4,
              "negativePrompt": "artifacts, halos",
          },
      },
  )
  ```
</CodeGroup>

## The output

A completed job carries a single webp file in `output.file`, typed `image`. `output.data` is `null`.

```json theme={null}
{
  "data": null,
  "file": {
    "url": "https://api.rendobar.com/dl/job_abc123?token=<token>",
    "path": "output.webp",
    "type": "image",
    "size": 498000,
    "meta": { "format": "webp", "width": 1024, "height": 1024 }
  },
  "files": [
    { "url": "https://api.rendobar.com/dl/job_abc123?token=<token>", "path": "output.webp", "type": "image", "size": 498000, "meta": { "format": "webp", "width": 1024, "height": 1024 } }
  ],
  "expiresAt": 1735689600000
}
```

The full [output shape](/docs/concepts/job#the-output) is the same for every job type.

## Watch it render

An edit job emits `job.preview` events while the model denoises, each carrying a small webp frame. Subscribe with the SDK to show the edit resolving instead of a spinner.

```ts theme={null}
const sub = client.realtime.subscribeJob(created.id, {
  onPreview: (e) => setPreview(`data:image/webp;base64,${e.data}`),
  onComplete: (job) => sub.unsubscribe(),
});
```

Previews are decoration and never hold up a job. The `standard` tier finishes in four steps, so it usually completes before a frame is worth showing. See [the field reference](/docs/jobs/image-generate#watch-it-render) on the generate page.

## Parameters

<ParamField body="inputs.images" type="string[]" required>
  One to four reference image URLs. A public link or an uploaded asset's content URL. The per-model cap applies.
</ParamField>

<ParamField body="prompt" type="string" required>
  The change to make, in plain language. No masks, no coordinates. Up to 4000 characters.
</ParamField>

<ParamField body="model" type="string" default="economy">
  A tier alias (`economy`, `standard`, `premium`) or an exact model id. A tier lets the platform pick the model. A pinned id unlocks that model's own controls.
</ParamField>

<ParamField body="width" type="integer">
  Requested output width in pixels, up to 4096. Defaults to the first reference image. Snapped to what the model can render.
</ParamField>

<ParamField body="height" type="integer">
  Requested output height in pixels, up to 4096. Defaults to the first reference image.
</ParamField>

<ParamField body="seed" type="integer">
  A fixed seed makes the result reproducible. Omit it for a fresh result each time.
</ParamField>

<ParamField body="enhancePrompt" type="boolean">
  Rewrite the instruction for the model before editing. Off by default on every model in the catalog today. The default is per model (`enhanceDefault` in [`GET /models`](#discover-models)), so omit it to keep whatever the model ships with.
</ParamField>

<ParamField body="steps" type="integer">
  Denoise steps. More steps means more detail and more time. Requires a pinned model that exposes steps. The accepted range depends on the model.
</ParamField>

<ParamField body="guidance" type="number">
  How strictly to follow the instruction. Higher is stricter. Range 1 to 10. Requires `qwen-image-edit-2511`.
</ParamField>

<ParamField body="negativePrompt" type="string">
  What to keep out of the edited image. Up to 1000 characters. Requires `qwen-image-edit-2511`.
</ParamField>

## Discover models

`GET /models?job=image.edit` lists the edit models with their reference-image caps, controls, and relative price. The [response shape](/docs/jobs/image-generate#discover-models) is the same for both generation job types.

```bash theme={null}
curl "https://api.rendobar.com/models?job=image.edit" \
  -H "Authorization: Bearer rb_YOUR_KEY"
```

## See also

* [Generation API](/docs/concepts/generation): the modalities and the shared model catalog
* [Image generate](/docs/jobs/image-generate): make an image from a text prompt
* [Job output](/docs/concepts/job#the-output): the output shape every job returns
* [SDK](/docs/sdk): `jobs.run`, uploads, and reading the output
* [Webhooks](/docs/guides/webhooks): receive `job.completed` instead of polling
