Music Tools

Beta 0.1.0 · OpenAPI 3.1.0

BeatMusic Music API

Download OpenAPI Document

Private beta. Generate, extend, cover, replace and task status are live for approved accounts. Audio is delivered as M4A. Endpoints marked Coming soon are not live yet. Request access

Create a task with your API key, then poll its status. The API uses its own prepaid balance; a failed task is refunded once. Songs stay available for 30 days.

Server
https://beatmusic.ai/api/v1
Authentication
Bearer token in the Authorization header. Required.

Safe retries

Send an Idempotency-Key header (up to 200 characters) on paid calls. Repeating the same key with the same body returns the original task with status 200 and Idempotent-Replayed: true, without a second charge. The same key with a different body returns 409.

Task statuses

pendingComplete: noCharged and being submitted.
runningComplete: noGenerating, or copying audio to our storage.
partialComplete: yesFewer songs than expected finished. Not refunded.
succeededComplete: yesAll songs finished; audio_url is an HTTPS link to an M4A (AAC/Opus) file.
failedComplete: yesNothing was delivered. The full price is refunded once.

Errors

Errors return {"error": {"code", "message", "request_id"}}. A refused request is never charged.

400invalid_requestA parameter is missing or invalid.
401invalid_api_keyMissing, wrong or revoked key.
402insufficient_balanceBalance is below the price.
403song_not_ownedsong_id is not a finished song of your account.
403account_frozenThe account is frozen.
409idempotency_conflictIdempotency-Key reused with a different body.
429rate_limitedToo many requests, or too many tasks in progress (3 by default).
503service_pausedEndpoint paused or not live yet.

Task response

JSON
{
  "task_id": "3f9c2a7e-1b4d-4c8a-9e21-7d5b0c6a8f10",
  "endpoint": "generate",
  "status": "succeeded",
  "is_complete": true,
  "cost_usd": 0.095,
  "refunded": false,
  "error": null,
  "created_at": "2026-11-06T08:00:00.000Z",
  "completed_at": "2026-11-06T08:01:02.000Z",
  "songs": [
    {
      "song_id": "8a1d4f0c-2e6b-4b7a-a3c9-5f2e1d0b9c84",
      "title": "New City",
      "tags": "indie pop, upbeat",
      "lyrics": "[Verse] ...",
      "duration_s": 168.4,
      "audio_url": "https://cdn.beatmusic.ai/api-music/....m4a",
      "image_url": "https://cdn.beatmusic.ai/api-music/images/....jpeg",
      "expires_at": "2026-12-06T08:01:02.000Z",
      "license": {
        "type": "commercial",
        "certificate_id": "BM-2026-8A1D4F0C",
        "licensee": "BeatMusic API Customer",
        "certificate_url": "https://beatmusic.ai/api/v1/certificates/8a1d4f0c-2e6b-4b7a-a3c9-5f2e1d0b9c84",
        "terms_url": "https://beatmusic.ai/terms-of-service"
      }
    }
  ]
}

Generate musicLive

POST /music/generate

Create full songs with vocals or instrumentals from a prompt or your own lyrics.

Price: $0.095 / call · Output: 2 songs

Parameters

  • mode "simple" | "custom" required

    simple writes the song from your prompt; custom uses your lyrics and style.

  • model "pro" | "lite" optional

    Music model. Defaults to pro.

  • prompt string optional

    Song description in simple mode (up to 500 characters), or lyrics in custom mode (up to 5,000). Required unless custom mode is instrumental.

  • style string optional

    Genre, mood and instruments. Up to 1,000 characters.

  • title string optional

    Song title. Up to 100 characters.

  • instrumental boolean optional

    Set true for a track with no vocals.

  • vocal_gender "m" | "f" optional

    Preferred vocal gender.

  • negative_tags string optional

    Styles to avoid. Up to 500 characters.

  • style_weight number optional

    How closely to follow the style, from 0 to 1.

  • weirdness number optional

    How experimental the result is, from 0 to 1.

  • licensee string optional

    Name printed as the holder on each song's license certificate, such as your customer. Up to 100 characters. Defaults to "BeatMusic API Customer".

cURL
curl -X POST https://beatmusic.ai/api/v1/music/generate \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"mode":"simple","model":"pro","prompt":"An upbeat indie pop song about moving to a new city","instrumental":false}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/music/generate', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"mode":"simple","model":"pro","prompt":"An upbeat indie pop song about moving to a new city","instrumental":false}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/music/generate",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"mode":"simple","model":"pro","prompt":"An upbeat indie pop song about moving to a new city","instrumental":False},
)
print(response.json())

Extend musicLive

POST /music/extend

Continue a song from a chosen point, keeping its voice and style.

Price: $0.095 / call · Output: 2 songs

