How to Generate AI Music with the Mureka API (Suno / Udio Alternative)

7 min read β€’ June 22, 2026

Table of contents

  1. Introduction
  2. Pricing
  3. Supported models
  4. Generate a song in two API calls
  5. Write your own lyrics, or force an instrumental
  6. Reference tracks, melody seeding, and custom vocals
  7. Clone a voice and generate multi-speaker speech
  8. Batch-generate with a script
  9. Examples
  10. Frequently asked questions
  11. Conclusion

Introduction

Mureka AI turns a single text prompt into a complete, produced song β€” a direct Suno and Udio alternative β€” and the useapi.net Mureka API drives your own Mureka account over plain REST, with its latest V9 default and flagship O2 models, at your normal consumer subscription price. Mureka is the music generator from Chinese tech company Kunlun Tech, built on its proprietary Mureka models (mureka-9, mureka-o2). One generation returns two complete songs β€” vocals, melody, and arrangement β€” and from there you can write your own lyrics, force an instrumental, seed a track from a reference song or melody, extend a song, or clone a voice for text-to-speech. useapi.net runs all of it from one API token.

Pricing

You keep your normal Mureka web subscription for the underlying credits, plus a single flat $15/month to useapi.net that covers API access to every supported service β€” there is no per-song surcharge from us. Mureka’s own subscription plans:

Plan Price Songs / month Cost per song
Pro $9/month up to 500 ~1.8Β’
Premier $27/month up to 2,000 ~1.35Β’

Song and speech allowances are shared (songs or speech minutes), lyrics generation is free, and downloading instrumentals and stems is free. The newer V9 and O2 models consume more Gold per song, so real counts run lower β€” roughly 250–400 songs on V9/O2. Pro/Premier members can buy additional Gold packs (price shown at checkout).

This is the consumer-account route. Mureka also runs an official developer API, but it works differently β€” it is sold as prepaid top-ups with 12-month validity, consumed per call rather than billed monthly, and the ladder runs from $30 (1 concurrent request) up to $30,000 (150 concurrent), with the $1,000 tier giving 5 concurrent. Generation there runs ~$0.045/song on V8/V9/O2 (~$0.03 on the older V7.6), plus extra charges for lyrics generation and stem export. useapi.net instead automates the consumer plan you already pay for, so a $27 Premier plan plus the flat $15 covers far more generation than the official API’s entry tier. For other music options under the same subscription, see the Flow Music API tutorial (Google’s Lyria 3 Pro) and the TemPolor API.

Supported models

Pick a model per request with the model field on POST /music/create. Omit it and the API applies its default, V9.

Model Engine What it’s for
V9 (default) mureka-9 Latest generation, used when model is omitted β€” advanced prompt control and studio-grade sound.
O2 mureka-o2 Flagship high-end model β€” best audio quality and musical coherence, with strong multilingual vocals.
V8 mureka-8.0.1 Prior-generation general-purpose model.
V7.6 mureka-7.6 Earlier model kept for compatibility β€” it was the default before V9.

Older aliases (V7.5, V7, O1, V6) are still accepted but redirect to current engines, so prefer the four models above. Every model returns finished MP3 audio β€” there is no MIDI or sheet-music output. The same account and token also drive Mureka’s text-to-speech and voice cloning, covered below.

Generate a song in two API calls

You need a useapi.net API token and a connected Mureka account β€” export the token so the curl examples below run as-is:

export USEAPI_TOKEN="user:1234-..."

The most reliable workflow is asynchronous: the create call returns a jobid immediately, then you poll until both songs are ready.

1. Submit the job β€” POST https://api.useapi.net/v1/mureka/music/create:

curl -X POST "https://api.useapi.net/v1/mureka/music/create" \
  -H "Authorization: Bearer $USEAPI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "account": "12345678901234",
    "prompt": "upbeat synthwave with bright female vocals about chasing a sunrise, 110 bpm",
    "model": "V9",
    "async": true
  }'

The account is your Mureka account id, and it is optional when you have a single account configured (the API auto-selects it). In async mode the response returns immediately with 201 Created, a jobid, and status: "created":

