Midjourney has no public API: comparable control in a pipeline

Midjourney's 10/1 alpha adds a pinnable --exp setting and edits that keep aspect ratio. What to use when you need that kind of control from code.

4 min readSume
All posts

If you need code-driven image control, Midjourney is not the tool to plan around: the research behind this post found no public API for it. Its October 1 alpha changelog is still worth reading for what control looks like, and the Sume Image API offers parameters that serve the same goals.

What the alpha changelog lists

The October 1 entry describes three changes relevant to repeatable work. They are features of Midjourney's own interface, and Midjourney's page is the place to confirm how they behave.

Midjourney alpha changelog 10/1/26 (read 2026-10-03)
ChangeWhy it matters for repeatable work
Multiple style references as one pillSeveral looks combined into a single control
--exp pinnable per folderA setting that stays fixed across a project
Edits preserve the base aspect ratioA changed image keeps its frame

The same goals through an API

On Sume's Image API, the controls are request fields and each model lists which it accepts. A field that a model does not list returns 400 unsupported_parameter, so the catalog is the contract.

  • Several style references: input_references, a per-model range, for example up to 16 on GPT Image 2.5.
  • A setting that stays fixed: store the request body in your project and send the same fields each time.
  • Keeping the frame on an edit: Ideogram 4.5 keeps the source image shape when an edit omits aspect_ratio.
  • Repeatability by number: seed is not served, so pin the model id and settings instead.

A project settings file

A pinnable setting in a chat tool becomes a small file in a pipeline. Keep one JSON per project and merge it into every request.

import json
import os
import requests


def main() -> None:
    base = json.load(open("project-settings.json"))
    body = {**base, "prompt": "Product on a marble counter, soft window light"}
    r = requests.post(
        "https://api.sume.com/v1/images",
        headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"},
        json=body,
        timeout=60,
    )
    print(r.status_code, r.json().get("usage", {}).get("cost"))


if __name__ == "__main__":
    main()

Choosing

For exploring looks by hand, an interface with pinning and style pills is pleasant. For anything that must run unattended or be rerun next month, choose a model with a documented request shape and keep the settings file next to the outputs.

Sources

Related posts

More in Comparisons

All Comparisons posts

Written by Sume