# 局部重绘（Midjourney）
> 两步流程：先发起 Vary (Region)，再补蒙版与提示词
> 第一步的任务会停在 `MODAL` 状态等待参数
> 父任务必须是放大后的单图
`POST /mj/submit/modal`
## 认证
- `Authorization` (string / 必填) — 所有接口均使用 Bearer Token 进行认证。 获取 API Key：[访问控制台](https://api.oairoute.com/keys) 创建。 请求时在请求头中添加： ```http Authorization: Bearer YOUR_OAIRoute_KEY ```
## 两步流程
| 步骤 | 端点 | 作用 |
|---|---|---|
| 1 | `POST /mj/submit/action` | 传 `Vary (Region)` 的 `customId`，任务进入 `MODAL` 状态 |
| 2 | `POST /mj/submit/modal` | 传 `taskId`、`prompt`、`maskBase64` 完成重绘 |
> **Note:** 
> 第一步本身不出图。任务停在 `MODAL` 时 `buttons` 为空，必须补第二步才会继续执行。
## 第一步：发起重绘
用 `/mj/submit/action` 触发，`customId` 取父任务里 `Vary (Region)` 那个按钮：
- `customId` (string / 必填) — `Vary (Region)` 的按钮 ID。
- `taskId` (string / 必填) — 父任务 ID，必须是放大后的单图。
- `notifyHook` (string / 可选) — 回调地址。
返回的任务 `status` 为 `MODAL`，记下它的 ID 进入第二步。
## 第二步：补参数
- `taskId` (string / 必填) — 第一步返回的任务 ID。
- `prompt` (string / 可选) — 描述重绘区域里要出现的内容。省略时沿用父任务的提示词。
- `maskBase64` (string / 必填) — 蒙版图片的 Base64，透明区域表示要重绘的部分。
- `noStorage` (boolean / 可选) — 为 `true` 时返回官方链接，默认 `false`。
## 蒙版怎么画
蒙版与底图**同尺寸**，用透明通道标记重绘范围：
| 蒙版像素 | 含义 |
|---|---|
| 透明（alpha = 0） | 这块会被重绘 |
| 不透明（alpha = 255） | 这块保持原样 |
常见做法是在 Photoshop 或 Figma 里把要改的区域擦成透明，其余保持白色不透明，导出 PNG 后转 Base64。
> **Note:** 
> 蒙版尺寸必须与底图完全一致，差一个像素都会被判为非法。用脚本生成时记得先 `resize` 到原图大小。
## 编辑技巧
**提示词描述目标状态。** 与其写「把红衣服改成蓝衣服」，不如写「人物穿蓝色外套，其余不变」。
**范围画得紧一点。** 蒙版比实际目标大一圈时，模型容易把周围一起改掉。
**多轮编辑会累积失真。** 每次编辑都重新编码，反复五次以上画质会明显下降。
## 错误码
| HTTP | 含义 |
|---|---|
| 200 | 请求已受理，看 `code` 判断是否成功 |
| 401 | Token 缺失或无效 |
| 429 | 触发限流 |
常见失败：`maskBase64` 缺失或尺寸与底图不一致；`taskId` 不是 `MODAL` 状态；父任务还是四宫格。
更多状态码与重试建议见[错误码与限流](../../../support/errors.html)，常见报错的排查步骤见[常见问题](../../../support/faq.html)。
## 使用示例
### 发起重绘
对放大后的单图执行 `Vary (Region)`，拿到一个 `MODAL` 状态的任务。
### 补蒙版完成
用第一步的任务 ID，配上提示词与蒙版 Base64，任务才开始真正执行。
**发起重绘{Start region edit}::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/mj/submit/action' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "customId": "MJ::Inpaint::1::UUID",
  "taskId": "1320098173412550"
}'
```
**发起重绘{Start region edit}::Python**
```
import requests

res = requests.post(
    "https://api.oairoute.com/mj/submit/action",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "customId": "MJ::Inpaint::1::UUID",
        "taskId": "1320098173412550",
    },
)
print(res.json())
```
**发起重绘{Start region edit}::JavaScript**
```
const res = await fetch("https://api.oairoute.com/mj/submit/action", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    customId: "MJ::Inpaint::1::UUID",
    taskId: "1320098173412550",
  }),
});
console.log(await res.json());
```
**补蒙版完成{Submit mask}::cURL**
```
curl --request POST \
  --url 'https://api.oairoute.com/mj/submit/modal' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "taskId": "1320098173412570",
  "prompt": "a red paper umbrella",
  "maskBase64": "data:image/png;base64,iVBORw0KGgo..."
}'
```
**补蒙版完成{Submit mask}::Python**
```
import base64, pathlib, requests

mask = "data:image/png;base64," + base64.b64encode(
    pathlib.Path("mask.png").read_bytes()).decode()

res = requests.post(
    "https://api.oairoute.com/mj/submit/modal",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "taskId": "1320098173412570",
        "prompt": "a red paper umbrella",
        "maskBase64": mask,
    },
)
print(res.json())
```
**补蒙版完成{Submit mask}::JavaScript**
```
import { readFileSync } from "node:fs";

const mask = "data:image/png;base64," + readFileSync("mask.png").toString("base64");
const res = await fetch("https://api.oairoute.com/mj/submit/modal", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    taskId: "1320098173412570",
    prompt: "a red paper umbrella",
    maskBase64: mask,
  }),
});
console.log(await res.json());
```
**200 发起重绘{Start region edit}**
```
{
  "code": 1,
  "description": "提交成功",
  "result": "1320098173412570"
}
```
**200 补蒙版完成{Submit mask}**
```
{
  "code": 1,
  "description": "提交成功",
  "result": "1320098173412571"
}
```