Parameters

  • song_id string required

    A song_id from a finished task of your account.

  • continue_at number required

    Second to continue from.

  • mode "simple" | "custom" required

    simple writes the song from your prompt; custom uses your lyrics and style.

  • model "pro" | "lite" optional

    Music model. Defaults to pro.

  • prompt string optional

    Song description in simple mode (up to 500 characters), or lyrics in custom mode (up to 5,000). Required unless custom mode is instrumental.

  • style string optional

    Genre, mood and instruments. Up to 1,000 characters.

  • title string optional

    Song title. Up to 100 characters.

  • instrumental boolean optional

    Set true for a track with no vocals.

  • vocal_gender "m" | "f" optional

    Preferred vocal gender.

  • negative_tags string optional

    Styles to avoid. Up to 500 characters.

  • style_weight number optional

    How closely to follow the style, from 0 to 1.

  • weirdness number optional

    How experimental the result is, from 0 to 1.

  • licensee string optional

    Name printed as the holder on each song's license certificate, such as your customer. Up to 100 characters. Defaults to "BeatMusic API Customer".

cURL
curl -X POST https://beatmusic.ai/api/v1/music/extend \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"song_id":"1024","continue_at":60,"mode":"custom","style":"Indie pop","prompt":"[Final chorus] A bigger ending"}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/music/extend', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"song_id":"1024","continue_at":60,"mode":"custom","style":"Indie pop","prompt":"[Final chorus] A bigger ending"}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/music/extend",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"song_id":"1024","continue_at":60,"mode":"custom","style":"Indie pop","prompt":"[Final chorus] A bigger ending"},
)
print(response.json())

Cover musicLive

POST /music/cover

Record a song again in a new style while keeping its melody.

Price: $0.095 / call · Output: 2 songs

Parameters

  • song_id string required

    A song_id from a finished task of your account.

  • audio_weight number optional

    How closely to follow the source, from 0 to 1.

  • mode "simple" | "custom" required

    simple writes the song from your prompt; custom uses your lyrics and style.

  • model "pro" | "lite" optional

    Music model. Defaults to pro.

  • prompt string optional

    Song description in simple mode (up to 500 characters), or lyrics in custom mode (up to 5,000). Required unless custom mode is instrumental.

  • style string optional

    Genre, mood and instruments. Up to 1,000 characters.

  • title string optional

    Song title. Up to 100 characters.

  • instrumental boolean optional

    Set true for a track with no vocals.

  • vocal_gender "m" | "f" optional

    Preferred vocal gender.

  • negative_tags string optional

    Styles to avoid. Up to 500 characters.

  • style_weight number optional

    How closely to follow the style, from 0 to 1.

  • weirdness number optional

    How experimental the result is, from 0 to 1.

  • licensee string optional

    Name printed as the holder on each song's license certificate, such as your customer. Up to 100 characters. Defaults to "BeatMusic API Customer".

cURL
curl -X POST https://beatmusic.ai/api/v1/music/cover \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"song_id":"1024","mode":"custom","style":"Warm acoustic folk","prompt":"Keep the original lyrics"}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/music/cover', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"song_id":"1024","mode":"custom","style":"Warm acoustic folk","prompt":"Keep the original lyrics"}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/music/cover",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"song_id":"1024","mode":"custom","style":"Warm acoustic folk","prompt":"Keep the original lyrics"},
)
print(response.json())

Replace a sectionLive

POST /music/replace

Rewrite one part of a song (10 to 120 seconds) and keep the rest. You get back 2 full-length versions, not just the clip.

Price: $0.0475 / call · Output: 2 full songs

Parameters

  • song_id string required

    A song_id from a finished task of your account.

  • full_lyrics string required

    The complete lyrics of the song, with the new lyrics already in place. Up to 5,000 characters.

  • section_lyrics string required

    Only the new lyrics sung between start_s and end_s. Up to 2,000 characters.

  • style string required

    Style of the song.

  • title string required

    Song title.

  • start_s number required

    Second where the replaced part starts.

  • end_s number required

    Second where the replaced part ends: 10 to 120 seconds after start_s, and within the song.

  • model "pro" | "lite" optional

    Music model. Defaults to pro.

  • negative_tags string optional

    Styles to avoid. Up to 500 characters.

  • licensee string optional

    Name printed as the holder on each song's license certificate, such as your customer. Up to 100 characters. Defaults to "BeatMusic API Customer".

cURL
curl -X POST https://beatmusic.ai/api/v1/music/replace \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"song_id":"1024","full_lyrics":"[Verse] Packing boxes in the rain\n[Chorus] New city, new name\n[Outro] Home again","section_lyrics":"[Chorus] New city, new name","style":"Indie pop","title":"New City","start_s":30,"end_s":52}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/music/replace', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"song_id":"1024","full_lyrics":"[Verse] Packing boxes in the rain\n[Chorus] New city, new name\n[Outro] Home again","section_lyrics":"[Chorus] New city, new name","style":"Indie pop","title":"New City","start_s":30,"end_s":52}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/music/replace",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"song_id":"1024","full_lyrics":"[Verse] Packing boxes in the rain\n[Chorus] New city, new name\n[Outro] Home again","section_lyrics":"[Chorus] New city, new name","style":"Indie pop","title":"New City","start_s":30,"end_s":52},
)
print(response.json())

