
How to Use Midjourney V8.1 API with EvoLink: Code Examples, Polling, and Callback

If you want to use Midjourney V8.1 from code, the practical question is not only "what endpoint do I call?" It is:
How do I test Midjourney V8.1, submit image generation tasks, track completion, control cost, and keep the option to switch image models later?
POST https://api.evolink.ai/v1/images/generations with model: "mj-v8.1", poll GET https://api.evolink.ai/v1/tasks/{task_id}, and use callback_url for production completion events.Quick Answer
Use EvoLink's image generation endpoint with the Midjourney V8.1 model name:
curl --request POST \
--url https://api.evolink.ai/v1/images/generations \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"model": "mj-v8.1",
"prompt": "a premium product photo of a matte black espresso machine on a marble counter --ar 16:9 --s 250",
"quality": "standard",
"model_params": {
"speed": "fast"
},
"callback_url": "https://your-domain.com/webhooks/evolink-image-task"
}'id, then query:curl --request GET \
--url https://api.evolink.ai/v1/tasks/<task_id> \
--header 'Authorization: Bearer YOUR_API_KEY'completed, read the results array and save the generated image URLs promptly. In fast mode, Midjourney V8.1 can return up to 4 images per generation; in draft mode it returns up to 24 lightweight sketch images. Content review may filter some outputs, and EvoLink bills the generation request per request rather than per image.What This Guide Covers
This is not a generic Midjourney prompt tutorial. It is a production guide for using Midjourney V8.1 through EvoLink.
| Reader task | What this article answers | Where EvoLink adds value |
|---|---|---|
| Try Midjourney V8.1 before coding | How to use the playground first | Browser testing before API work |
| Submit a task | Which endpoint, model name, and payload shape to use | One EvoLink API key and one image endpoint |
| Track completion | How polling and task_id work | Shared async task pattern across image and video routes |
| Move to production | How to use callback_url, retries, and result storage | Callback support and task status visibility |
| Control cost | How speed and quality affect billing | Transparent per-request pricing on the model page |
| Choose a model | When to use V8.1 versus GPT Image 2, Nano Banana Pro, or V7 | Model routing without rebuilding the integration |
Before You Start
You need four things:
- An EvoLink account.
- An EvoLink API key.
- A backend environment that can keep your API key private.
- A result storage plan, because generated image links can be time-limited.
task_id, and return only the safe state your product UI needs.Step 1: Test the Workflow in the EvoLink Playground
- whether your prompt style works for the visual direction you need
- whether you need image-to-image, Style Reference, or Omni Reference
- whether
draft,fast,standard, orhdis appropriate for the asset type
This matters for SEO and product quality for the same reason: users do not just want an API call. They want a working image workflow. Testing in the playground first reduces failed engineering loops, makes prompt examples more realistic, and gives your team a baseline before routing traffic from your product.
Step 2: Get Your EvoLink API Key
Use Bearer token authentication:
Authorization: Bearer YOUR_API_KEYIn production, keep the key server-side. A common setup is:
User action in your app
-> your backend API route
-> EvoLink image generation endpoint
-> store task_id
-> poll or receive callback
-> save results to your own storage
-> show final image in your appThat pattern keeps your frontend simple and protects the API key.
Step 3: Choose the Midjourney V8.1 Route
For new image generation, use:
POST https://api.evolink.ai/v1/images/generationsUse this model name:
{
"model": "mj-v8.1"
}prompt, then add the text description and supported prompt parameters.Step 4: Send a Text-to-Image Request
Use this for product photos, editorial visuals, concept art, moodboards, and general creative generation.
curl --request POST \
--url https://api.evolink.ai/v1/images/generations \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"model": "mj-v8.1",
"prompt": "a cinematic product photo of a titanium travel mug on wet black stone, soft studio reflection, premium outdoor brand style --ar 16:9 --s 250 --chaos 8",
"quality": "standard",
"model_params": {
"speed": "fast"
}
}'Example task-created response:
{
"created": 1757156493,
"id": "task-unified-1757156493-xkd8mv2r",
"model": "mj-v8.1",
"object": "image.generation.task",
"progress": 0,
"status": "pending",
"task_info": {
"can_cancel": true,
"estimated_time": 120
},
"type": "image",
"usage": {
"billing_rule": "per_call",
"credits_reserved": 6.0,
"user_group": "default"
}
}id. That is the task_id you use for polling or reconciliation after callback delivery.Step 5: Add Image-to-Image or Reference Images
Midjourney V8.1 uses Midjourney-style prompt syntax for image references. For image-to-image, prepend image URLs before the text prompt. Supported input formats include PNG, GIF, WebP, JPG, and JPEG. One image URL without text is invalid; use one image plus text, multiple images, or multiple images plus text.
curl --request POST \
--url https://api.evolink.ai/v1/images/generations \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"model": "mj-v8.1",
"prompt": "https://your-cdn.example.com/reference-sofa.jpg a luxury living room campaign image, keep the sofa shape and fabric feel, warm morning light --ar 4:3 --iw 1.2 --s 200",
"quality": "standard",
"model_params": {
"speed": "fast"
}
}'Use this pattern when you need the generated output to follow an existing product, scene, character, or visual direction.
Step 6: Use Style Reference and Omni Reference
For brand-like visual consistency, use Style Reference. For subject or object anchoring, use Omni Reference.
{
"model": "mj-v8.1",
"prompt": "a premium skincare bottle on a clean studio set, soft shadows, commercial beauty lighting --ar 1:1 --sref https://your-cdn.example.com/brand-style.jpg --sw 180 --oref https://your-cdn.example.com/product-object.jpg --ow 250",
"quality": "standard",
"model_params": {
"speed": "fast"
}
}Important route rules:
| Reference type | Syntax | Practical use | Notes |
|---|---|---|---|
| Image prompt | URL prompt text --iw N | Use an input image as visual guidance | Put URL before the text prompt |
| Style Reference | --sref URL --sw N | Transfer visual style | Requires a text prompt |
| Omni Reference | --oref URL --ow N | Anchor object or subject identity | Requires a text prompt; object reference can take longer |
Step 7: Poll the Task Until Completion
Use polling when you are building a simple integration, a backend job worker, or an internal tool.
curl --request GET \
--url https://api.evolink.ai/v1/tasks/task-unified-1757156493-xkd8mv2r \
--header 'Authorization: Bearer YOUR_API_KEY'id, model, progress, status, task_info, type, and results when completed.{
"created": 1756817821,
"id": "task-unified-1756817821-4x3rx6ny",
"model": "mj-v8.1",
"object": "image.generation.task",
"progress": 100,
"results": [
"https://cdn.evolink.ai/images/generated-image-abc123.jpg"
],
"status": "completed",
"task_info": {
"can_cancel": false
},
"type": "image"
}Recommended polling behavior:
| Stage | Suggested interval | What to do |
|---|---|---|
| First 20 seconds | Every 3-5 seconds | Show queued or processing state |
| Long-running task | Every 5-10 seconds | Avoid excessive polling |
| Completed | Stop polling | Copy result URLs to your own storage |
| Failed | Stop polling | Log request payload, task ID, and error state |
| Timeout in your app | Stop user-facing wait | Keep a background worker checking the task if needed |
Step 8: Use callback_url for Production
callback_url when creating the task:{
"model": "mj-v8.1",
"prompt": "a clean hero image for a travel booking app, modern airport lounge, premium editorial photo style --ar 16:9",
"quality": "standard",
"model_params": {
"speed": "fast"
},
"callback_url": "https://your-domain.com/webhooks/evolink-image-task"
}callback_url as an HTTPS callback address after task completion, with completion, failure, or cancellation events, a 10-second timeout, and up to 3 retries. The URL must use HTTPS, must stay within 2048 characters, and must not point to private IP ranges such as 127.0.0.1, 10.x.x.x, 172.16-31.x.x, or 192.168.x.x.Your webhook handler should:
- return a 2xx response quickly
- verify that the
task_idexists in your database - make one final
GET /v1/tasks/{task_id}check before marking the task final - deduplicate repeated callbacks by task ID and terminal status
- save final result URLs to your own storage before the 30-day link window expires
Use callback for user-facing applications, batch generation, and high-volume workflows. Use polling for simple admin tools and local testing.
Common Midjourney V8.1 Request Parameters on EvoLink
The exact API Reference should remain your source of truth. This table summarizes the common fields used in the generation workflow.
| Field | Required | Example | What it controls |
|---|---|---|---|
model | Yes | mj-v8.1 | Selects Midjourney V8.1 |
prompt | Yes | a product photo... --ar 16:9 --s 250 | Image description plus supported MJ-style prompt parameters |
quality | No | standard, hd | Output quality tier and pricing multiplier |
model_params.speed | No | draft, fast | Queue priority and pricing multiplier |
callback_url | No | https://your-domain.com/webhooks/evolink-image-task | Completion callback for production workflows |
--ar, --s, --chaos, --exp, --raw, --seed, --iw, --sref, --sw, --oref, and --ow.model_params.speed for speed and the top-level quality field for output quality.Parameters You Should Not Assume
Do not copy parameter lists from older Midjourney versions or third-party examples without checking the EvoLink API Reference.
| Do not assume | Why |
|---|---|
--v 8.1 | The route is already locked to V8.1 |
--fast, --turbo, --draft in prompt | Speed is controlled by model_params.speed |
--hd | Quality is controlled by the top-level quality field |
--q | Not exposed on this V8.1 route unless backend support is confirmed |
--no | Not exposed on this V8.1 route unless backend support is confirmed |
--cref | Use Omni Reference (--oref) for subject or object reference workflows |
This is one reason the EvoLink product page matters. It gives developers the current route behavior instead of forcing them to reconcile outdated community parameter lists.
Pricing and Cost Planning
| Choice | Cost impact | Product guidance |
|---|---|---|
fast | Base speed tier | Default for most production requests |
draft | Same base pricing on this route | Useful for exploration, not a discounted half-price tier |
standard | Base quality tier | Default for most previews and app UI output |
hd | 1.5x quality multiplier | Use for final assets, hero visuals, and premium workflows |
| Fast 4 images, Draft 24 sketches | Billed per request | Evaluate effective cost by approved outputs, not only requested task count |
hd behind a vague "best quality" toggle unless your billing model can absorb the extra cost. Also note that quality: "hd" is mutually exclusive with model_params.speed: "draft".Example Payloads by Use Case
Product Photography
{
"model": "mj-v8.1",
"prompt": "a premium product photo of a ceramic desk lamp on a walnut table, soft window light, editorial interior design style --ar 4:3 --s 180",
"quality": "standard",
"model_params": {
"speed": "fast"
}
}Final Marketing Hero Image
{
"model": "mj-v8.1",
"prompt": "a luxury resort terrace overlooking a futuristic skyline at golden hour, cinematic commercial photography, elegant travel campaign mood --ar 16:9 --s 300 --chaos 6",
"quality": "hd",
"model_params": {
"speed": "fast"
},
"callback_url": "https://your-domain.com/webhooks/evolink-image-task"
}Image-to-Image Product Variant
{
"model": "mj-v8.1",
"prompt": "https://your-cdn.example.com/reference-chair.jpg a modern ecommerce lifestyle photo, keep the chair silhouette, add a bright Scandinavian apartment setting --ar 3:2 --iw 1.4 --s 150",
"quality": "standard",
"model_params": {
"speed": "fast"
}
}Brand Style Reference
{
"model": "mj-v8.1",
"prompt": "a set of premium coffee packaging on a clean studio background --ar 1:1 --sref https://your-cdn.example.com/brand-moodboard.jpg --sw 220 --s 200",
"quality": "standard",
"model_params": {
"speed": "fast"
}
}JavaScript Example: Submit and Poll
Use this shape from your backend, not from the browser.
const API_KEY = process.env.EVOLINK_API_KEY;
const BASE_URL = "https://api.evolink.ai/v1";
async function createMidjourneyTask() {
const response = await fetch(`${BASE_URL}/images/generations`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "mj-v8.1",
prompt: "a premium product photo of a smart speaker on a stone plinth --ar 16:9 --s 250",
quality: "standard",
model_params: {
speed: "fast"
}
})
});
if (!response.ok) {
throw new Error(`EvoLink task create failed: ${response.status}`);
}
return response.json();
}
async function getTask(taskId) {
const response = await fetch(`${BASE_URL}/tasks/${taskId}`, {
headers: {
Authorization: `Bearer ${API_KEY}`
}
});
if (!response.ok) {
throw new Error(`EvoLink task query failed: ${response.status}`);
}
return response.json();
}
async function waitForTask(taskId) {
for (let attempt = 0; attempt < 60; attempt += 1) {
const task = await getTask(taskId);
if (task.status === "completed") return task;
if (task.status === "failed") throw new Error(`Task failed: ${task.id}`);
await new Promise((resolve) => setTimeout(resolve, 5000));
}
throw new Error(`Task timeout: ${taskId}`);
}Python Example: Submit and Poll
import os
import time
import requests
API_KEY = os.environ["EVOLINK_API_KEY"]
BASE_URL = "https://api.evolink.ai/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
payload = {
"model": "mj-v8.1",
"prompt": "a premium product photo of a minimalist wristwatch on dark slate --ar 16:9 --s 220",
"quality": "standard",
"model_params": {
"speed": "fast",
},
}
create_response = requests.post(
f"{BASE_URL}/images/generations",
headers=headers,
json=payload,
timeout=30,
)
create_response.raise_for_status()
task = create_response.json()
task_id = task["id"]
for _ in range(60):
status_response = requests.get(
f"{BASE_URL}/tasks/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=30,
)
status_response.raise_for_status()
current = status_response.json()
if current["status"] == "completed":
print(current.get("results", []))
break
if current["status"] == "failed":
raise RuntimeError(f"Task failed: {task_id}")
time.sleep(5)
else:
raise TimeoutError(f"Task timeout: {task_id}")Production Checklist
Use this checklist before sending real user traffic.
| Area | Required production behavior |
|---|---|
| API key | Store EVOLINK_API_KEY server-side only |
| Request logging | Log model, prompt hash, model_params.speed, quality, user ID, and task_id |
| User experience | Show pending, processing, completed, and failed states |
| Polling | Back off after the first few checks; avoid tight loops |
| Callback | Return 2xx quickly and process the event asynchronously |
| Result storage | Copy final images to your own storage before links expire |
| Cost control | Gate hd behind product rules |
| Fallback | Keep a second image route for cases where V8.1 is not the best fit |
| Abuse prevention | Rate-limit users, sanitize prompts, and monitor failed tasks |
| Documentation | Link developers to the API Reference for exact fields |
When to Use Midjourney V8.1 vs Other EvoLink Image Models
EvoLink's product value is not only that it exposes one model. The value is that your application can compare and route across models without rebuilding authentication, billing, and task tracking each time.
| Model | Choose it when | Avoid using it as the default when |
|---|---|---|
| Midjourney V8.1 | You need Midjourney-style visual direction, product photography, Style Reference, Omni Reference, and Fast four-image generations | Your workflow is primarily text rendering or strict layout reproduction |
| Midjourney V7 | You already have V7 prompts or want to keep an older Midjourney-family route available | You are starting a new workflow and want V8.1 generation defaults |
| Nano Banana Pro | You want an EvoLink image alternative to test against product mockup or editing-heavy workflows | You specifically need MJ-style prompt syntax and four-image creative batches |
| GPT Image 2 | You want an EvoLink image alternative for instruction-heavy image workflows | You specifically need Midjourney-style visual output and MJ prompt controls |
For production teams, this is the real advantage: you can start with Midjourney V8.1, keep GPT Image 2 or Nano Banana Pro as alternatives, and make routing decisions based on actual user outcomes rather than provider lock-in.
Common Mistakes
Mistake 1: Treating the blog as the API reference
This article explains the workflow. The API Reference on the model page controls exact route behavior.
Mistake 2: Passing speed flags in the prompt
model_params.speed. Do not rely on --fast, --turbo, or --draft inside the prompt.Mistake 3: Assuming every request returns exactly four usable images
results you receive.Mistake 4: Waiting on one long HTTP request
task_id, then poll or receive callback.Mistake 5: Not saving generated results
Generated image links are valid for 30 days. Copy results to your own storage when the task completes.
FAQ
How do I use the Midjourney V8.1 API with EvoLink?
What is the Midjourney V8.1 API model name on EvoLink?
mj-v8.1 for the main generation route. Other V8.1 operations such as variation, remix, canvas edit, retexture, remove background, and advanced edit have their own model names on the Midjourney V8.1 API page.What endpoint do I call for Midjourney V8.1 image generation?
Does Midjourney V8.1 support image-to-image through EvoLink?
prompt, followed by the text description and supported prompt parameters.Does Midjourney V8.1 support polling?
id. Query GET /v1/tasks/{task_id} until the task reaches completed or failed.Does Midjourney V8.1 support callback URL?
Yes. The V8.1 API reference documents a callback URL field as an HTTPS callback address for completion, failure, or cancellation. Use callback for production workflows and keep polling as a backup verification path.
How many images does one Midjourney V8.1 request return?
results array you receive. Billing is per request, not per returned image.Should I use standard or hd quality?
standard for default previews and most app UI workflows. Use hd for final marketing assets, hero images, or paid user workflows where native HD output matters enough to justify the 1.5x quality multiplier. Do not combine quality: "hd" with model_params.speed: "draft".Should I use fast or draft?
fast as the default. Use draft for fast composition exploration with lightweight sketch outputs, but do not assume it is a half-price tier on this route.When should I choose GPT Image 2 or Nano Banana Pro instead?
Choose GPT Image 2 when your workflow depends on precise instruction following, OpenAI-adjacent architecture, or broader reasoning context. Choose Nano Banana Pro when image editing, product mockups, or Gemini image workflows matter more than Midjourney-style prompt syntax.
Sources and Further Reading
- EvoLink Midjourney V8.1 API page
- EvoLink Midjourney V8.1 image generation docs
- EvoLink Midjourney V8.1 pricing section
- EvoLink model catalog
- Midjourney public documentation


