Inpaint
Repaint a masked region of an upsampled Midjourney image (Vary Region).
POST /v2/images/midjourney/action — action: "inpaint"
Equivalent to Midjourney's Vary (Region) button: repaints only the area of an upsampled image covered by your mask, optionally guided by a new prompt. The result is a fresh 4-image grid of candidates, each of which can be upsampled again.
Request
| Parameter | Type | Required | Description |
|---|---|---|---|
parentJobId | string (uuid) | Yes | ID of the completed upsample job to act on |
action | string | Yes | "inpaint" |
mask | string (base64) | Yes | Black-and-white mask image, same dimensions as the parent image. White = repaint, black = preserve. An optional data:image/...;base64, prefix is accepted and stripped. Max ~8 MB decoded. |
prompt | string | No | What to render in the repainted region (max 2000 chars). Omit to let Midjourney re-imagine the region from the original prompt. |
webhookUrl | string | No | HTTPS URL that receives a JSON POST when the job reaches a subscribed event — see Webhooks for payload formats |
webhookEvents | string[] | No | Events to be notified about: "progress", "completed", "failed". Defaults to ["completed", "failed"] when webhookUrl is set |
The parent must be a completed upsample action job — inpainting a 4-up
grid directly returns 400; upsample one image first.
The mask is uploaded to our CDN for processing and deleted as soon as the
job completes or fails — it is never stored with the job, and it is not
echoed back in the job's input.
Credits
16 credits per inpaint.
Example result
Once the job is COMPLETED, the result object on
GET /v2/jobs/:id contains a new 4-image grid:
{
"images": [
"https://cdn2.apiframe.ai/images/b2c3d4e5-...-1.png",
"https://cdn2.apiframe.ai/images/b2c3d4e5-...-2.png",
"https://cdn2.apiframe.ai/images/b2c3d4e5-...-3.png",
"https://cdn2.apiframe.ai/images/b2c3d4e5-...-4.png"
],
"gridUrl": "https://cdn2.apiframe.ai/images/b2c3d4e5-...-grid.png"
}Code examples
curl -X POST https://api.apiframe.ai/v2/images/midjourney/action \
-H "X-API-Key: afk_your_api_key_here" \
-H "Content-Type: application/json" \
-d "{
\"parentJobId\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",
\"action\": \"inpaint\",
\"mask\": \"$(base64 -i mask.png)\",
\"prompt\": \"a red hot air balloon\"
}"import base64
import requests
with open("mask.png", "rb") as f:
mask = base64.b64encode(f.read()).decode()
response = requests.post(
"https://api.apiframe.ai/v2/images/midjourney/action",
headers={
"X-API-Key": "afk_your_api_key_here",
"Content-Type": "application/json",
},
json={
"parentJobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"action": "inpaint",
"mask": mask,
"prompt": "a red hot air balloon",
},
)
print(response.json())import { readFile } from "node:fs/promises";
const mask = (await readFile("mask.png")).toString("base64");
const response = await fetch("https://api.apiframe.ai/v2/images/midjourney/action", {
method: "POST",
headers: {
"X-API-Key": "afk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
parentJobId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
action: "inpaint",
mask,
prompt: "a red hot air balloon",
}),
});
console.log(await response.json());maskBytes, _ := os.ReadFile("mask.png")
mask := base64.StdEncoding.EncodeToString(maskBytes)
payload, _ := json.Marshal(map[string]string{
"parentJobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"action": "inpaint",
"mask": mask,
"prompt": "a red hot air balloon",
})
req, _ := http.NewRequest("POST", "https://api.apiframe.ai/v2/images/midjourney/action",
bytes.NewReader(payload))
req.Header.Set("X-API-Key", "afk_your_api_key_here")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)Try it
/v2/images/midjourney/actionTry it