AI Agent API Reference (OpenAPI)
This document is a minimal, self-contained reference written for AI Agents (Claude Code / OpenClaw / custom agents).
All endpoints return a unified envelope:
{ "code": 0, "message": "success", "data": {}, "requestId": "req_xxx" }
Error handling: treat a response as failed only when code exists and is not 0. If code is null or omitted, do NOT treat it as an error.
Field naming: many endpoints accept both camelCase and snake_case inside data. Parse with fallbacks:
- Task ID:
jobId/job_id/taskId/task_id - Upload URL:
signedUrl/signed_url - Result image URL:
imageUrl/image_url; for result lists preferdata.results(each item usually hasurl), do not rely onresult.imagesonly
Authentication
- Header (either one):
Authorization: Bearer <your API key>X-API-Key: <your API key>
Getting an API key: sign in on mopng.cn → open /agent → create an Agent API Key (format ak_...). Keep the key only in your own private configuration; never commit it to a repository.
Choosing an integration path
| Path | Base URL | When to use |
|---|---|---|
| MoPNG Agent negotiation API (recommended) | https://agent-api.mopng.cn | Let the server-side agent pick tools, models, and orchestrate the workflow; your agent only states intent, reviews the plan, and collects results |
| Direct tool API (rest of this page) | https://mo-api.mopng.cn | You already know exactly which tool and parameters to call, and want step-by-step control |
Both paths share the same API key.
Base paths
- Direct tool API:
/api/v1/open(mo-api.mopng.cn) - MoPNG Agent negotiation API:
/api/v1/open/agent(agent-api.mopng.cn)
MoPNG Agent negotiation API (recommended)
Best for multi-step image workflows (text-to-image, image-to-image, cutout, background replacement, outpainting, upscaling, and combinations). Flow: submit Brief → server returns Plan → (optional revision rounds) → approve → poll exec for results.
1. List available models (optional)
GET https://agent-api.mopng.cn/api/v1/open/agent/models
Returns the models currently supported for text-to-image generation.
2. Create a session (submit a Brief)
POST https://agent-api.mopng.cn/api/v1/open/agent/session
{
"version": "1.0",
"user_intent": "Replace the product background with pure white, keep the shadow natural",
"spec": {
"goal": "white-background product photo",
"subject": {
"type": "image",
"reference": "https://example.com/product.png",
"references": ["https://example.com/product.png"]
},
"format": "png"
},
"budget": {
"cost_mode": "balanced",
"max_cost_points": 10,
"max_time_sec": 120
}
}
Field notes:
spec.subject.referencemust be a publicly reachable HTTPS URL or the literalprompt-only(pure text-to-image). Upload local files to object storage first and pass the URL — never send local paths or base64. Up to 14 reference images viareferencesspec.format:png/jpg/jpeg/webp, defaultpngbudget.cost_mode:economy/balanced/premium; when the estimate exceedsmax_cost_pointsthe server pauses for your confirmationsensitive(optional):no_face_alter(default false),no_celebrity/no_brand(default true)
The response's session_id is used by every subsequent step.
3. Review the plan
GET /api/v1/open/agent/session/{session_id}/plan
Returns the planned steps, selected models, and cost estimate. Revise if needed.
4. Revise the plan (optional, multiple rounds)
POST /api/v1/open/agent/session/{session_id}/revision
{
"plan_id": "plan_xxx",
"round": 2,
"feedback": [
{ "field": "style", "comment": "Use a light-gray gradient background" }
],
"reason": "Client requested a different background tone"
}
After revising, GET the plan again and review until satisfied.
5. Approve execution
POST /api/v1/open/agent/session/{session_id}/approve
Returns an exec_id.
6. Poll for execution results
GET /api/v1/open/agent/session/{session_id}/exec
- On success the payload delivers
result_image_url(visual-QA plans may returnresult_textinstead of an image) - Also reported:
steps_log(per-step status), actual models used, actual cost,ai_labeling - On failure the status is
partial_failed/failed; readerror_codeanduser_messageand report honestly — never claim the image was generated
7. Interrupt and clean up (optional)
- POST
/session/{session_id}/interrupt: interrupt a running session - DELETE
/session/{session_id}: delete a session
Quick example
BASE=https://agent-api.mopng.cn/api/v1/open/agent
KEY="Authorization: Bearer $MOPNG_API_KEY"
# 1. Create a session
SID=$(curl -sS -X POST "$BASE/session" -H "$KEY" -H "Content-Type: application/json" \
-d '{"version":"1.0","user_intent":"Cut out the subject and export a transparent PNG","spec":{"goal":"cutout transparent png","subject":{"type":"image","reference":"https://example.com/photo.jpg"}}}' \
| python3 -c "import sys,json;print(json.load(sys.stdin)['data']['session_id'])")
# 2. Review plan → 3. Approve → 4. Poll results
curl -sS "$BASE/session/$SID/plan" -H "$KEY"
curl -sS -X POST "$BASE/session/$SID/approve" -H "$KEY"
curl -sS "$BASE/session/$SID/exec" -H "$KEY"
For a full client implementation, use the open-source skill repo:
gitee.com/jkin8010/mopng-api(SKILL.md contains the contract and scripts).
Image upload (local files)
When you have a local image file (e.g. ./photo.jpg), upload it first to get a publicly accessible URL, then call the tool endpoints.
POST https://mo-api.mopng.cn/api/v1/images/upload
- Content-Type:
multipart/form-data - Body:
filefield (the image file) - Auth: same as above,
Authorization: Bearer <your API key>
Response example:
{
"code": 0,
"data": {
"signedUrl": "https://...",
"signed_url": "https://...",
"bucket": "...",
"path": "...",
"md5": "..."
}
}
Image input rules
| Source | How to pass it |
|---|---|
Local file (e.g. ./a.png) | Upload via POST /api/v1/images/upload first, then use the returned signedUrl / signed_url |
Remote URL (e.g. https://example.com/photo.jpg) | Pass it directly, no upload needed |
Async tasks and polling
When a POST response has data.status of pending or processing, poll with the same API key until completed or failed. Do not assume polling is only needed when you set async_mode — the server may always return async tasks.
| Capability | POST path | Poll with GET (replace {id} with the task ID from the response) |
|---|---|---|
| Background removal, upscaling | /api/v1/open/image/remove-bg, /api/v1/open/image/upscale | /api/v1/open/image/tasks/{id} |
| Outpainting, translation | /api/v1/open/image/outpainting, /api/v1/open/image/translation | /api/v1/open/ai/generations/{id} (do not use /image/tasks) |
| Text-to-image, image-to-image | /api/v1/open/ai/generations | /api/v1/open/ai/generations/{id} |
Task ID: read from data in the first (and polling) responses; accepts jobId / job_id / taskId / task_id.
Result images: prefer data.results (usually an array of objects with url; imageUrl / image_url also possible); if results is absent, fall back to result.imageUrl / result.image_url.
Polling example (background removal / upscaling):
curl -sS "https://mo-api.mopng.cn/api/v1/open/image/tasks/matting-xxxxxxxx-20260320120000" \
-H "Authorization: Bearer $MOPNG_API_KEY"
For outpainting / translation / text-to-image / image-to-image, poll /api/v1/open/ai/generations/{id} instead.
Polling interval: 2–5 seconds. Apply the same error rule (code exists and is not 0).
Model discovery (text-to-image / image-to-image)
text-to-image and image-to-image are not limited to a single model. Before calling /api/v1/open/ai/generations, query available models:
- GET
https://mo-api.mopng.cn/api/v1/open/ai/models - Optional query:
type=text_to_image,type=image_edit, etc. (filter by capability)
Recommended agent flow:
- Call
/api/v1/open/ai/modelsto list available models. - Filter models supporting the current task (
text_to_imageorimage_to_image). - Use the
modelfield value and check the vendor documentation below for parameter formats. - Validate parameters per the vendor docs (resolution, aspect ratio, image input fields, async behavior).
- Then call
/api/v1/open/ai/generations.
Note: when vendor docs and actual server behavior disagree, the server response wins.
Vendor model documentation
Bytedance (Volcano Engine Ark)
doubao-seedream-4-0-250828(text_to_image / image_to_image) — Seedream 4.0 API docsdoubao-seedream-4-5-251128(text_to_image / image_to_image) — Jimeng 4.5 docs
Aliyun (DashScope)
qwen-image/qwen-image-plus/qwen-image-max(text_to_image) — Qwen Image APIqwen-image-edit-plus(image_to_image / image_edit) — Qwen Image Edit APIwanx-v2(text_to_image / image_to_image / image_edit) — Wanx V2 text-to-imagewanx-v2.5(text_to_image / image_to_image / image_edit) — Wanx V2.5
Copy-paste instructions for agents
Image input: local files must be uploaded first via POST /api/v1/images/upload; use data.signedUrl or data.signed_url. Remote URLs can be passed directly.
If a POST response has data.status pending/processing: poll — cutout/upscale via GET /api/v1/open/image/tasks/{taskId|task_id}; outpainting/translation/text-to-image/image-to-image via GET /api/v1/open/ai/generations/{jobId|task_id}. Same auth as task creation. Result images: prefer data.results[].url.
Before calling /api/v1/open/ai/generations for text-to-image or image-to-image:
1) GET /api/v1/open/ai/models?type=text_to_image (or type=image_edit) to list models;
2) pick a model supporting the target capability (check the type field);
3) confirm parameter formats in the vendor documentation;
4) then build the /api/v1/open/ai/generations request.
Important: the request body uses model (not model_id), and prompt stays at the top level (not nested in parameters).
Text-to-image: type=text_to_image, top-level prompt.
Image-to-image: type=image_to_image, top-level prompt + referenceImages.
Important constraint: image_url / referenceImage
remove-bg, upscale, outpainting, and translation require image_url to be a publicly reachable URL; referenceImage/referenceImages for image-to-image follow the same rule.
- Local images: upload via
POST /api/v1/images/uploadfirst, then usedata.signedUrl/data.signed_url - Remote URLs: if already a reachable
https://...address, pass it directly
remove-bg (background removal)
POST https://mo-api.mopng.cn/api/v1/open/image/remove-bg
Request body example:
{
"image_url": "https://example.com/input.jpg",
"output_format": "png",
"return_mask": false,
"only_mask": false,
"async_mode": false
}
Key data fields (camelCase / snake_case compatible):
taskId/task_idstatus:pending|processing|completed|failed- When completed: prefer the first item's
urlin theresultsarray; orresult.imageUrl/result.image_url, plusresult.maskUrl/result.mask_url(whenreturn_mask=true)
If status is pending / processing, poll GET /api/v1/open/image/tasks/{taskId|task_id} (regardless of async_mode).
upscale (HD upscaling)
POST https://mo-api.mopng.cn/api/v1/open/image/upscale
Request body example:
{
"image_url": "https://example.com/input.jpg",
"scale": 2,
"tile_size": 0,
"tile_pad": 10,
"output_format": "png",
"async_mode": false
}
async_modeis optional; even when omitted orfalse, poll GET/api/v1/open/image/tasks/{taskId|task_id}wheneverstatusispending/processing.
Response data: taskId/task_id, status, and image URLs in results or result (camelCase / snake_case may both appear).
outpainting (smart expansion)
POST https://mo-api.mopng.cn/api/v1/open/image/outpainting
Request body example:
{
"provider": "aliyun",
"model_id": "wanx-outpaint",
"image_url": "https://example.com/input.jpg",
"direction": "all",
"expand_ratio": 0.5,
"angle": 0,
"output_ratio": null,
"best_quality": false
}
Async: if data.status is pending / processing, poll GET /api/v1/open/ai/generations/{jobId|taskId|task_id} (do not use /api/v1/open/image/tasks/...). Prefer data.results[].url when done.
translation (image translation)
POST https://mo-api.mopng.cn/api/v1/open/image/translation
Request body example:
{
"provider": "aliyun",
"model_id": "qwen-mt-image",
"image_url": "https://example.com/text-image.jpg",
"source_language": "auto",
"target_language": "en",
"domain_hint": null,
"sensitive_word_filter": false,
"term_intervention": null
}
Async: if data.status is pending / processing, poll GET /api/v1/open/ai/generations/{jobId|taskId|task_id}. Prefer data.results[].url when done. Error rule: code is not None and code != 0.
text-to-image
POST https://mo-api.mopng.cn/api/v1/open/ai/generations
Minimal request (note: use model, not model_id; prompt stays top-level):
{
"type": "text_to_image",
"model": "wanx-v2.5",
"prompt": "A red-billed blue magpie on a branch, blue sky and white clouds behind"
}
Fields:
- type:
text_to_image(required) - model: model name (required), e.g.
wanx-v2.5,qwen-image-plus,doubao-seedream-4; get the list viaGET /api/v1/open/ai/models - prompt: prompt text (required), top-level, not nested inside
parameters
Task status:
- GET
/api/v1/open/ai/generations/{jobId|job_id|task_id} - When completed, prefer
data.results(e.g.results[0].url); fall back to the legacy single-objectresult
image-to-image
POST https://mo-api.mopng.cn/api/v1/open/ai/generations
Upload local images first; remote URLs can be passed as referenceImages. Multiple reference images are supported; for legacy compatibility you may also pass the first image as referenceImage.
Minimal request:
{
"type": "image_to_image",
"model": "qwen-image-edit-plus",
"prompt": "Turn the sky sunset-gold, keep the subject unchanged",
"referenceImages": [
"https://example.com/input-a.jpg",
"https://example.com/input-b.jpg"
],
"referenceImage": "https://example.com/input-a.jpg"
}
Fields:
- type:
image_to_image(required) - model: model name (required), e.g.
wanx-v2.5,qwen-image-edit-plus - prompt: edit instruction (required), top-level
- referenceImages: array of reference image URLs (recommended, multi-image), top-level
- referenceImage: single reference URL (compatibility field; when sending multiple, set it to
referenceImages[0])
Task status:
- GET
/api/v1/open/ai/generations/{jobId|job_id|task_id}; the result list isdata.results