GLM-5.2 is now availableLearn more
How to Use Midjourney V8.1 API with EvoLink: Code Examples, Polling, and Callback
guide

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

EvoLink Team
EvoLink Team
Product Team
June 21, 2026
18 min read

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?

On EvoLink, the answer is to treat Midjourney V8.1 as one route inside a unified image API workflow. You can test prompts in the Midjourney V8.1 playground, call 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.
This guide focuses on the developer path. For the exact live parameter list and billing table, use the Midjourney V8.1 API page as the source of truth.

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"
  }'
The create call returns an async task object. Store the returned id, then query:
curl --request GET \
  --url https://api.evolink.ai/v1/tasks/<task_id> \
  --header 'Authorization: Bearer YOUR_API_KEY'
When the task reaches 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 taskWhat this article answersWhere EvoLink adds value
Try Midjourney V8.1 before codingHow to use the playground firstBrowser testing before API work
Submit a taskWhich endpoint, model name, and payload shape to useOne EvoLink API key and one image endpoint
Track completionHow polling and task_id workShared async task pattern across image and video routes
Move to productionHow to use callback_url, retries, and result storageCallback support and task status visibility
Control costHow speed and quality affect billingTransparent per-request pricing on the model page
Choose a modelWhen to use V8.1 versus GPT Image 2, Nano Banana Pro, or V7Model routing without rebuilding the integration

Before You Start

You need four things:

  1. An EvoLink account.
  2. An EvoLink API key.
  3. A backend environment that can keep your API key private.
  4. A result storage plan, because generated image links can be time-limited.
Do not put your EvoLink API key in frontend JavaScript. Call EvoLink from your backend, store the returned task_id, and return only the safe state your product UI needs.
Start with the Midjourney V8.1 API page, not with code. The playground helps you verify three things before you write integration logic:
  • 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, or hd is 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.

Use Bearer token authentication:

Authorization: Bearer YOUR_API_KEY

In 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 app

That 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/generations

Use this model name:

{
  "model": "mj-v8.1"
}
Midjourney V8.1 on EvoLink supports text-to-image and image-to-image through the same generation route. For image-to-image, place image URLs at the beginning of the 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"
  }
}
Store the response 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"
  }
}
Use the Midjourney V8.1 Prompt Builder when you want to assemble prompt parameters without memorizing every flag.

Important route rules:

Reference typeSyntaxPractical useNotes
Image promptURL prompt text --iw NUse an input image as visual guidancePut URL before the text prompt
Style Reference--sref URL --sw NTransfer visual styleRequires a text prompt
Omni Reference--oref URL --ow NAnchor object or subject identityRequires 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'
The task response includes fields such as 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:

StageSuggested intervalWhat to do
First 20 secondsEvery 3-5 secondsShow queued or processing state
Long-running taskEvery 5-10 secondsAvoid excessive polling
CompletedStop pollingCopy result URLs to your own storage
FailedStop pollingLog request payload, task ID, and error state
Timeout in your appStop user-facing waitKeep a background worker checking the task if needed

Step 8: Use callback_url for Production

Polling is fine for prototypes. For production, pass 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"
}
EvoLink's Midjourney V8.1 API reference documents 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_id exists 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.

The exact API Reference should remain your source of truth. This table summarizes the common fields used in the generation workflow.

FieldRequiredExampleWhat it controls
modelYesmj-v8.1Selects Midjourney V8.1
promptYesa product photo... --ar 16:9 --s 250Image description plus supported MJ-style prompt parameters
qualityNostandard, hdOutput quality tier and pricing multiplier
model_params.speedNodraft, fastQueue priority and pricing multiplier
callback_urlNohttps://your-domain.com/webhooks/evolink-image-taskCompletion callback for production workflows
Prompt-level controls exposed on this route include --ar, --s, --chaos, --exp, --raw, --seed, --iw, --sref, --sw, --oref, and --ow.
Speed and quality are not prompt flags on this EvoLink route. Use 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 assumeWhy
--v 8.1The route is already locked to V8.1
--fast, --turbo, --draft in promptSpeed is controlled by model_params.speed
--hdQuality is controlled by the top-level quality field
--qNot exposed on this V8.1 route unless backend support is confirmed
--noNot exposed on this V8.1 route unless backend support is confirmed
--crefUse 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

For live pricing, use the Midjourney V8.1 pricing section. The integration logic should still understand the main cost drivers:
ChoiceCost impactProduct guidance
fastBase speed tierDefault for most production requests
draftSame base pricing on this routeUseful for exploration, not a discounted half-price tier
standardBase quality tierDefault for most previews and app UI output
hd1.5x quality multiplierUse for final assets, hero visuals, and premium workflows
Fast 4 images, Draft 24 sketchesBilled per requestEvaluate effective cost by approved outputs, not only requested task count
In your own product, expose cost-sensitive choices intentionally. Do not hide 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.

AreaRequired production behavior
API keyStore EVOLINK_API_KEY server-side only
Request loggingLog model, prompt hash, model_params.speed, quality, user ID, and task_id
User experienceShow pending, processing, completed, and failed states
PollingBack off after the first few checks; avoid tight loops
CallbackReturn 2xx quickly and process the event asynchronously
Result storageCopy final images to your own storage before links expire
Cost controlGate hd behind product rules
FallbackKeep a second image route for cases where V8.1 is not the best fit
Abuse preventionRate-limit users, sanitize prompts, and monitor failed tasks
DocumentationLink developers to the API Reference for exact fields

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.

ModelChoose it whenAvoid using it as the default when
Midjourney V8.1You need Midjourney-style visual direction, product photography, Style Reference, Omni Reference, and Fast four-image generationsYour workflow is primarily text rendering or strict layout reproduction
Midjourney V7You already have V7 prompts or want to keep an older Midjourney-family route availableYou are starting a new workflow and want V8.1 generation defaults
Nano Banana ProYou want an EvoLink image alternative to test against product mockup or editing-heavy workflowsYou specifically need MJ-style prompt syntax and four-image creative batches
GPT Image 2You want an EvoLink image alternative for instruction-heavy image workflowsYou 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

Use model_params.speed. Do not rely on --fast, --turbo, or --draft inside the prompt.

Mistake 3: Assuming every request returns exactly four usable images

Fast generation requests can produce four images, while Draft mode can produce 24 lightweight sketch images. Content review may filter outputs, so store and display the actual results you receive.

Mistake 4: Waiting on one long HTTP request

Use async task handling. Submit, store 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

Create an EvoLink API key, test prompts on the Midjourney V8.1 playground, then send an image generation request with the Midjourney V8.1 model name. Store the returned task ID, then poll the task status endpoint or use a callback URL.
Use 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?

Use the EvoLink image generation endpoint for task creation and the EvoLink task status endpoint to query async task progress. The exact routes are shown in the code examples above and on the Midjourney V8.1 API page.
Yes. For the main V8.1 generation route, place image URLs at the beginning of the prompt, followed by the text description and supported prompt parameters.

Does Midjourney V8.1 support polling?

Yes. The create call returns an async task object with an 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?

Fast generation requests can produce up to four images. Draft mode can produce up to 24 lightweight sketch images. Content review can filter outputs, so always use the actual results array you receive. Billing is per request, not per returned image.

Should I use standard or hd quality?

Use 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?

Use 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

Start in the Midjourney V8.1 playground, confirm the prompt and parameter setup, then move the same workflow into your backend using the async task pattern in this guide.
Open Midjourney V8.1 on EvoLink

Ready to Reduce Your AI Costs by 89%?

Start using EvoLink today and experience the power of intelligent API routing.