{
  "jobid": "j0622184042017475905m-u1234-a12345678901234-bot:mureka",
  "verb": "music/create",
  "jobType": "music",
  "status": "created",
  "created": "2026-06-22T18:40:42.412Z",
  "request": {
    "account": "12345678901234",
    "prompt": "upbeat synthwave with bright female vocals about chasing a sunrise, 110 bpm",
    "model": "V9",
    "async": true
  }
}

2. Poll for the result β€” GET https://api.useapi.net/v1/mureka/jobs/{jobid} (the jobid ends in bot:mureka, so URL-encode it in the path β€” it contains a :):

curl "https://api.useapi.net/v1/mureka/jobs/JOBID" \
  -H "Authorization: Bearer $USEAPI_TOKEN"

When status is completed, the finished audio lives in response.songs[]. Each generation returns two songs (an A/B pair, version "1" and "2"), and each carries an mp3_url plus cover art:

{
  "jobid": "j0622184042017475905m-u1234-a12345678901234-bot:mureka",
  "status": "completed",
  "response": {
    "feed_id": 11223344,
    "state": 3,
    "songs": [
      {
        "song_id": "user:1234-mureka:123456789-song:33445566",
        "title": "Chasing the Sunrise",
        "version": "1",
        "duration_milliseconds": 173040,
        "mp3_url": "https://static-cos.mureka.ai/cos-prod/...1.mp3",
        "cover": "https://static-cos.mureka.ai/cos-prod/...1.png"
      },
      {
        "song_id": "user:1234-mureka:123456789-song:33445567",
        "title": "Chasing the Sunrise",
        "version": "2",
        "duration_milliseconds": 178910,
        "mp3_url": "https://static-cos.mureka.ai/cos-prod/...2.mp3",
        "cover": "https://static-cos.mureka.ai/cos-prod/...2.png"
      }
    ]
  }
}

A song typically finishes in 30–90 seconds (about 45 on average), and an account supports up to 10 parallel generations. Songs can run up to about 5 minutes depending on the lyrics. Jobs are retained for 7 days, so you can re-fetch a finished result any time in that window. Prefer not to poll? Pass a replyUrl in the create body to receive a webhook callback when the job completes (the payload matches the poll response). A job can come back status: "failed" (e.g. a content-policy rejection), and the create call may return 402 (useapi.net subscription expired) / 412 (out of Mureka credits), 429 (rate limit, or all 10 generation slots busy), or 596 (account session error) β€” see the endpoint docs for the full list.

Write your own lyrics, or force an instrumental

The plain prompt on POST /music/create lets the model write the lyrics for you. To supply your own words, switch to POST /music/create-advanced β€” lyrics is required there (use [Verse] / [Chorus] tags, 50–5,000 chars), and desc steers the style with a comma-separated list of genres, moods, and vocal direction. vocal_gender forces male or female:

# Your own lyrics β†’ forces a vocal render of those exact words
curl -X POST "https://api.useapi.net/v1/mureka/music/create-advanced" \
  -H "Authorization: Bearer $USEAPI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "lyrics": "[Verse 1]\nCity lights blur in the rain\n[Chorus]\nAnd I will wait for the morning sun",
    "desc": "soulful R&B, lush keys, 90 bpm",
    "vocal_gender": "female",
    "model": "V9",
    "async": true
  }'

For a purely instrumental track, use POST /music/create-instrumental β€” just a prompt describing the music, no lyrics:

curl -X POST "https://api.useapi.net/v1/mureka/music/create-instrumental" \
  -H "Authorization: Bearer $USEAPI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "prompt": "ethereal post-rock, cascading delay guitars, orchestral swells building to a cinematic crescendo", "model": "O2", "async": true }'

All three endpoints return the same jobid you poll on, and any resulting song_id can be lengthened with POST /music/extend (pass the song_id plus new lyrics) or reworked with POST /music/regenerate.

Reference tracks, melody seeding, and custom vocals

POST /music/create-advanced can seed a song from your own audio instead of a text description, using three reference inputs (each mutually exclusive with desc):

Parameter Seed from Set it up with
ref_id A reference track whose style inspires the song POST /files (upload), GET /music/refs (browse)
motif_id A melody idea that kickstarts the song POST /files/motif
vocal_id A specific singing voice, including your own uploaded vocal POST /files/vocal, GET /music/vocals

This is how you make Mureka sing your custom lyrics in a voice you supply β€” upload an MP3 vocal sample, take the returned id, and pass it as vocal_id alongside your lyrics. The same Pro-tier reference features (custom soundtracks and melodies) that the Mureka website offers are all reachable from the API.

