메인 콘텐츠로 건너뛰기

🎯 핵심 개념 이해하기

MidJourney API는 Discord 버튼 상호작용을 시뮬레이션합니다. 일반적인 REST API와 달리, 각 작업이 다음 단계에 사용할 새로운 버튼을 반환하는 상태 머신처럼 동작합니다.

4가지 핵심 API

API용도사용 시점
POST /mj/submit/imagine텍스트-이미지 생성모든 워크플로의 시작점
GET /mj/task/\{id\}/fetch작업 상태 조회 및 버튼 가져오기매 submit 이후(완료될 때까지 폴링)
POST /mj/submit/action버튼 클릭(upscale, vary, zoom 등)이미지에 작업을 수행하고 싶을 때
POST /mj/submit/modal추가 입력 제출status가 MODAL일 때만

📊 전체 워크플로 다이어그램

┌─────────────────────────────────────────────────────────────────────────────┐
│                         MIDJOURNEY API WORKFLOW                             │
└─────────────────────────────────────────────────────────────────────────────┘

  ┌──────────────────┐
  │  POST /submit/   │  ← Step 1: Submit prompt, get task_id
  │     imagine      │
  └────────┬─────────┘
           │ Returns: { "result": "task_id_1" }

  ┌──────────────────┐
  │ GET /task/{id}/  │  ← Step 2: Poll until status = "SUCCESS"
  │      fetch       │
  └────────┬─────────┘
           │ Returns: imageUrl + buttons[] (U1,U2,U3,U4,V1,V2,V3,V4,🔄)

  ┌──────────────────┐
  │  POST /submit/   │  ← Step 3: Click a button using customId
  │     action       │
  └────────┬─────────┘
           │ Returns: { "result": "task_id_2" }

  ┌──────────────────┐
  │ GET /task/{id}/  │  ← Step 4: Poll the new task
  │      fetch       │
  └────────┬─────────┘

           ├─── status = "SUCCESS" → Done! Get imageUrl

           └─── status = "MODAL" → Need additional input (see Step 5)


           ┌──────────────────┐
           │  POST /submit/   │  ← Step 5: Submit mask/prompt for special operations
           │      modal       │
           └────────┬─────────┘
                    │ Returns: { "result": "task_id_3" }

           ┌──────────────────┐
           │ GET /task/{id}/  │  ← Step 6: Poll until SUCCESS
           │      fetch       │
           └──────────────────┘

🔑 핵심 개념: Buttons와 customId

성공한 모든 작업은 buttons 배열을 반환합니다. 각 버튼에는 다음 작업을 실행할 때 사용하는 customId가 있습니다. /mj/task/\{id\}/fetch의 응답 예시:
{
  "status": "SUCCESS",
  "imageUrl": "https://api.cometapi.com/mj/image/xxx",
  "buttons": [
    { "customId": "MJ::JOB::upsample::1::abc123", "label": "U1" },
    { "customId": "MJ::JOB::upsample::2::abc123", "label": "U2" },
    { "customId": "MJ::JOB::variation::1::abc123", "label": "V1" },
    { "customId": "MJ::JOB::reroll::0::abc123", "emoji": "🔄" }
  ]
}
⚠️ 중요: customId는 고정된 값이 아닙니다. 작업마다 바뀝니다. 항상 buttons 배열에서 가져오세요.

📋 단계별 버튼 참조

IMAGINE 이후(4분할 그리드 이미지)

초기 이미지 생성이 완료되면 다음 버튼이 반환됩니다:
ButtoncustomId PatternActionResult
U1-U4MJ::JOB::upsample::1::xxx단일 이미지 업스케일고해상도 단일 이미지
V1-V4MJ::JOB::variation::1::xxx변형 생성새로운 4분할 그리드
🔄MJ::JOB::reroll::0::xxx::SOLO전체 재생성새로운 4분할 그리드

UPSCALE 이후(단일 이미지)

업스케일 후에는 편집 도구를 사용할 수 있습니다:
LabelNeeds Modal?
Upscale (Subtle) / Upscale (2x)❌ 아니요
Upscale (Creative) / Upscale (4x)❌ 아니요
Vary (Subtle) 🪄❌ 아니요
Vary (Strong) 🪄❌ 아니요
Vary (Region) 🖌️✅ 예(마스크)
Zoom Out 2x / 1.5x 🔍❌ 아니요
Custom Zoom 🔍✅ 예(프롬프트)
⬅️➡️⬆️⬇️ Pan❌ 아니요
Animate 🎞️❌ 아니요
🔄 Reroll❌ 아니요
참고: 버튼 라벨과 customId 형식은 프롬프트에 지정한 MJ 버전(예: --v 6.1 vs --v 5.2)에 따라 달라질 수 있습니다. 항상 API 응답에서 버튼을 확인하세요.
⚠️ Inpaint (Vary Region) 버튼은 Upscale 이후에만 표시됩니다!

