$KEY with your API token and $HOST with the actual platform domain.
export KEY="sk-your-api-key"
export HOST="https://api.apimart.ai"
Flow A: Basic text-to-image (imagine → upscale)
# 1. imagine produces 4 images
curl -sS -X POST "$HOST/v1/midjourney/generations/imagine" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"prompt": "a futuristic city at sunset, photorealistic, cinematic lighting",
"version": "8.1", "size": "16:9", "speed": "fast", "stylize": 250
}'
# → {"code":200,"data":[{"task_id":"task_01KQVZAPBW...","status":"submitted"}]}
# 2. poll until SUCCESS (about 30–60s)
curl -sS "$HOST/v1/midjourney/task_01KQVZAPBW..." -H "Authorization: Bearer $KEY"
# → SUCCESS, includes grid_image_url + 4 image_urls + buttons(U1-U4 / V1-V4 / 🔄)
# 3. upscale the 2nd image (composed locally, SUCCESS in milliseconds)
curl -sS -X POST "$HOST/v1/midjourney/generations/upscale" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_01KQVZAPBW...", "index": 2}'
# → query to get the single image image_urls[0]
Flow B: Image guidance → strong variation → upscale
# 1. image-guided imagine
curl -sS -X POST "$HOST/v1/midjourney/generations/imagine" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"prompt": "turn this product into a luxury studio photo",
"image_urls": ["https://your-cdn.example.com/product.png"],
"iw": 1.5, "size": "1:1"
}'
# 2. apply a strong variation to the result
curl -sS -X POST "$HOST/v1/midjourney/generations/high-variation" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_01XXX...", "index": 1, "speed": "fast"}'
# 3. upscale one of the variation images
curl -sS -X POST "$HOST/v1/midjourney/generations/upscale" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_02_variant...", "index": 3}'
Flow C: Inpaint (two-step inpaint + modal)
Prerequisite: first run imagine + upscale to get a single-image task (see Flow A).# 1. submit inpaint → enters MODAL
curl -sS -X POST "$HOST/v1/midjourney/generations/inpaint" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_02_upscaled..."}'
# → {"data":[{"task_id":"task_03_inpaint...","status":"modal"}]}
# note status=modal, the task waits for you to supply the mask; 30-minute timeout auto-cancels (CANCEL) + refund
# 2. frontend draws the mask (white = repaint area, transparent = keep), uploads it to your own OSS to get mask_url (must be publicly reachable)
# 3. submit modal to complete
curl -sS -X POST "$HOST/v1/midjourney/generations/modal" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"task_id": "task_03_inpaint...",
"prompt": "replace the selected area with a red leather sofa",
"mask_url": "https://your-oss.example.com/mask-abc.png"
}'
# → same task_id, status turns to submitted; 4. poll for 60–90s until SUCCESS, includes 4 inpaint candidates
Flow D: Zoom Out
# produces an image directly, no mask needed (neither Outpaint nor CustomZoom enters MODAL)
curl -sS -X POST "$HOST/v1/midjourney/generations/zoom" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"task_id": "task_02_upscaled...", "zoom_ratio": 1.5, "speed": "fast"}'
Flow E: Image-to-video (i2v)
# 720p HD + batch=4 (4x billing)
curl -sS -X POST "$HOST/v1/midjourney/generations/video" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"prompt": "city traffic at night, neon reflections, slow camera dolly",
"image_urls": ["https://your-cdn.example.com/city.jpg"],
"video_type": "vid_1.1_i2v_720", "batch_size": 4
}'
# actual charge = midjourney@video-720p × 4
# start/end frame transition (end_url auto-upgrades to start_end)
curl -sS -X POST "$HOST/v1/midjourney/generations/video" \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"prompt": "transition smoothly from sunrise to sunset",
"image_urls": ["https://your-cdn.example.com/sunrise.jpg"],
"end_url": "https://your-cdn.example.com/sunset.jpg",
"video_type": "vid_1.1_i2v_720"
}'
Shared utility: Python client wrapper
import time
import httpx
API_KEY = "sk-..."
HOST = "https://api.apimart.ai"
class MjClient:
def __init__(self):
self.client = httpx.Client(
base_url=HOST,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=30,
)
def imagine(self, prompt, **params):
r = self.client.post("/v1/midjourney/generations/imagine",
json={"prompt": prompt, **params})
return r.json()["data"][0]["task_id"]
def upscale(self, task_id, index):
r = self.client.post("/v1/midjourney/generations/upscale",
json={"task_id": task_id, "index": index})
return r.json()["data"][0]["task_id"]
def query(self, task_id):
return self.client.get(f"/v1/midjourney/{task_id}").json()
def wait(self, task_id, timeout=180):
deadline = time.time() + timeout
while time.time() < deadline:
t = self.query(task_id)
if t["status"] in ("SUCCESS", "FAILURE"):
return t
if t["status"] == "MODAL":
raise RuntimeError(f"task {task_id} needs a /modal call")
time.sleep(3)
raise TimeoutError(task_id)
mj = MjClient()
imagine_id = mj.imagine("a cat", version="8.1", speed="fast", size="16:9")
mj.wait(imagine_id)
upscale_id = mj.upscale(imagine_id, 2)
print(mj.wait(upscale_id)["image_urls"][0])
Shared utility: TypeScript wrapper
const API_KEY = "sk-...";
const HOST = "https://api.apimart.ai";
async function mj(path: string, body: any) {
const r = await fetch(`${HOST}${path}`, {
method: "POST",
headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify(body),
});
return r.json();
}
async function query(id: string) {
const r = await fetch(`${HOST}/v1/midjourney/${id}`, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
return r.json();
}
async function waitTask(id: string, timeoutMs = 180_000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const t = await query(id);
if (t.status === "SUCCESS" || t.status === "FAILURE") return t;
if (t.status === "MODAL") throw new Error(`needs a /modal call: ${id}`);
await new Promise((r) => setTimeout(r, 3000));
}
throw new Error(`timeout: ${id}`);
}
const r = await mj("/v1/midjourney/generations/imagine",
{ prompt: "a cat", version: "8.1", speed: "fast" });
const result = await waitTask(r.data[0].task_id);
console.log(result.image_urls);
State machine
submit → NOT_START(0%) → SUBMITTED(5-30%) → IN_PROGRESS(~99%) → SUCCESS(100%)
↘ FAILURE(100%) → auto refund
inpaint / CustomZoom → MODAL(15%) ──POST /modal {mask_url, prompt}──▶ SUBMITTED → ...
└ 30min timeout → CANCEL + refund