Node.js / TypeScript Tutorial

Midjourney API with Node.js — Complete Guide

Generate AI images with Midjourney in Node.js or TypeScript. This tutorial covers job submission, result polling, and webhook integration with full, copy-paste code examples.

Prerequisites

  • ✓ Node.js 18+ (for built-in fetch) or any Node with node-fetch
  • ✓ A Midjourney API key — get one free here
  • ✓ TypeScript is supported but optional
01

Setup (Node 18+ — no install needed)

// Node 18+ has built-in fetch — no npm install required!
// For older Node versions: npm install node-fetch

const API_KEY = process.env.MIDJOURNEY_API_KEY;
const BASE_URL = 'https://api.midjourney-api.com';
02

Submit an Image Generation Job

async function submitJob(prompt, mode = 'fast') {
  const response = await fetch(`${BASE_URL}/midjourney/v1/submit-jobs`, {
    method: 'POST',
    headers: {
      'API-KEY': API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      prompt,
      mode,       // 'fast' or 'relaxed'
      timeout: 600,
    }),
  });

  const data = await response.json();

  if (data.status !== 0) {
    throw new Error(`API error: ${data.message}`);
  }

  console.log('Job submitted! Task ID:', data.data.taskId);
  return data.data.taskId;
}

// Usage
const taskId = await submitJob('a cyberpunk city at night --ar 16:9 --niji 7');
03

Poll for the Result

async function waitForResult(taskId, maxAttempts = 30, intervalMs = 10000) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const res = await fetch(`${BASE_URL}/midjourney/v1/job-status`, {
      method: 'POST',
      headers: {
        'API-KEY': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ taskIds: [taskId] }),
    });

    const { data } = await res.json();
    const job = data[0];

    if (job.status === 1) {
      // status 1 = success
      console.log('Image URL:', job.image);
      console.log('All images:', job.images);
      return job;
    } else if (job.status === 2) {
      // status 2 = failed
      throw new Error('Job failed');
    }

    console.log(`Attempt ${attempt + 1}: still processing...`);
    await new Promise((r) => setTimeout(r, intervalMs));
  }

  throw new Error('Timeout: job did not complete in time');
}

const result = await waitForResult(taskId);
04

TypeScript Support

// Full TypeScript type definitions

interface SubmitJobRequest {
  prompt: string;
  mode?: 'fast' | 'relaxed';
  hookUrl?: string;
  timeout?: number;
}

interface JobResult {
  taskId: string;
  status: 0 | 1 | 2;   // 0=pending, 1=success, 2=failed
  image?: string;
  images?: string[];
  prompt?: string;
  mjPrompt?: string;
  createdAt?: number;
  meta?: { width: number; height: number };
}

interface ApiResponse<T> {
  status: number;
  message: string;
  data: T;
}

// Typed fetch helper
async function midjourneyRequest<T>(
  path: string,
  body: object
): Promise<ApiResponse<T>> {
  const res = await fetch(`${BASE_URL}${path}`, {
    method: 'POST',
    headers: { 'API-KEY': API_KEY!, 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  });
  return res.json() as Promise<ApiResponse<T>>;
}

🚀 Using with Next.js API Routes

// app/api/generate/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function POST(req: NextRequest) {
  const { prompt } = await req.json();

  const res = await fetch(
    'https://api.midjourney-api.com/midjourney/v1/submit-jobs',
    {
      method: 'POST',
      headers: {
        'API-KEY': process.env.MIDJOURNEY_API_KEY!,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ prompt, mode: 'fast' }),
    }
  );

  const data = await res.json();
  return NextResponse.json(data);
}

Ready to Build Your AI Image App?

Get your free API key and start generating images in minutes.