Split stemsComing soon

POST /audio/stems

Split a song into vocals and instrumental, or into 12 separate tracks.

Price: Shared with beta users · Output: 2 or 12 stems

Parameters

  • song_id string required

    A song_id from a finished task of your account.

  • stems 2 | 12 required

    Number of stems.

cURL
curl -X POST https://beatmusic.ai/api/v1/audio/stems \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"song_id":"1024","stems":2}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/audio/stems', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"song_id":"1024","stems":2}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/audio/stems",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"song_id":"1024","stems":2},
)
print(response.json())

Convert to WAVComing soon

POST /audio/wav

Get a lossless WAV file of a generated song.

Price: Shared with beta users · Output: 1 WAV file

Parameters

  • song_id string required

    A song_id from a finished task of your account.

cURL
curl -X POST https://beatmusic.ai/api/v1/audio/wav \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"song_id":"1024"}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/audio/wav', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"song_id":"1024"}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/audio/wav",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"song_id":"1024"},
)
print(response.json())

Convert to MIDIComing soon

POST /audio/midi

Get note data for each instrument in a song.

Price: Shared with beta users · Output: MIDI note data

Parameters

  • song_id string required

    A song_id from a finished task of your account.

cURL
curl -X POST https://beatmusic.ai/api/v1/audio/midi \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"song_id":"1024"}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/audio/midi', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"song_id":"1024"}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/audio/midi",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"song_id":"1024"},
)
print(response.json())

Generate lyricsComing soon

POST /lyrics/generate

Write song lyrics from a short idea.

Price: Shared with beta users · Output: Structured lyrics

Parameters

  • prompt string required

    What the song is about.

cURL
curl -X POST https://beatmusic.ai/api/v1/lyrics/generate \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"A song about leaving home for the first time"}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/lyrics/generate', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"prompt":"A song about leaving home for the first time"}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/lyrics/generate",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"prompt":"A song about leaving home for the first time"},
)
print(response.json())

Get timed lyricsComing soon

POST /lyrics/timestamped

Get lyrics with timestamps for karaoke views and subtitles.

Price: Shared with beta users · Output: Word timings

Parameters

  • song_id string required

    A song_id from a finished task of your account.

  • lyrics string required

    Lyrics of the song.

cURL
curl -X POST https://beatmusic.ai/api/v1/lyrics/timestamped \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"song_id":"1024","lyrics":"The complete lyrics"}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/lyrics/timestamped', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"song_id":"1024","lyrics":"The complete lyrics"}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/lyrics/timestamped",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"song_id":"1024","lyrics":"The complete lyrics"},
)
print(response.json())

Boost a styleComing soon

POST /style/boost

Turn a few words into a detailed style description.

Price: Shared with beta users · Output: Expanded style

Parameters

  • style string required

    A short style idea.

cURL
curl -X POST https://beatmusic.ai/api/v1/style/boost \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"style":"dreamy synth pop"}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/style/boost', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"style":"dreamy synth pop"}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/style/boost",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"style":"dreamy synth pop"},
)
print(response.json())

Read task statusLive

POST /tasks/status

Check up to 20 tasks. Audio URLs appear when a task is complete.

Price: Free · Output: Task and song details

Parameters

  • task_ids string[] required

    Task ids, 1 to 20 at a time.

cURL
curl -X POST https://beatmusic.ai/api/v1/tasks/status \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"task_ids":["3f9c2a7e-1b4d-4c8a-9e21-7d5b0c6a8f10"]}'
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/tasks/status', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"task_ids":["3f9c2a7e-1b4d-4c8a-9e21-7d5b0c6a8f10"]}),
});
console.log(await response.json());
Python
import os, requests

response = requests.post(
    "https://beatmusic.ai/api/v1/tasks/status",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
    json={"task_ids":["3f9c2a7e-1b4d-4c8a-9e21-7d5b0c6a8f10"]},
)
print(response.json())

Read balanceComing soon

GET /balance

Check the remaining balance on your API account.

Price: Free · Output: Remaining balance

Parameters

This endpoint has no parameters.

cURL
curl https://beatmusic.ai/api/v1/balance \
  -H "Authorization: Bearer $BEATMUSIC_API_KEY"
Node.js
const response = await fetch('https://beatmusic.ai/api/v1/balance', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.BEATMUSIC_API_KEY}`,
  },
});
console.log(await response.json());
Python
import os, requests

response = requests.get(
    "https://beatmusic.ai/api/v1/balance",
    headers={"Authorization": f"Bearer {os.environ['BEATMUSIC_API_KEY']}"},
)
print(response.json())