⚡ 전체 예제: 생성 & 업스케일

1단계: Imagine 요청 제출

curl -X POST 'https://api.cometapi.com/mj/submit/imagine' \
  -H 'Authorization: Bearer <YOUR_COMETAPI_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "botType": "MID_JOURNEY",
    "prompt": "a cute cat --v 6.1",
    "accountFilter": { "modes": ["FAST"] }
  }'
응답:
{ "code": 1, "result": "1768464763141701" }

2단계: 작업 상태 폴링

curl -X GET 'https://api.cometapi.com/mj/task/1768464763141701/fetch' \
  -H 'Authorization: Bearer <YOUR_COMETAPI_KEY>'
응답(완료 시):
{
  "status": "SUCCESS",
  "imageUrl": "https://api.cometapi.com/mj/image/1768464763141701",
  "buttons": [
    { "customId": "MJ::JOB::upsample::1::5f20922e-xxx", "label": "U1" },
    { "customId": "MJ::JOB::upsample::2::5f20922e-xxx", "label": "U2" },
    ...
  ]
}

3단계: U1 클릭하여 업스케일

curl -X POST 'https://api.cometapi.com/mj/submit/action' \
  -H 'Authorization: Bearer <YOUR_COMETAPI_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "taskId": "1768464763141701",
    "customId": "MJ::JOB::upsample::1::5f20922e-xxx"
  }'
응답:
{ "code": 1, "result": "1768464800000000" }

4단계: 새 작업 폴링 및 결과 가져오기

curl -X GET 'https://api.cometapi.com/mj/task/1768464800000000/fetch' \
  -H 'Authorization: Bearer <YOUR_COMETAPI_KEY>'

⚠️ Modal은 언제 필요한가요?

/mj/submit/action을 호출했을 때 작업 상태가 SUCCESS가 아니라 MODAL이 되면, 추가 입력을 제공하기 위해 /mj/submit/modal을 호출해야 합니다.

확인된 Modal 작업

OperationButtonWhat to Submit
InpaintVary (Region)maskBase64 (PNG 마스크) + prompt
Custom Zoom🔍 Custom Zoomprompt (예: “your prompt —zoom 2”)
예제: Inpaint 흐름
# 1. Action API를 통해 Vary (Region) 버튼 클릭
curl -X POST 'https://api.cometapi.com/mj/submit/action' \
  -H 'Authorization: Bearer <YOUR_COMETAPI_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{"taskId": "xxx", "customId": "MJ::Inpaint::xxx", "enableRemix": true}'

# 2. 폴링하여 status = "MODAL" 확인
curl -X GET 'https://api.cometapi.com/mj/task/new_task_id/fetch'
# Response: { "status": "MODAL" }

# 3. Modal API를 통해 마스크와 프롬프트 제출
curl -X POST 'https://api.cometapi.com/mj/submit/modal' \
  -H 'Authorization: Bearer <YOUR_COMETAPI_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "taskId": "new_task_id",
    "prompt": "replace with golden crown",
    "maskBase64": "data:image/png;base64,..."
  }'

🚀 속도 모드 선택

경로에 속도 접두사를 추가하세요:
모드경로 접두사예시
Fast/mj-fast/mj-fast/mj/submit/imagine
Turbo/mj-turbo/mj-turbo/mj/submit/imagine
Relax(기본값)/mj/submit/imagine

🔗 기타 진입점

이 API들은 imagine → action 흐름을 따르지 않는 독립적인 진입점입니다:
API용도
POST /mj/submit/blend2~5개의 이미지를 하나로 블렌드
POST /mj/submit/describe이미지에서 프롬프트(Prompt) 생성
POST /mj/submit/video이미지를 비디오로 변환
POST /mj/submit/edits마스크를 사용해 이미지 편집

❓ 문제 해결 팁

API 설계와 워크플로를 기준으로, 다음은 자주 발생할 수 있는 문제들입니다:
문제가능한 원인해결 방법
Vary (Region) 버튼을 찾을 수 없음4분할 그리드 이미지를 보고 있음먼저 업스케일(U1-U4 클릭)한 뒤 버튼 확인
작업 상태가 MODAL에 멈춤작업에 추가 입력이 필요함필요한 데이터와 함께 /mj/submit/modal 호출
customId가 작동하지 않음오래되었거나 하드코딩된 값을 사용 중항상 /mj/task/\{id\}/fetch 응답에서 최신 customId를 가져오세요
buttons 배열이 비어 있음작업이 아직 진행 중임버튼에 접근하기 전에 status: "SUCCESS"를 기다리세요