Midjourney V8.2 Variation Interface
curl --request POST \
--url https://api.evolink.ai/v1/images/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "mj-v8.2-variation",
"model_params": {
"task_id": "task-unified-xxx",
"image_number": 2,
"type": "strong"
}
}
'import requests
url = "https://api.evolink.ai/v1/images/generations"
payload = {
"model": "mj-v8.2-variation",
"model_params": {
"task_id": "task-unified-xxx",
"image_number": 2,
"type": "strong"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: 'mj-v8.2-variation',
model_params: {task_id: 'task-unified-xxx', image_number: 2, type: 'strong'}
})
};
fetch('https://api.evolink.ai/v1/images/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.evolink.ai/v1/images/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'mj-v8.2-variation',
'model_params' => [
'task_id' => 'task-unified-xxx',
'image_number' => 2,
'type' => 'strong'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.evolink.ai/v1/images/generations"
payload := strings.NewReader("{\n \"model\": \"mj-v8.2-variation\",\n \"model_params\": {\n \"task_id\": \"task-unified-xxx\",\n \"image_number\": 2,\n \"type\": \"strong\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.evolink.ai/v1/images/generations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"mj-v8.2-variation\",\n \"model_params\": {\n \"task_id\": \"task-unified-xxx\",\n \"image_number\": 2,\n \"type\": \"strong\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.evolink.ai/v1/images/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"mj-v8.2-variation\",\n \"model_params\": {\n \"task_id\": \"task-unified-xxx\",\n \"image_number\": 2,\n \"type\": \"strong\"\n }\n}"
response = http.request(request)
puts response.read_body{
"created": 1757165031,
"id": "task-unified-1757165031-mjv82",
"model": "mj-v8.2-variation",
"object": "image.generation.task",
"progress": 0,
"status": "pending",
"task_info": {
"estimated_time": 45
},
"type": "image",
"usage": {
"billing_rule": "per_call",
"credits_reserved": 1.8,
"user_group": "default"
}
}{
"error": {
"code": "invalid_request",
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid or expired token",
"type": "authentication_error"
}
}{
"error": {
"code": "insufficient_quota",
"message": "Insufficient quota. Please top up your account.",
"type": "insufficient_quota"
}
}{
"error": {
"code": "model_access_denied",
"message": "Token does not have access to model: mj-v8.2-variation",
"type": "invalid_request_error"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}{
"error": {
"code": "internal_error",
"message": "Internal server error",
"type": "api_error"
}
}Midjourney V8.2
Midjourney V8.2 Variation
- Based on completed mj-v8.2 series tasks, generate style variants with differences for the specified image
- The prompt has no effect on variation output (it only produces style variants of the source image); to guide the changes with a prompt, use mj-v8.2-remix instead
- Note: derived tasks based on V8.2 images (variation / remix / edit) are rendered by the V7 engine upstream (documented by the upstream channel); the result may differ slightly in style from the source image. Pricing is unchanged
- Source task must be an image-generation, variation, remix or edit task; results of upload-paint / retexture / remove-bg are rejected by the upstream (405)
- There is no
speedfield:speed: fastis accepted and ignored, any other value returns 400 - Async processing mode, use the returned task ID to query status
POST
/
v1
/
images
/
generations
Midjourney V8.2 Variation Interface
curl --request POST \
--url https://api.evolink.ai/v1/images/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "mj-v8.2-variation",
"model_params": {
"task_id": "task-unified-xxx",
"image_number": 2,
"type": "strong"
}
}
'import requests
url = "https://api.evolink.ai/v1/images/generations"
payload = {
"model": "mj-v8.2-variation",
"model_params": {
"task_id": "task-unified-xxx",
"image_number": 2,
"type": "strong"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: 'mj-v8.2-variation',
model_params: {task_id: 'task-unified-xxx', image_number: 2, type: 'strong'}
})
};
fetch('https://api.evolink.ai/v1/images/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.evolink.ai/v1/images/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => 'mj-v8.2-variation',
'model_params' => [
'task_id' => 'task-unified-xxx',
'image_number' => 2,
'type' => 'strong'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.evolink.ai/v1/images/generations"
payload := strings.NewReader("{\n \"model\": \"mj-v8.2-variation\",\n \"model_params\": {\n \"task_id\": \"task-unified-xxx\",\n \"image_number\": 2,\n \"type\": \"strong\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.evolink.ai/v1/images/generations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"mj-v8.2-variation\",\n \"model_params\": {\n \"task_id\": \"task-unified-xxx\",\n \"image_number\": 2,\n \"type\": \"strong\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.evolink.ai/v1/images/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"mj-v8.2-variation\",\n \"model_params\": {\n \"task_id\": \"task-unified-xxx\",\n \"image_number\": 2,\n \"type\": \"strong\"\n }\n}"
response = http.request(request)
puts response.read_body{
"created": 1757165031,
"id": "task-unified-1757165031-mjv82",
"model": "mj-v8.2-variation",
"object": "image.generation.task",
"progress": 0,
"status": "pending",
"task_info": {
"estimated_time": 45
},
"type": "image",
"usage": {
"billing_rule": "per_call",
"credits_reserved": 1.8,
"user_group": "default"
}
}{
"error": {
"code": "invalid_request",
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid or expired token",
"type": "authentication_error"
}
}{
"error": {
"code": "insufficient_quota",
"message": "Insufficient quota. Please top up your account.",
"type": "insufficient_quota"
}
}{
"error": {
"code": "model_access_denied",
"message": "Token does not have access to model: mj-v8.2-variation",
"type": "invalid_request_error"
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}{
"error": {
"code": "internal_error",
"message": "Internal server error",
"type": "api_error"
}
}Midjourney has a built-in content moderation system. Each image is moderated individually: filtered images are left out of the results and the remaining images are delivered normally, so you may receive fewer images than usual. If at least one image passes, the task is
completed and billed normally; if all images are filtered, the task ends as failed and the reserved credits are refunded in full. Please make sure your prompts and reference images comply with the content guidelines.Authorizations
All endpoints require Bearer Token authentication
Get API Key:
Visit API Key Management Page to get your API Key
Add to request header:
Authorization: Bearer YOUR_API_KEY
Body
application/json
Model name
Available options:
mj-v8.2-variation Model parameters
Show child attributes
Show child attributes
HTTPS callback URL for task completion
Callback timing:
- Triggered when the task is completed or failed
- Sent after billing confirmation
Security restrictions:
- HTTPS protocol only
- Callbacks to private IP addresses are prohibited (127.0.0.1, 10.x.x.x, 172.16-31.x.x, 192.168.x.x, etc.)
- URL length must not exceed
2048characters
Callback mechanism:
- Timeout:
10seconds - Up to
3retries after failure (retries at1s/2s/4s after failure) - Callback response body format matches the task query endpoint
- A 2xx status code is considered successful; other status codes trigger retries
Example:
"https://your-domain.com/webhooks/image-task-completed"
Response
Task created successfully
Task creation timestamp
Example:
1757165031
Task ID
Example:
"task-unified-1757165031-mjv82"
Actual model name used
Example:
"mj-v8.2-variation"
Task object type
Available options:
image.generation.task Task progress percentage (0-100)
Required range:
0 <= x <= 100Example:
0
Task status
Available options:
pending, processing, completed, failed Example:
"pending"
Async task info
Show child attributes
Show child attributes
Task output type
Available options:
text, image, audio, video Example:
"image"
Usage and billing info
Show child attributes
Show child attributes