Clone a voice and generate multi-speaker speech

The same account also drives Mureka’s text-to-speech. POST /speech turns text into audio with either a preset or a cloned voice, and unlike music generation it has no concurrency (generation-slot) limit. Clone a voice first from an MP3 sample with POST /speech/voice, then pass the returned id as the voice_id parameter with your text:

curl -X POST "https://api.useapi.net/v1/mureka/speech" \
  -H "Authorization: Bearer $USEAPI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "text": "Hello, this is a cloned voice speaking.", "voice_id": 12345, "async": true }'

For a back-and-forth dialogue, drop text/voice_id and send a conversation array instead β€” each turn names its own voice_id, so two or more cloned voices can talk to each other in one render:

curl -X POST "https://api.useapi.net/v1/mureka/speech" \
  -H "Authorization: Bearer $USEAPI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "conversation": "[{\"voice_id\": 12345, \"text\": \"Is there anything I can help you with?\"}, {\"voice_id\": 67890, \"text\": \"Yes β€” read me back the weather.\"}]",
    "async": true
  }'

Speech jobs poll the same way, with the finished MP3 in response.mp3_url. See GET /speech/voices for the available voices, including the ones you have cloned.

Batch-generate with a script

Finding the right track takes many attempts, and running them by hand is tedious. The Node.js script below reads a list of prompts from prompts.json, submits each one to POST /music/create in async mode, polls every job until it is done, then downloads both MP3s from each generation β€” so you can queue a batch and come back to a folder of finished songs.

You need Node.js v21 or newer. Put prompts.json and mureka.mjs in the same folder and run node ./mureka.mjs API_TOKEN, where API_TOKEN is your useapi.net API token. With more than one Mureka account configured, pass the account id (or its Google email) as a second argument β€” with a single account it is auto-selected. Each entry’s prompt is required, and the optional model maps straight to the create endpoint.

Expand prompts.json
[
    {
        "prompt": "When model is omitted the V9 default is used. lo-fi hip hop, mellow piano, rainy-day mood, 80 bpm"
    },
    {
        "model": "V9",
        "prompt": "upbeat synthwave with bright female vocals about chasing a sunrise, 110 bpm. For all parameters see https://useapi.net/docs/api-mureka-v1/post-mureka-music-create"
    },
    {
        "model": "O2",
        "prompt": "cinematic orchestral score, soaring strings, epic brass, building to a triumphant finale"
    },
    {
        "model": "V7.6",
        "prompt": "acoustic folk ballad, fingerpicked guitar, warm male vocals, nostalgic. To write your own lyrics use POST /music/create-advanced; for an instrumental use POST /music/create-instrumental"
    }
]
Expand mureka.mjs script
/*

Script version 1.0, June 22, 2026

Script to batch-generate songs using prompts with the Mureka API v1 by useapi.net πŸš€
Uses POST /music/create in asynchronous (fire-and-forget) mode, then polls each job
until it is final and downloads every generated MP3 (each generation returns two songs).
For more details visit https://useapi.net/docs/api-mureka-v1/post-mureka-music-create

Installation Instructions:
==========================

You need Node.js v21 or newer installed to run this script. Download and install Node.js from:

- Windows, macOS, Linux: https://nodejs.org/

After installation, verify by running the following command in a terminal:

   node -v

Running the Script:
===================

Usage: node mureka.mjs <API_TOKEN> [ACCOUNT] [PROMPTS_FILE]

Replace API_TOKEN with your actual useapi.net API token, see https://useapi.net/docs/start-here/setup-useapi
ACCOUNT is optional β€” your Mureka account id or its Google email, see https://useapi.net/docs/start-here/setup-mureka
  It is only required when more than one Mureka account is configured. With a single account it is auto-selected.
If optional PROMPTS_FILE not provided prompts.json will be used.

Example:
--------

node mureka.mjs user:1234-abcdefhijklmnopqrstuv

This command executes the script using API token user:1234-abcdefhijklmnopqrstuv and the only configured account.

Changelog:
==========

- June 22, 2026: Initial release.

*/

import readline from 'node:readline';
import fs from 'fs/promises';
import { writeFile } from 'node:fs/promises';
import { Readable } from 'node:stream';


// Constants
const RESULTS_FILE = 'mureka_results.txt';
const ERRORS_FILE = 'mureka_errors.txt';
const DEFAULT_PROMPTS_FILE = 'prompts.json';
const SLEEP_429 = 10 * 1000; // in milliseconds β€” wait between rate-limit / concurrent-limit retries
const MAX_429_RETRIES = 6;   // give up a prompt after this many consecutive 429s (all slots busy)
const SLEEP_POLL = 15 * 1000; // in milliseconds β€” a song takes ~45 seconds on average to generate

// Current Mureka models for POST /music/create. V9 is the API default when model is omitted.
// The API also accepts older aliases (V7.5, V7, O1, V6) that map to current engines β€” add any
// you want to use here. See https://useapi.net/docs/api-mureka-v1/post-mureka-music-create
const SUPPORTED_MODELS = ['V9', 'V8', 'O2', 'V7.6'];

const urlAccounts = 'https://api.useapi.net/v1/mureka/accounts';
const urlMusicCreate = 'https://api.useapi.net/v1/mureka/music/create';
const urlJobs = 'https://api.useapi.net/v1/mureka/jobs/';

// Utility to sleep for given milliseconds
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// Function to fetch configured Mureka API accounts
async function fetchAccounts(apiToken) {
    const response = await fetch(urlAccounts, {
        headers: {
            'Accept': 'application/json',
            'Authorization': `Bearer ${apiToken}`
        }
    });

    if (!response.ok) {
        console.error(`β›” Error fetching accounts (HTTP ${response.status}): ${response.statusText}`);
        process.exit(1);
    }

    return response.json();
}

// Submit a single prompt to POST /music/create in async mode. Returns { status, jobid }.
async function submitMusic(apiToken, account, prompt, index) {
    const { model, prompt: text } = prompt;

    console.log(`πŸš€ ${model ?? 'default (V9)'} Β» Prompt #${index} β€’ account ${account} …`);

    // model is omitted from the body when not specified, so the API applies its own default (V9).
    const body = JSON.stringify({
        account,
        prompt: text,
        model,
        async: true
    });

    const createResponse = await fetch(urlMusicCreate, {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${apiToken}`
        },
        body
    });

    const createBody = await createResponse.text();

    // async:true β†’ 201 Created with { jobid, status:'created', … }.
    // (200 OK would be the synchronous result and also carries a jobid β€” handled too.)
    if (createResponse.status == 200 || createResponse.status == 201) {
        const json = JSON.parse(createBody);
        const { jobid } = json;
        if (jobid) {
            await fs.appendFile(RESULTS_FILE, `${jobid},#${index}:${text ?? ''}\n`);
            console.log(`βœ… jobid`, jobid);
            return { status: createResponse.status, jobid };
        } else {
            const error = `No jobid found in HTTP ${createResponse.status} response`;
            console.log(`❓ ${error}`, createBody);
            await fs.appendFile(ERRORS_FILE, `${error},#${index}:${text ?? ''}\n`);
            return { status: 500 };
        }
    } else {
        switch (createResponse.status) {
            case 429:
                console.log(`πŸ”„οΈ Retry on HTTP ${createResponse.status} (rate limit or all generation slots busy)`);
                break;
            case 400:
                console.log(`πŸ›‘ Validation error`, createBody);
                await fs.appendFile(ERRORS_FILE, `${createResponse.status},#${index}:${text ?? ''}\n`);
                break;
            case 402:
            case 412:
                console.log(`πŸ›‘ Subscription expired or insufficient credits`, createBody);
                await fs.appendFile(ERRORS_FILE, `${createResponse.status},#${index}:${text ?? ''}\n`);
                break;
            case 596:
                console.log(`πŸ›‘ Account session expired β€” re-add the account at https://useapi.net/docs/api-mureka-v1/post-mureka-accounts`, createBody);
                await fs.appendFile(ERRORS_FILE, `${createResponse.status},#${index}:${text ?? ''}\n`);
                break;
            default:
                console.log(`❗ FAILED with HTTP ${createResponse.status}`, createBody);
                await fs.appendFile(ERRORS_FILE, `${createResponse.status},#${index}:${text ?? ''}\n`);
        }
        return { status: createResponse.status };
    }
}

// Download a single mp3_url to disk.
async function downloadMp3(url, filename, jobid, prompt) {
    try {
        await fs.access(filename);
        console.log(`⚠️ ${filename} already exists. Skipping download.`);
        return;
    } catch {
        // File does not exist, proceed with downloading
    }

    console.log(`βœ… Downloading ${url} to ${filename}`);
    try {
        const audioResponse = await fetch(url);
        if (!audioResponse.ok) {
            console.error(`β›” Unable to download ${jobid} (HTTP ${audioResponse.status}):\n${prompt}\n`, url);
            return;
        }
        const stream = Readable.fromWeb(audioResponse.body);
        await writeFile(filename, stream);
    } catch (err) {
        console.error(`β›” Error during download: ${err}`);
    }
}

// Poll every submitted job until it is final, then download each generated song's MP3.
async function download(apiToken) {
    if (! await fileExists(RESULTS_FILE)) return;

    try {
        const resultsContent = await fs.readFile(RESULTS_FILE, 'utf8');
        const lines = resultsContent.trim().split('\n');

        for (const line of lines) {
            const commaAt = line.indexOf(',');
            const jobid = commaAt === -1 ? line : line.slice(0, commaAt);
            const prompt = commaAt === -1 ? '' : line.slice(commaAt + 1);
            // jobid contains ':' (…-bot:mureka) β€” make a filesystem-safe base name.
            const safeJob = jobid.replace(/[:]/g, '_');

            console.log(`πŸ‘‰ ${jobid}`);

            while (true) {
                const response = await fetch(`${urlJobs}${encodeURIComponent(jobid)}`, {
                    headers: {
                        'Accept': 'application/json',
                        'Authorization': `Bearer ${apiToken}`
                    }
                });

                if (!response.ok) {
                    // 404 = job not found or expired (jobs are retained for 7 days).
                    console.log(`πŸ›‘ Poll failed ${jobid} (HTTP ${response.status}):\n${prompt}\n`, await response.text());
                    break;
                }

                const job = await response.json();
                const { status, response: result, error, errorDetails } = job;

                if (status == 'failed') {
                    console.error(`πŸ›‘ FAILED ${jobid} (${error ?? 'unknown error'}${errorDetails ? ` β€” ${errorDetails}` : ''}):\n${prompt}\n`);
                    break;
                }

                if (status == 'completed') {
                    const songs = result?.songs ?? [];

                    if (songs.length === 0) {
                        console.error(`πŸ›‘ Job ${jobid} completed but returned no songs:\n${prompt}\n`);
                        break;
                    }

                    // Each generation returns two songs (version "1" and "2") β€” download both.
                    for (let i = 0; i < songs.length; i++) {
                        const song = songs[i];
                        const url = song?.mp3_url;
                        const variant = song?.version ?? (i + 1);
                        const filename = `${safeJob}_v${variant}.mp3`;

                        if (url)
                            await downloadMp3(url, filename, jobid, prompt);
                        else
                            console.error(`πŸ›‘ No mp3_url for song ${i + 1} of ${jobid}:\n${prompt}\n`);
                    }

                    break;
                }

                console.log(`βŒ› ${jobid} status (${status ?? 'created'}) and is still in progress, waiting…`);
                await sleep(SLEEP_POLL);
            }
        }
    } catch (error) {
        console.log(`β›” Error during download:`, error.stack || error);
    }
}

// Main function
async function main() {
    const apiToken = process.argv[2];
    const accountArg = process.argv[3];
    const promptFile = process.argv[4] || DEFAULT_PROMPTS_FILE;

    if (!apiToken) {
        console.error('Usage: node mureka.mjs <API_TOKEN> [ACCOUNT] [PROMPTS_FILE]');
        process.exit(1);
    }

    console.info('Script v1.0');

    console.info('Node version is: ' + process.version);

    try {
        if (await fileExists(RESULTS_FILE)) {
            let user_input;
            while (!['y', 'n'].includes(user_input)) {
                user_input = (await promptUser(`❔ ${RESULTS_FILE} file detected. Do you want to download the results now? (y/n): `))?.toLowerCase();
                if (user_input == 'y') {
                    await download(apiToken);
                    await fs.unlink(RESULTS_FILE);
                }
            }
        }

        const start = new Date();
        try {
            console.info('START EXECUTION', start);
            await execute(apiToken, accountArg, promptFile);
        }
        finally {
            console.info('COMPLETED', new Date());
            console.info('EXECUTION ELAPSED', diffInMinutesAndSeconds(start, new Date()));
        }

        try {
            console.info('START DOWNLOAD', start);
            await download(apiToken);
        }
        finally {
            console.info('TOTAL ELAPSED', diffInMinutesAndSeconds(start, new Date()));
        }
    } catch (error) {
        console.error('β›” Error during execution:', error.stack || error);
    }
}

// Resolve the Mureka account to use: by id or Google email when provided, otherwise the
// single configured account. Returns the numeric account id string sent to the API.
function resolveAccount(accounts, accountArg) {
    const accountList = Object.values(accounts);

    console.info(`Configured Mureka API accounts (${accountList.length}):`, accountList.map(a => a.account).join(', '));

    if (accountList.length <= 0) {
        console.error(`β›” No configured Mureka accounts found. Please refer to https://useapi.net/docs/start-here/setup-mureka`);
        process.exit(1);
    }

    let matched;

    if (accountArg) {
        // Match by Mureka account id or by the account's Google email.
        matched = accountList.find(a => a.account === accountArg || a.email === accountArg);
        if (!matched) {
            console.error(`β›” Account "${accountArg}" not found. Please refer to https://useapi.net/docs/start-here/setup-mureka`);
            process.exit(1);
        }
    } else if (accountList.length === 1) {
        matched = accountList[0];
    } else {
        console.error(`β›” ${accountList.length} accounts configured β€” pass the account id or email as the second argument.`);
        process.exit(1);
    }

    if (matched.error) {
        console.error(`β›” Account ${matched.account} has a pending error: ${matched.error}. Re-add it at https://useapi.net/docs/api-mureka-v1/post-mureka-accounts`);
        process.exit(1);
    }

    return matched.account;
}

async function execute(apiToken, accountArg, promptFile) {
    const accounts = await fetchAccounts(apiToken);
    const account = resolveAccount(accounts, accountArg);

    console.info(`Using Mureka account ${account}`);

    const promptData = await fs.readFile(promptFile, 'utf8');
    const prompts = JSON.parse(promptData);
    console.log(`Total number of prompts to process`, prompts.length);

    let warnings = [];

    // Parameters accepted by this script for POST /music/create.
    // See https://useapi.net/docs/api-mureka-v1/post-mureka-music-create for the full parameter set.
    const supportedParams = ['model', 'prompt'];

    const invalidKeys = (prompt) => Object.keys(prompt).filter(key => !key.startsWith('__') && !supportedParams.includes(key));

    for (let i = 1; i <= prompts.length; i++) {
        const prompt = prompts[i - 1];
        const { prompt: text, model } = prompt;

        const notSupported = invalidKeys(prompt);
        if (notSupported.length)
            warnings.push(`⚠️  Following params not supported: ${notSupported.join(',')}. Prompt ${i}`);

        if (!text)
            warnings.push(`⚠️  Please specify a prompt. Prompt ${i}`);

        if (text && text.length > 3000)
            warnings.push(`⚠️  prompt exceeds 3000 characters. Prompt ${i}`);

        if (model && !SUPPORTED_MODELS.includes(model))
            warnings.push(`⚠️  Unknown model "${model}" β€” supported: ${SUPPORTED_MODELS.join(', ')}. Prompt ${i}`);
    }

    if (warnings.length > 0) {
        warnings.forEach(warning => console.warn(warning));
        console.error(`β›” Execution stopped due to warnings.`);
        process.exit(1);
    }

    for (let i = 0; i < prompts.length; i++) {
        const prompt = prompts[i];
        let retries429 = 0;
        while (true) {
            const { status } = await submitMusic(apiToken, account, prompt, i + 1);
            if (status == 429) {
                if (++retries429 > MAX_429_RETRIES) {
                    console.error(`β›” Gave up on prompt #${i + 1} after ${MAX_429_RETRIES} retries β€” all slots still busy.`);
                    await fs.appendFile(ERRORS_FILE, `429 (gave up after ${MAX_429_RETRIES} retries),#${i + 1}\n`);
                    break;
                }
                await sleep(SLEEP_429);
            } else if (status == 402 || status == 412 || status == 596) {
                process.exit(1);
            } else
                break;
        }
    }
}

// Utility function to check if a file exists
async function fileExists(path) {
    try {
        await fs.access(path);
        return true;
    } catch {
        return false;
    }
}

// Function to prompt user input
async function promptUser(query) {
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    return new Promise((resolve) => rl.question(query, answer => {
        rl.close();
        resolve(answer);
    }));
}

function diffInMinutesAndSeconds(date1, date2) {
    const diffInSeconds = Math.floor((date2 - date1) / 1000);
    return `${Math.floor(diffInSeconds / 60)} minutes ${diffInSeconds % 60} seconds`;
};

main();

Examples

These are real songs and speech generated through the Mureka API, straight from our blog walkthroughs β€” each from the request shapes shown above. Full prompts and curl for each are in the linked posts.

Astro Gardener β€” V9, female-vocal indie pop with custom lyrics (create-advanced)

β€” from Mureka: V9 Now the Default Music Model

Cascading Sunrise β€” V9 instrumental (create-instrumental)

β€” from Mureka: V9 Now the Default Music Model

Galactic Odyssey β€” flagship O2 instrumental (create-instrumental)

β€” from Mureka: O2 and V7.6 Music Models

Pirate Programmer β€” V7.6, male-vocal sea-shanty-meets-electronic (create-advanced)

β€” from Mureka: O2 and V7.6 Music Models

Custom vocal clone β€” an uploaded voice singing custom lyrics over a reference track (create-advanced with vocal_id + ref_id)

β€” from Mureka: Custom Vocals

Multi-speaker speech β€” two cloned voices in one conversation (POST /speech)

β€” from Mureka: Speech Generation and Voice Cloning

Frequently asked questions

Is the Mureka API a Suno or Udio alternative? Yes. Like Suno and Udio, Mureka generates full songs with vocals from a single text prompt β€” and the useapi.net Mureka API drives your own Mureka account over plain REST, with the latest V9 default and flagship O2 models, all under one flat $15/month useapi.net subscription. See Supported models above.

Is there an official Mureka API? Yes. Mureka runs an official developer API, sold as prepaid top-ups (12-month validity) consumed per call β€” from $30 (1 concurrent request) up to $30,000 (150), with the $1,000 tier giving 5 concurrent. Generation runs ~$0.045/song on V8/V9/O2 (~$0.03 on V7.6), plus charges for lyrics and stems. useapi.net is the consumer-account route, automating the $9–$27/month Mureka web plan you already pay for. See Pricing above.

Which models can I use? V9 (default), the flagship O2, V8, and V7.6. Omit the model field and the API uses V9. Older aliases (V7.5, V7, O1, V6) still work but redirect to current engines. See Supported models above.

Can I write my own lyrics or generate an instrumental? Yes. Use POST /music/create-advanced with [Verse]/[Chorus]-tagged lyrics to force a vocal render of your exact words, or POST /music/create-instrumental for a lyrics-free track. See Write your own lyrics, or force an instrumental above.

Can I clone a voice or generate speech? Yes. POST /speech/voice clones a voice from an MP3 sample, then POST /speech renders text β€” including multi-speaker conversation dialogues β€” with no concurrency (generation-slot) limit. See Clone a voice and generate multi-speaker speech above.

What do I get back, and in what format? Every music generation returns two complete songs (an A/B pair), each as an mp3_url with cover art, up to about 5 minutes long. The output is finished MP3 audio β€” there is no MIDI or sheet-music export. See Generate a song in two API calls above.

How much does it cost? You keep your normal Mureka web plan for credits (~1.35–1.8Β’ per song), plus a flat $15/month to useapi.net for API access to all services, with no per-song surcharge. See Pricing above.

How is this different from the official Mureka API? The official Mureka API is sold as prepaid top-ups (12-month validity) consumed per call, from $30 up to $30,000, charging ~$0.045/song on V8/V9/O2 (~$0.03 on V7.6) plus lyric and stem fees. useapi.net instead automates your own consumer Mureka account, so you generate at the Mureka website subscription price plus a flat $15/month β€” and the same one subscription covers other AI services too, including the Flow Music and TemPolor music APIs.

Conclusion

Visit our Discord Server or Telegram Channel for any support questions and concerns.

We regularly post guides and tutorials on the YouTube Channel.

The full runnable example is in the mureka-api GitHub repo.

Cross posted