Midjourney
Generate images with Midjourney asynchronously: parameters, results, and caveats.
| Item | Value |
|---|---|
| Base URL | https://api.hop-base.com/v1 |
| Submit a task | POST /v1/images/generations |
| Query a task | GET /v1/video/tasks/{task_id} |
| List tasks | GET /v1/video/tasks |
| Key group | Midjourney Image Generation |
Midjourney is an asynchronous API: submit a task to get a HopBase task ID, then poll it for the result; every task returns exactly four images, and each one is billed.
Available models
| Model | Model ID | Tier / size | Official price |
|---|---|---|---|
| Midjourney v8.2 | midjourney-v8-2 | 1K by default; native 2K with --hd | $0.0067from/ image |
Confirm the exact model ID available to your key with GET /v1/models before sending paid work.
Request parameters
All requests use Authorization: Bearer sk-your-key and Content-Type: application/json. Size and quality go in -- parameters at the end of the prompt, not in request fields.
Body fields
| Parameter | Required | Type and limits | Default | Description |
|---|---|---|---|---|
model | Required | string, exact match | — | midjourney-v8-2 |
prompt | Required | string with a description | — | Add -- parameters after it |
images | Optional | array of 0–1 items | — | Reference image |
n | Optional | only 4 | 4 | Every task returns four images |
quality | Omit | must be empty | — | Use --hd for 2K |
extra | Omit | must be empty | — | No extra parameters |
promptmust contain a description, not only--parameters, and no::; images without a description are rejected.imagesis a reference image, for example[{"url":"https://example.com/ref.png"}]. It takes one image; for several, see “Multiple reference images” below.- Each
images[]item has exactly one ofurl(public absolute HTTP(S)) orfile_id, and nousage. - A non-empty
qualityreturns 400; use--hdin the prompt for 2K. - A non-empty
extraobject returns 400; this model takes no extra parameters.
The body is decoded strictly: any field not in the table is rejected with 400 at submission, no task is created, and nothing is billed. Set the aspect ratio with --ar in the prompt and the quality with --hd.
Fields that OpenAI Images clients often send, such as size, response_format, and style, are outside the table; the full list is under "More details" in Caveats below.
Size and aspect ratio
Image size comes from --ar (or its alias --aspect) in the prompt. --hd renders natively at roughly twice the edge length.
Any whole-number ratio works, not just the ones listed — as long as neither direction exceeds 14:1 (4:1 with --hd). The table lists common ratios; every size was measured, not derived — --hd is not an exact doubling.
--ar | Default | With --hd |
|---|---|---|
1:1 (default) | 1024 × 1024 | 2048 × 2048 |
1:2 | 768 × 1536 | 1552 × 3104 |
9:16 | 816 × 1456 | 1648 × 2944 |
2:3 | 896 × 1344 | 1792 × 2688 |
3:4 | 928 × 1232 | 1904 × 2544 |
5:6 | 992 × 1200 | 2016 × 2416 |
6:5 | 1200 × 992 | 2416 × 2016 |
4:3 | 1232 × 928 | 2544 × 1904 |
3:2 | 1344 × 896 | 2688 × 1792 |
16:9 | 1456 × 816 | 2944 × 1648 |
2:1 | 1536 × 768 | 3104 × 1552 |
21:9 | 1680 × 720 | 3376 × 1440 |
14:1 | 4096 × 288 | Rejected — see below |
--artakes exactly onewidth:heightvalue made of positive whole numbers;--ar 1.5:1is rejected.- The ratio may not exceed 14:1 in either direction.
--hdlowers that ceiling to 4:1:--hd --ar 14:1is rejected, while--hd --ar 4:1renders at 4096 × 1184.
Prompt parameters
These are accepted and passed through:
| Parameter | Range | Purpose |
|---|---|---|
--ar / --aspect | whole ratio | Aspect ratio |
--hd | flag | Native 2K render |
--s / --stylize | 0-1000 | Stylization strength |
--c / --chaos | 0-100 | Variation across the four images |
--weird / --w | 0-3000 | Unconventional aesthetics |
--iw | 0-3 | Weight of the reference image |
--sref + --sw | --sw 0-1000 | Style reference and its strength |
--no | text | Exclude elements |
--seed | integer | Reproducibility |
--tile, --exp | flag / 0-100 | Seamless tiling; dynamic range |
- Put every parameter after the description: any text after the first
--parameter is read as that parameter's value. - A numeric parameter with a range must be followed by exactly one number; a missing, extra, non-numeric, or out-of-range value returns 400.
Multiple reference images
images takes one image. To use several, put their URLs at the very start of prompt, separated by spaces, followed by your description — this is Midjourney's standard Image Prompt syntax:
"prompt": "https://example.com/a.png https://example.com/b.png a cat sitting in a vintage car --ar 1:1"
- Every URL must be a public HTTP(S) address.
- Reference images are inspiration, not a collage: their influence is not evenly split, and a strong subject in one image can dominate the result.
- To make sure something from a particular image shows up, name it in the description, or raise
--iw(0-3) to give the reference images more weight.
Refused parameters
These are rejected with 400 at submission. The model would otherwise ignore them silently, leaving you paying for an effect you never got, or fail the task minutes later.
| Parameter | Why |
|---|---|
--q / --quality | Has no effect on this model version |
--niji | Niji is a separate model version, not a parameter here |
--repeat | Has no effect; the image count per task is fixed |
--oref, --cref | Omni and character reference are unavailable on v8.x |
--stealth, --stop | Not supported on this model version |
--relax, --turbo | Tasks always run in Fast mode: Relax is not offered through this API, and Turbo is unavailable on v8.x |
--draft | Returns 24 low-resolution images per task; not offered |
--profile / --p | Personalization profiles are not supported here |
:: | Multi-prompt weighting is not supported on this model version |
Response
Submit response
A successful submit returns HTTP 202:
| Field | Type | Description |
|---|---|---|
id | string | HopBase task ID to poll |
object | string | Always image.generation.task |
model | string | midjourney-v8-2 |
status | string | Starts as queued |
created | integer | Creation time (Unix seconds) |
billing_bucket | string | Default tier or the --hd 2K tier |
requested_images | integer | Always 4 |
images_per_task | integer | Always 4 |
notice | string | Reminder: four images, each billed |
{
"id": "ktEXAMPLE",
"object": "image.generation.task",
"model": "midjourney-v8-2",
"status": "queued",
"created": 1790000000,
"billing_bucket": "img_1k",
"requested_images": 4,
"images_per_task": 4,
"notice": "this model always returns 4 images per task and bills every returned image"
}Query result
status moves through queued → processing → completed or failed. Only the last two are terminal, so treat any other value as still running.
| Field | Type | Description |
|---|---|---|
id | string | Task ID |
object | string | Always video.generation.task, image tasks included |
status | string | queued / processing / completed / failed |
outputs | string[] | Four image URLs once completed, valid 24 hours |
usage | object | Metering once completed: bucket (the tier from submit) and billed_images (always 4) |
usage.cost | number | The charge for this task in CNY (the same charge as usage.cost_usd) |
usage.cost_usd | number | The USD amount actually deducted from your balance for this task, the same as its usage record |
usage.currency | string | The currency of usage.cost, always CNY |
error.code | string | Stable error code on failure |
error.message | string | English explanation of the failure |
An excerpt of a completed task; the ID and URLs are placeholders:
{
"id": "ktEXAMPLE",
"object": "video.generation.task",
"model": "midjourney-v8-2",
"status": "completed",
"created": 1790000000,
"outputs": [
"https://api.hop-base.com/example-signed-image-1.png",
"https://api.hop-base.com/example-signed-image-2.png",
"https://api.hop-base.com/example-signed-image-3.png",
"https://api.hop-base.com/example-signed-image-4.png"
],
"usage": { "bucket": "img_1k", "billed_images": 4, "cost": 0.1496, "cost_usd": 0.022, "currency": "CNY" }
}The output URLs are served from api.hop-base.com as signed links valid for 24 hours from the moment the task completes. Querying again returns the same URL without extending it, and an expired link returns 410, so download the images in time.
Once the task finishes, the query's top-level usage also carries cost_usd — the USD amount actually deducted from your balance for this task, 0 for an uncharged failure — cost (the same charge in CNY), and currency (always CNY); see Video generation. The task list (GET /v1/video/tasks) carries the same cost, cost_usd, and currency in the usage of every finished task.
Examples
Submit a 16:9 task, then poll it to a terminal state:
curl https://api.hop-base.com/v1/images/generations \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{
"model": "midjourney-v8-2",
"prompt": "a red apple on a wooden table, studio light --ar 16:9"
}'
# Poll with the returned id; send no billing header
curl https://api.hop-base.com/v1/video/tasks/YOUR_TASK_ID \
-H "Authorization: Bearer sk-your-key"Caveats
- Every task returns four images and each is billed, so budget for four images per submission.
naccepts only4or nothing at all.- Set the ratio with
--arand 2K with--hd;sizeorqualityin the body returns 400. - With
--hd, the aspect-ratio ceiling drops from 14:1 to 4:1. - Put every
--parameter after the description. - Concurrency is limited: submitting a large batch in parallel fails most of it rather than queueing it.
- A task still unfinished 2 hours after creation is marked failed and not billed.
Even in fashion or commercial portraits, detailed descriptions of body shape, figure, or body parts such as legs, or emphasis on close-fitting or sheer clothing, can be refused when they add up. Describe the overall look, style, setting, and lighting instead, and submit again.
-
These fields that OpenAI Images clients often send are outside the table and return 400:
size response_format style user background output_format -
The body must be a single JSON object with nothing after it.
-
Parameter names are case-insensitive.
-
A parameter listed in neither parameter table is not blocked at submission, but it is not guaranteed to take effect.
-
The short form
--rof--repeatis not blocked at submission today, but it has no effect either; do not use it. -
Midjourney moderates content more strictly than most image models, and a refused task is not billed.
-
Only a small number of prompts render at once, far fewer than the synchronous image models; submit a few at a time and retry the ones that come back busy.
-
Poll the same way as any other asynchronous media task, without a billing header.
-
Older failed tasks may omit
error.code.
Common errors
Every submission-time error is HTTP 400; no task is created and nothing is billed. Checks run in order and the first failure is returned, in this body:
{
"error": {
"message": "request body does not match the JSON contract: json: unknown field \"size\"",
"type": "invalid_request_error"
}
}| Error | Fix |
|---|---|
json: unknown field "size" | Remove the extra field; set the ratio with --ar |
the quality field has no effect on this model | Remove quality; use --hd for 2K |
the n field cannot change that | Omit n or set it to 4 |
prompt must contain a description | Add a description before the parameters |
parameter --draft is not accepted | Remove the refused parameter |
may not exceed 4:1 when --hd is used | Narrow the ratio, or drop --hd |
Failed tasks
A failed task still answers the query with HTTP 200 and status failed. Decide success or failure from status, branch on error.code, and show error.message.
| Cause | error.code | What to do |
|---|---|---|
| Prompt refused by moderation | input_sensitive | Rephrase the prompt and resubmit |
| Reference image refused by moderation | input_sensitive | Swap the reference image and resubmit |
| Moderation, source not reported | input_sensitive | Rephrase; swap the reference image if sent |
| Concurrency ceiling reached | rate_limited | Retry shortly; run fewer tasks at once |
| No description | prompt_required | Add a description |
| Unsupported parameter | invalid_request | Remove the parameter not in the supported list |
| Invalid aspect ratio | invalid_request | Use a whole-number ratio within the ceiling |
| Malformed prompt | invalid_request | Check the trailing parameters and their values |
| Generation failed (other) | generation_failed | Retry once; then contact support with the task ID |
| Task could not be tracked | generation_failed | Contact support with the task ID |
| Timed out | timeout | Resubmit |
| Finished with no output | no_output | Resubmit |
Each line starting with # is the trigger and the next line is the verbatim error.message; parts in angle brackets vary with the request:
# A field outside the table
request body does not match the JSON contract: json: unknown field "<field>"
# Non-empty quality
the quality field has no effect on this model; ask for 2K output with --hd in the prompt instead
# n other than 4
this model always returns 4 images per task and bills every returned image; the n field cannot change that, so omit it or set it to 4
# Empty prompt
prompt is required for this model, even when input images are provided
# :: in the prompt
multi-prompt weighting (::) is not supported on this model version
# Parameters but no description
prompt must contain a description, not only parameters
# A refused parameter
parameter --<name> is not accepted: <reason>
# An images[] item with neither or both of url / file_id
images[<index>] must provide exactly one of url or file_id
# url that is not a public absolute http(s) address
images[<index>].url must be a publicly accessible absolute http(s) URL
# usage on an images[] item
images[<index>].usage is not part of the image generation API; remove this field
# Non-empty extra
model "midjourney-v8-2" does not accept unverified extra parameters
# More than one reference image
model "midjourney-v8-2" accepts at most 1 input images, got <count># --ar with no value or several
parameter --ar requires exactly one value such as 16:9
# --ar not in width:height form
parameter --ar must look like 16:9, got "<value>"
# Decimals in --ar
parameter --ar must use whole numbers such as 3:2; decimals are rejected, got "<value>"
# Zero or negative in --ar
parameter --ar must use positive numbers, got "<value>"
# Ratio beyond 14:1
parameter --ar may not exceed 14:1, got "<value>"
# Ratio beyond 4:1 with --hd
parameter --ar may not exceed 4:1 when --hd is used, got "<value>"
# Numeric parameter with no value or several
parameter --<name> requires exactly one numeric value
# Numeric parameter that is not a number
parameter --<name> must be a number, got "<value>"
# Numeric parameter out of range
parameter --<name> must be between <min> and <max>, got <value>{
"id": "ktEXAMPLE",
"object": "video.generation.task",
"model": "midjourney-v8-2",
"status": "failed",
"created": 1790000000,
"error": {
"code": "input_sensitive",
"message": "the prompt was rejected by content moderation; rephrase it and submit again"
}
}# input_sensitive: prompt refused by content moderation
the prompt was rejected by content moderation; rephrase it and submit again
# input_sensitive: reference image refused by content moderation
the reference image was rejected by content moderation; replace it and submit again
# input_sensitive: content moderation refused it, source not reported
the prompt or reference image was rejected by content moderation; revise it and submit again
# rate_limited: concurrency ceiling reached
this model is at its concurrency limit right now; please retry shortly
# prompt_required: no description
prompt is required for this model, even when input images are provided
# invalid_request: unsupported parameter
the prompt uses a parameter that this model version does not support
# invalid_request: invalid aspect ratio
the --ar value is not a valid aspect ratio for this model
# invalid_request: malformed prompt
the prompt was rejected by the model; check the parameters at the end of the prompt
# generation_failed: generation failed (other)
image generation failed; please retry, and contact support with the task ID if it keeps failing
# generation_failed: task could not be tracked (ends with this)
… contact support with the task ID
# timeout: timed out
task did not reach a billable terminal state within 2 hours; polling stopped
# no_output: finished with no output
image generation finished without a usable output; please retry, and contact support with the task ID if it keeps failingBilling
Midjourney bills per returned image, so a task costs four images at the rate for its tier; the default render and the --hd 2K render are priced separately. Only a task that completes successfully is billed; rejected submissions, moderation refusals, and failed tasks are not.
Official list prices are on the pricing page. Your own rate is the one shown in the signed-in model catalog, and each request's actual charge is in your usage record.
The model's specs and official prices are also on its model card.
Next steps
- Image generation overview: all image model series and shared rules
- Kling image: another image series that runs as async tasks
- Create image API reference: every body field
- Get video task API reference: the query endpoint for Midjourney tasks
- Creative Studio: generate images and video without writing code
- Troubleshooting: look up an error message