Suno API
Generate full songs with vocals and lyrics, then extend, cover, mashup, replace sections, split stems, convert to WAV, render MIDI, make music videos, and clone voices. 18 async operations plus 4 instant helpers, one unified task flow.
Suno API
The suno-* model family exposes the complete Suno music toolchain
through one endpoint. Generate a song from a text idea or exact lyrics,
then keep working on it: extend it, re-cover an uploaded track, layer
vocals or instrumentals, mash two songs together, replace a section,
separate stems, convert to WAV, extract MIDI, render a music video, or
clone a singing voice.
Current pricing for every operation is on the Suno model page.
Endpoints
All 18 asynchronous operations share the audio task endpoint — the
model field picks the operation:
POST /api/v1/audio/generationsPoll completion with:
GET /api/v1/tasks/{id}Four synchronous helpers answer inline (no task lifecycle):
POST /api/v1/audio/suno/boost-style
POST /api/v1/audio/suno/timestamped-lyrics
POST /api/v1/audio/suno/persona
POST /api/v1/audio/suno/check-voiceQuick example — generate a song
curl https://reapi.ai/api/v1/audio/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-music",
"customMode": false,
"instrumental": false,
"version": "V5",
"prompt": "A dreamy synthwave track about driving through a neon city at midnight"
}'import requests, time
headers = {"Authorization": "Bearer YOUR_API_KEY"}
task = requests.post(
"https://reapi.ai/api/v1/audio/generations",
headers=headers,
json={
"model": "suno-music",
"customMode": False,
"instrumental": False,
"version": "V5",
"prompt": "A dreamy synthwave track about driving through a neon city at midnight",
},
).json()
while True:
r = requests.get(
f"https://reapi.ai/api/v1/tasks/{task['id']}", headers=headers
).json()
if r["status"] in ("completed", "failed"):
break
time.sleep(5)
print(r["output"]["tracks"])const headers = {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
};
const task = await fetch('https://reapi.ai/api/v1/audio/generations', {
method: 'POST',
headers,
body: JSON.stringify({
model: 'suno-music',
customMode: false,
instrumental: false,
version: 'V5',
prompt:
'A dreamy synthwave track about driving through a neon city at midnight',
}),
}).then((r) => r.json());
let result;
do {
await new Promise((r) => setTimeout(r, 5000));
result = await fetch(`https://reapi.ai/api/v1/tasks/${task.id}`, {
headers,
}).then((r) => r.json());
} while (result.status === 'processing');
console.log(result.output.tracks);package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
)
const key = "YOUR_API_KEY"
func main() {
body, _ := json.Marshal(map[string]any{
"model": "suno-music",
"customMode": false,
"instrumental": false,
"version": "V5",
"prompt": "A dreamy synthwave track about driving through a neon city at midnight",
})
req, _ := http.NewRequest("POST",
"https://reapi.ai/api/v1/audio/generations", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+key)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var task struct {
ID string `json:"id"`
}
json.NewDecoder(resp.Body).Decode(&task)
for {
time.Sleep(5 * time.Second)
poll, _ := http.NewRequest("GET",
"https://reapi.ai/api/v1/tasks/"+task.ID, nil)
poll.Header.Set("Authorization", "Bearer "+key)
pr, err := http.DefaultClient.Do(poll)
if err != nil {
panic(err)
}
var result struct {
Status string `json:"status"`
Output struct {
Tracks []struct {
ID string `json:"id"`
URL string `json:"url"`
Title string `json:"title"`
} `json:"tracks"`
} `json:"output"`
}
json.NewDecoder(pr.Body).Decode(&result)
pr.Body.Close()
if result.Status != "processing" {
fmt.Printf("%+v\n", result.Output.Tracks)
return
}
}
}One generation request returns two tracks. Each track carries an
id you reuse as audioId in every track-referencing operation below.
Modes: inspiration vs custom
Generation-class operations (suno-music, suno-upload-cover,
suno-mashup) run in one of two modes:
customMode: false(inspiration) —prompt(max 500 characters) describes the song idea; Suno writes the lyrics.customMode: true(custom) —promptis used strictly as lyrics;styleandtitlebecome required. Withinstrumental: true,promptis not needed.
Character caps scale with version: prompt 3000 (V4) / 5000
(others), style 200 (V4) / 1000 (others), title 80 (100 on some
extend variants).
Versions
version is required on generation-class operations:
V4, V4_5, V4_5PLUS, V4_5ALL, V5, V5_5.
suno-add-vocals / suno-add-instrumental accept V4_5PLUS / V5 /
V5_5 (default V4_5PLUS); suno-sounds accepts V5 / V5_5.
Referencing earlier work: taskId + audioId
Operations that act on an existing song take:
taskId— your reAPI task id (task_...) of the source task. It must be your own completed task; reAPI resolves it internally.audioId— the track id from that task'soutput.tracks[].id.
Media inputs (uploadUrl, uploadUrlList, voiceUrl, verifyUrl)
accept public HTTP(S) URLs only — no base64 / data URIs.
Operation reference
Every asynchronous operation posts to /api/v1/audio/generations and is
selected by the model field; poll /api/v1/tasks/{id} for the result.
The four synchronous helpers have their own routes and answer inline.
Create
Generate a song
POST /api/v1/audio/generations · model: "suno-music"
Generates a song from a text description — either a short idea the model turns into lyrics, or your own lyrics, style and title — and returns multiple finished audio variations.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-music. |
customMode | boolean | yes | false = inspiration mode (describe an idea, the model writes the lyrics). true = custom mode (you supply style, title and — for vocal tracks — the exact lyrics). |
instrumental | boolean | yes | true generates a track with no lyrics. In custom mode it decides whether prompt is required; in inspiration mode it does not change which fields are required. |
version | string | yes | Model version. One of V4, V4_5, V4_5PLUS, V4_5ALL, V5, V5_5. V4 caps a track at ~4 min and the V4_5* line at ~8 min; V5 / V5_5 publish no length cap. Also selects the prompt / style character limits below. |
prompt | string | conditional | Inspiration mode: the core idea, max 500 characters — required, and the lyrics are written from it rather than matching it word for word. Custom mode: used verbatim as the sung lyrics; required when instrumental is false; max 3000 characters on V4, 5000 on every other version. |
style | string | conditional | Genre, mood or artistic direction (e.g. Classical, Jazz, upbeat). Required in custom mode; max 200 characters on V4, 1000 on every other version. Ignored in inspiration mode. |
title | string | conditional | Track title. Required in custom mode; max 80 characters on all versions. Ignored in inspiration mode. |
negativeTags | string | no | Comma-separated styles or traits to steer away from, e.g. Heavy Metal, Upbeat Drums. |
vocalGender | string | no | m or f. Only effective when customMode is true, and it biases the voice rather than guaranteeing it. |
styleWeight | number | no | How strictly the result adheres to style. 0–1, up to 2 decimal places. |
weirdnessConstraint | number | no | How far the result may deviate creatively. 0–1, up to 2 decimal places. |
audioWeight | number | no | Balance of audio features against the other inputs. 0–1, up to 2 decimal places. |
personaId | string | no | Persona id or voice id to apply to the generated music. Only available when customMode is true. Persona ids come from POST /api/v1/audio/suno/persona; voice ids come from suno-voice-generate. |
personaModel | string | no | style_persona or voice_persona — which kind of persona personaId refers to. Only available on V5 and V5_5. |
Response — on completion, output.audio_urls[] holds one URL per generated variation (usually two). output.tracks[] carries the same items with metadata, index-aligned with audio_urls: type (audio), url, id (the track's audio id — pass it as audioId to extend, WAV, stem-separation, MIDI, music-video and timestamped-lyrics operations), title, duration in seconds, tags (comma-separated style tags), lyrics and image_url (cover art, rehosted alongside the audio). Only url is guaranteed — metadata keys are omitted when upstream returns them empty.
Notes — the two modes have different required sets, and the API enforces them. Inspiration mode (customMode: false) needs only prompt, capped at 500 characters; style and title are ignored. Custom mode (customMode: true) always requires style and title, and additionally requires prompt when instrumental is false — an instrumental custom request is valid with just style and title. Character caps move with version: prompt 3000 on V4 and 5000 elsewhere, style 200 on V4 and 1000 elsewhere; title is 80 on every version. Pricing per generation is listed at https://reapi.ai/models/suno.
Generate lyrics
POST /api/v1/audio/generations · model: "suno-lyrics"
Writes song lyrics from a theme description and returns them as structured text — no audio is produced.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-lyrics. |
prompt | string | yes | Description of the lyrics you want — theme, mood, style or story elements. Max 200 characters. More specific prompts yield more targeted lyrics. |
Response — this task returns text, not audio: there is no audio_urls or tracks. On completion output.result.lyrics[] holds the generated variations (typically 2–3), each an object with title and text. The text body is formatted with standard section markers ([Verse], [Chorus], [Bridge], …), so it can be passed straight into suno-music as prompt in custom mode.
{
"output": {
"result": {
"lyrics": [
{ "title": "Small Town Lights", "text": "[Verse]\n...\n\n[Chorus]\n..." },
{ "title": "Back Then", "text": "[Verse]\n...\n\n[Chorus]\n..." }
]
}
}
}Notes — variations that the upstream model failed to produce are dropped rather than returned as empty entries, so lyrics[] can be shorter than the usual 2–3 items. If none survive, the task fails and the reservation is refunded.
Generate a sound
POST /api/v1/audio/generations · model: "suno-sounds"
Generates a short sound or sound bed — background music, ambience, game SFX — with optional looping, tempo and key control, and returns audio.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-sounds. |
prompt | string | yes | Description of the sound to generate. Max 500 characters. |
version | string | yes | Model version. V5 or V5_5 only — the older versions do not support sound generation. |
soundLoop | boolean | no | Generate the result as a seamless loop, for background music and ambient beds. Defaults to false. |
soundTempo | integer | no | Target tempo in BPM, 1–300. Omit to let the model choose. |
soundKey | string | no | Musical key: Cm, C#m, Dm, D#m, Em, Fm, F#m, Gm, G#m, Am, A#m, Bm, C, C#, D, D#, E, F, F#, G, G#, A, A#, B. Omit for any key. |
grabLyrics | boolean | no | Capture lyric subtitles for the generated audio. Defaults to false. |
Response — same shape as a song: output.audio_urls[] with one URL per generated variation, and output.tracks[] index-aligned with it, each entry carrying the same per-track fields — type (audio), url, id, title, duration in seconds, tags, lyrics and image_url (cover art) — with the empty ones omitted.
Extend & rework
Extend a track
POST /api/v1/audio/generations · model: "suno-extend"
Continues an existing track from a chosen time point, producing a new set of audio variants that keep the source track's style.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-extend. |
defaultParamFlag | boolean | yes | true — extend using the parameters in this request (prompt, style, title, continueAt all become required). false — inherit the source track's parameters; only audioId and version are needed. |
audioId | string | yes | The track to extend. Take it from the parent task's output.tracks[].id. |
version | enum | yes | One of V4, V4_5, V4_5PLUS, V4_5ALL, V5, V5_5. Must match the source track's version. |
prompt | string | conditional | Required when defaultParamFlag is true. Describes how the music should continue or change across the extension. Max 3000 chars on V4, 5000 on every other version. |
style | string | conditional | Required when defaultParamFlag is true. Style of the extended audio; align it with the source track's style for the most consistent result. Max 200 chars on V4, 1000 on every other version. |
title | string | conditional | Required when defaultParamFlag is true. Title of the extended track. Max 80 chars on V4 and V4_5ALL, 100 on every other version. |
continueAt | number | conditional | Required when defaultParamFlag is true. Seconds into the source track where the extension begins. Must be greater than 0 and less than the source track's duration (the upper bound is checked upstream). |
negativeTags | string | no | Styles or traits to keep out of the extension, e.g. Heavy Metal, Upbeat Drums. |
vocalGender | enum | no | m or f. Raises the probability of that vocal gender; it is not a guarantee. |
styleWeight | number | no | 0–1, up to 2 decimal places. Strength of adherence to style. |
weirdnessConstraint | number | no | 0–1, up to 2 decimal places. Controls experimental/creative deviation. |
audioWeight | number | no | 0–1, up to 2 decimal places. Balance of audio features against the other inputs. |
personaId | string | no | Persona ID or Voice ID to apply. Only takes effect when defaultParamFlag is true. |
personaModel | enum | no | style_persona or voice_persona. Only available on V5 and V5_5. |
Response — on completion, output.audio_urls holds the generated audio URLs and output.tracks[] carries one index-aligned entry per variant, each with id (pass this back as audioId in follow-up operations), url, type (audio), title, duration in seconds, tags (comma-separated style tags), lyrics and image_url (cover art).
Notes — the defaultParamFlag matrix is strict: with true, all four of prompt, style, title and continueAt must be present, and the per-version character caps above apply; with false, everything except audioId and version is inherited from the source track. continueAt must be greater than 0.
Cover an uploaded track
POST /api/v1/audio/generations · model: "suno-upload-cover"
Re-records audio you supply in a new style while keeping its core melody, returning the reworked variants.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-upload-cover. |
uploadUrl | string | yes | Public http(s) URL of the source audio. Maximum 8 minutes. Base64 and data: URIs are rejected. |
customMode | boolean | yes | true — supply your own style/title (and prompt when the result has vocals). false — only prompt is used and lyrics are generated from it. |
instrumental | boolean | yes | true produces a track with no lyrics. In custom mode it decides whether prompt is required; in non-custom mode it does not change which fields are required. |
version | enum | yes | One of V4, V4_5, V4_5PLUS, V4_5ALL, V5, V5_5. |
prompt | string | conditional | Required in custom mode when instrumental is false, where it is used verbatim as the lyrics (max 3000 chars on V4, 5000 on every other version). Required in non-custom mode, where it is the core idea lyrics are written from (max 500 chars). |
style | string | conditional | Required in custom mode; the genre or style of the cover, e.g. Jazz, Classical. Max 200 chars on V4, 1000 on every other version. Leave empty in non-custom mode. |
title | string | conditional | Required in custom mode. Max 80 chars on V4 and V4_5ALL, 100 on every other version. Leave empty in non-custom mode. |
negativeTags | string | no | Styles or traits to exclude from the cover. |
vocalGender | enum | no | m or f. Only effective when customMode is true, and only raises the probability of that vocal gender. |
styleWeight | number | no | 0–1, up to 2 decimal places. Strength of adherence to style. |
weirdnessConstraint | number | no | 0–1, up to 2 decimal places. Controls experimental/creative deviation. |
audioWeight | number | no | 0–1, up to 2 decimal places. Balance of audio features against the other inputs. |
personaId | string | no | Persona ID or Voice ID to apply. Only available when customMode is true. |
personaModel | enum | no | style_persona or voice_persona. Only available on V5 and V5_5. |
Response — on completion, output.audio_urls holds the cover's audio URLs and output.tracks[] carries one index-aligned entry per variant, each with id, url, type (audio), title, duration in seconds, tags, lyrics and image_url (cover art).
Notes — the requirement matrix is customMode × instrumental: custom + instrumental needs style and title; custom + vocals needs style, title and prompt; non-custom needs only prompt (capped at 500 characters) regardless of instrumental, and style/title should be left empty. uploadUrl is always required and the audio behind it must not exceed 8 minutes.
Extend an uploaded track
POST /api/v1/audio/generations · model: "suno-upload-extend"
Continues audio you supply from a chosen time point, returning a longer track that carries on the uploaded material's style.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-upload-extend. |
uploadUrl | string | yes | Public http(s) URL of the source audio. Maximum 8 minutes. Base64 and data: URIs are rejected. |
defaultParamFlag | boolean | yes | true — extend using the parameters in this request (style, title and continueAt become required, plus prompt when instrumental is false). false — reuse the uploaded audio's own parameters; on top of the always-required uploadUrl, instrumental and version, only prompt is needed. |
instrumental | boolean | yes | true extends without lyrics. When defaultParamFlag is true it decides whether prompt is required; when false it does not change which fields are required. |
version | enum | yes | One of V4, V4_5, V4_5PLUS, V4_5ALL, V5, V5_5. Must match the source music's version. |
continueAt | number | conditional | Required when defaultParamFlag is true. Seconds into the uploaded audio where the extension begins. Must be greater than 0 and less than the uploaded audio's duration (the upper bound is checked upstream). |
prompt | string | conditional | Required when defaultParamFlag is true and instrumental is false, where it is used verbatim as the lyrics; also required when defaultParamFlag is false, where lyrics are generated from it. Max 3000 chars on V4, 5000 on every other version. |
style | string | conditional | Required when defaultParamFlag is true; e.g. Jazz, Classical, Electronic. Max 200 chars on V4, 1000 on every other version. |
title | string | conditional | Required when defaultParamFlag is true. Max 80 chars on V4 and V4_5ALL, 100 on every other version. |
negativeTags | string | no | Styles to exclude from the extension. |
vocalGender | enum | no | m or f. Raises the probability of that vocal gender; it is not a guarantee. |
styleWeight | number | no | 0–1, up to 2 decimal places. Strength of adherence to style. |
weirdnessConstraint | number | no | 0–1, up to 2 decimal places. Controls experimental/creative deviation. |
audioWeight | number | no | 0–1, up to 2 decimal places. Balance of audio features against the other inputs. |
personaId | string | no | Persona ID or Voice ID to apply. Only available when defaultParamFlag is true. |
personaModel | enum | no | style_persona or voice_persona. Only available on V5 and V5_5. |
Response — on completion, output.audio_urls holds the extended audio URLs and output.tracks[] carries one index-aligned entry per variant, each with id, url, type (audio), title, duration in seconds, tags, lyrics and image_url (cover art).
Notes — the requirement matrix is defaultParamFlag × instrumental: flag true + instrumental needs style, title and continueAt; flag true + vocals needs style, title, prompt and continueAt; flag false needs only prompt beyond the always-required uploadUrl, instrumental and version (everything else is taken from the uploaded audio). continueAt must be greater than 0, and unlike the cover operation there is no 500-character short-prompt mode — the per-version caps apply in both modes.
Layer & combine
Add vocals to a track
POST /api/v1/audio/generations · model: "suno-add-vocals"
Takes an audio file you host and sings a new vocal line over it, returning the layered tracks as audio URLs.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-add-vocals. |
uploadUrl | string | yes | Public HTTP(S) URL of the source audio to add vocals to. Base64 and data: URIs are rejected. |
prompt | string | yes | Lyric content and singing style to guide the vocal. Min 1 character. |
style | string | yes | Musical style for the vocal, e.g. Jazz. Min 1 character. |
title | string | yes | Track title, shown in players and used for the file name. Min 1 character. |
negativeTags | string | yes | Comma-separated styles or elements to keep out of the result, e.g. heavy metal, strong drum beats. Min 1 character. |
version | string | no | One of V4_5PLUS, V5, V5_5. Defaults to V4_5PLUS. |
vocalGender | string | no | m or f. Biases the voice; it raises the probability rather than guaranteeing the gender. |
styleWeight | number | no | Adherence to style. 0–1, up to 2 decimal places. |
weirdnessConstraint | number | no | Experimental / creative deviation. 0–1, up to 2 decimal places. |
audioWeight | number | no | Relative weight of the source audio's elements. 0–1, up to 2 decimal places. |
Response — on completion, output.audio_urls[] holds the generated audio URLs and output.tracks[] carries one entry per track with id, url, type (audio), title, duration (seconds), tags (comma-separated style tags), lyrics and image_url (cover art). The two arrays are index-aligned, one entry per generated variant. tracks[].id is the audioId you pass to track-referencing operations.
Notes — unlike the generate/extend operations, all five content fields (prompt, style, title, negativeTags, uploadUrl) are unconditionally required, and version is restricted to the three newest models: V4, V4_5 and V4_5ALL are rejected. Pricing: reapi.ai/models/suno.
curl -X POST https://reapi.ai/api/v1/audio/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-add-vocals",
"uploadUrl": "https://example.com/music.mp3",
"prompt": "A calm and relaxing piano track.",
"style": "Jazz",
"title": "Relaxing Piano",
"negativeTags": "heavy metal, strong drum beats",
"version": "V4_5PLUS"
}'Add instrumental to a track
POST /api/v1/audio/generations · model: "suno-add-instrumental"
Takes an audio file you host and generates an instrumental accompaniment for it, returning the layered tracks as audio URLs.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-add-instrumental. |
uploadUrl | string | yes | Public HTTP(S) URL of the source audio to accompany. Base64 and data: URIs are rejected. |
tags | string | yes | Styles to include, e.g. relaxing, piano, soothing. Defines the character of the accompaniment. Min 1 character. |
title | string | yes | Track title, shown in players and used for the file name. Min 1 character. |
negativeTags | string | yes | Comma-separated styles or elements to keep out of the result. Min 1 character. |
version | string | no | One of V4_5PLUS, V5, V5_5. Defaults to V4_5PLUS. |
vocalGender | string | no | m or f. Biases the voice; it raises the probability rather than guaranteeing the gender. |
styleWeight | number | no | Adherence to the requested style. 0–1, up to 2 decimal places. |
weirdnessConstraint | number | no | Experimental / creative deviation. 0–1, up to 2 decimal places. |
audioWeight | number | no | Relative weight of the source audio's elements. 0–1, up to 2 decimal places. |
Response — same shape as add-vocals: output.audio_urls[] plus output.tracks[] with id, url, type, title, duration, tags and lyrics per track.
Notes — this operation names the style field tags, not style; sending style is rejected. All four of uploadUrl, tags, title and negativeTags are unconditionally required, and version accepts only V4_5PLUS, V5 and V5_5. Pricing: reapi.ai/models/suno.
curl -X POST https://reapi.ai/api/v1/audio/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-add-instrumental",
"uploadUrl": "https://example.com/music.mp3",
"tags": "relaxing, piano, soothing",
"title": "Relaxing Piano",
"negativeTags": "heavy metal, strong drum beats",
"version": "V4_5PLUS"
}'Mash up two tracks
POST /api/v1/audio/generations · model: "suno-mashup"
Combines exactly two audio files you host into one new piece, returning the remixed tracks as audio URLs.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-mashup. |
uploadUrlList | string[] | yes | Exactly 2 public HTTP(S) audio URLs. Fewer or more is rejected; base64 and data: URIs are rejected. |
customMode | boolean | yes | true unlocks the detailed controls (style, title, lyrics); false is the simple mode driven by prompt alone. |
version | string | yes | One of V4, V4_5, V4_5PLUS, V4_5ALL, V5, V5_5. |
instrumental | boolean | no | Generate the mashup without lyrics. In custom mode it decides whether prompt is required; in non-custom mode it has no effect on required fields. |
prompt | string | no | Conditionally required — see Notes. In custom mode it is used verbatim as the lyrics; in non-custom mode it is the core idea and lyrics are written from it. |
style | string | conditional | Required in custom mode, ignored otherwise. Genre, mood or artistic direction. |
title | string | conditional | Required in custom mode, ignored otherwise. Max 80 characters on every version. |
vocalGender | string | no | m or f. Only takes effect when customMode is true. |
styleWeight | number | no | Adherence to style. 0–1, up to 2 decimal places. Only takes effect when customMode is true. |
weirdnessConstraint | number | no | Creative deviation. 0–1, up to 2 decimal places. Only takes effect when customMode is true. |
audioWeight | number | no | Weight of the source audio elements. 0–1, up to 2 decimal places. Only takes effect when customMode is true. |
Response — output.audio_urls[] plus output.tracks[], each track carrying id, url, type, title, duration, tags and lyrics.
Notes — uploadUrlList must contain exactly two URLs. With customMode: true, style and title become required, and prompt is required too unless instrumental is true; the caps then depend on version — prompt up to 3000 characters on V4 and 5000 on every other version, style up to 200 on V4 and 1000 elsewhere, title 80 throughout. With customMode: false, prompt is optional but capped at 500 characters and the other content fields are ignored. Pricing: reapi.ai/models/suno.
curl -X POST https://reapi.ai/api/v1/audio/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-mashup",
"uploadUrlList": [
"https://example.com/audio1.mp3",
"https://example.com/audio2.mp3"
],
"customMode": true,
"instrumental": false,
"version": "V4_5PLUS",
"prompt": "A calm and relaxing piano track with soft melodies",
"style": "Jazz",
"title": "Relaxing Piano"
}'Section editing
Replace a section
POST /api/v1/audio/generations · model: "suno-replace-section"
Regenerates one time window inside an existing song from a new prompt and style, blending the replacement into the material before and after it, and returns the re-rendered track(s).
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-replace-section. |
taskId | string | conditional | Variant A. The reAPI task id (task_...) of the song you are editing. Required together with audioId; see Notes. |
audioId | string | conditional | Variant A. Identifies which track of that task to edit — take it from the parent task's output.tracks[].id. Required together with taskId. |
uploadUrl | string | conditional | Variant B. Public http(s) URL of your own audio file. Required together with version. Base64 / data: URIs are rejected. |
version | enum | conditional | Variant B. Model version used to render the replacement: V4, V4_5, V4_5PLUS, V4_5ALL, V5, V5_5. Required together with uploadUrl. |
prompt | string | yes | Lyrics for the replaced segment. Min 1 char. |
tags | string | yes | Style tags for the replaced segment, e.g. Jazz. Min 1 char. |
title | string | yes | Title of the resulting song. Min 1 char. |
negativeTags | string | no | Styles to keep out of the replaced segment, e.g. Rock. Min 1 char. |
infillStartS | number | yes | Start of the replacement window, in seconds from the beginning of the track. >= 0. Must be less than infillEndS. Values are interpreted to 2-decimal precision (e.g. 10.50). |
infillEndS | number | yes | End of the replacement window, in seconds. >= 0. Must be greater than infillStartS, and infillEndS - infillStartS must be between 6 and 60 seconds. |
fullLyrics | string | yes | The COMPLETE lyrics of the song after the edit — untouched sections plus the rewritten one — not just the replaced part. Min 1 char. |
Response — on completion, output.audio_urls[] holds the URL of each rendered track. output.tracks[] carries the same audio index-aligned with per-track metadata: type ("audio"), url, id (pass this back as audioId in later track-referencing operations), title, duration (seconds), tags, and lyrics.
Notes — the source is specified by exactly one of two mutually exclusive variants: (A) taskId + audioId to edit a track generated on reAPI, or (B) uploadUrl + version to edit audio you supply. Both halves of a variant must be present together, and mixing fields from the two variants in one request is rejected with a validation error — so is sending neither. version belongs to variant B only — sending it alongside taskId / audioId is what makes a request "mixed", so variant A must omit it and the replacement is rendered with the source track's own model. Two further limits apply to the window: it must span at least 6 and at most 60 seconds, and upstream additionally refuses a replacement longer than 50% of the original track's total duration. fullLyrics is what the whole song is re-rendered against, so passing only the new lines will drop the rest of the lyrics.
Track assets
These operations act on a track you already generated: they take the reapi taskId of a completed Suno task plus (usually) the audioId of one track inside it, and return a derived asset. Per-operation pricing: https://reapi.ai/models/suno.
Separate vocals and instrument stems
POST /api/v1/audio/generations · model: "suno-vocal-separation"
Splits one generated track into vocal/accompaniment or per-instrument stems and returns one audio URL per stem.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-vocal-separation. |
taskId | string | yes | reapi task id (task_...) of a completed Suno task that produced the track. Min length 1. |
audioId | string | yes | The track inside that task to process. Copy it from the parent task's output.tracks[].id. Min length 1. |
type | enum | no | Separation mode. separate_vocal (default) splits into 2 stems — vocals + instrumental. split_stem splits into up to 12 stems (vocals, backing vocals, drums, bass, guitar, keyboard, strings, brass, woodwinds, percussion, synth, FX/other). split_stem_advanced does multi-stem separation and can target one specific instrument via stemName. |
stemName | enum | conditional | The single instrument track to extract. Only meaningful with type: "split_stem_advanced", where it is required. 98 accepted values covering vocals, drums, guitars, keys, strings, brass, woodwinds, percussion and synths — e.g. Lead Vocal, Backing Vocals, Drum Kit, Kick, Bass, Piano, Electric Guitar, Synth Pad, Brass Section, Violin, Flute, 808. |
Response
output.audio_urls holds one URL per separated stem, index-aligned with output.tracks[]. Each entry in output.tracks[] carries type: "audio", url, and label naming the stem. When upstream returns per-stem records, label is the upstream stem group name and the track also carries id and duration; otherwise label comes from the fixed set origin, instrumental, vocals, backing_vocals, drums, bass, guitar, piano, keyboard, percussion, strings, synth, fx, brass, woodwinds. Stems that upstream did not produce are simply absent — the array length varies with the mode and the source material.
Notes — stemName is rejected as missing only when type is split_stem_advanced; the other two modes ignore it. Separation quality depends on the mix: cleanly separated AI mixes yield the best stems. The per-stem id values returned here are what you pass as audioId to suno-midi.
Convert a track to WAV
POST /api/v1/audio/generations · model: "suno-wav"
Re-renders one generated track as an uncompressed WAV file for professional editing.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-wav. |
taskId | string | yes | reapi task id (task_...) of the completed Suno task that produced the track. Min length 1. |
audioId | string | yes | Which track in that task to convert. Copy it from the parent task's output.tracks[].id. Min length 1. |
Response
output.audio_urls holds a single URL pointing at the WAV file. No output.tracks[] is emitted for this operation.
Notes — WAV files are typically 5–10× larger than the MP3 equivalent, and processing time scales with the length of the source track.
Generate MIDI from separated stems
POST /api/v1/audio/generations · model: "suno-midi"
Transcribes separated audio into structured MIDI note data (pitch, timing, velocity) per detected instrument.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-midi. |
taskId | string | yes | reapi task id (task_...) of a completed vocal-separation task — not a music-generation task. Min length 1. |
audioId | string | no | Restricts transcription to one separated stem; take the value from that separation task's output.tracks[].id. Omit to transcribe all separated stems. Min length 1. |
Response
A structured text result, not audio: there is no audio_urls or tracks. On completion output.result.midi holds a state string and an instruments[] array. Each instrument has a name and a notes[] array whose entries carry pitch (MIDI note number, 0–127), start and end (seconds), and velocity (0–1).
Notes — Separation must run first; passing the task id of a plain music-generation task is not valid input for this operation. Not every instrument is detected — the result reflects what is actually present in the source stems, and upstream notes that separations run with type: "split_stem" can yield no note data at all. If upstream completes with no note data, the task is reported as failed rather than completing with an empty result.
Create a music video
POST /api/v1/audio/generations · model: "suno-music-video"
Renders one generated track into an MP4 with visualizations plus optional artist and brand attribution.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-music-video. |
taskId | string | yes | reapi task id (task_...) of the completed Suno task that produced the track. Min length 1. |
audioId | string | yes | Which track in that task to visualize. Copy it from the parent task's output.tracks[].id. Min length 1. |
author | string | no | Artist or creator name shown as a signature on the video cover. 1–50 characters. |
domainName | string | no | Website or brand shown as a watermark at the bottom of the video. 1–50 characters. |
Response
output.video_urls holds a single URL pointing at the rendered MP4.
Notes — Render time varies with the length of the source track.
Generate cover art
POST /api/v1/audio/generations · model: "suno-cover-image"
Generates cover images for a completed music task; usually returns two stylistic variants to choose from.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-cover-image. |
taskId | string | yes | reapi task id (task_...) of the completed music-generation task to illustrate. Min length 1. Note this operation targets the task as a whole — there is no audioId. |
Response
output.image_urls holds the generated cover images, typically two.
Notes — A cover can be generated only once per source task; a second request for the same taskId is rejected upstream rather than producing new images. Submit it after the music task has completed.
Voice cloning
Cloning a singing voice is a three-step chain, and each step is its own billable task (see pricing):
suno-voice-validate— submit the source recording and the vocal segment to analyse. The completed task returns a validation phrase.suno-voice-generate— have the person record themselves reading (ideally singing) that phrase, host the recording at a public URL, and submit it asverifyUrltogether with the reapitaskIdof the step-1 task. The completed task returns avoiceId.suno-voice-regenerate— only needed when a validation phrase failed or expired.
The voiceId from step 2 is then used in the generation operations that accept a persona: pass it as personaId with personaModel: "voice_persona".
Step 1 — Generate a validation phrase
POST /api/v1/audio/generations · model: "suno-voice-validate"
Analyses the vocal segment of a source recording and returns the phrase the speaker must read aloud to verify the voice.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-voice-validate. |
voiceUrl | string | yes | Public http(s) URL of the source recording. Base64 / data: payloads are rejected. |
vocalStartS | integer | yes | Start time, in seconds, of the vocal segment to extract. 0 or greater. |
vocalEndS | integer | yes | End time, in seconds, of the vocal segment. Must be greater than vocalStartS. |
language | string | no | Language of the generated phrase. Upstream documents en, zh, es, fr, pt, de, ja, ko, hi, ru. |
curl https://reapi.ai/api/v1/audio/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-voice-validate",
"voiceUrl": "https://example.com/audio/source_voice.mp3",
"vocalStartS": 0,
"vocalEndS": 10,
"language": "en"
}'Response — a structured text result. When the task completes, output.result.validateInfo holds the phrase text to be read, and output.result.status holds the upstream state that made it terminal (wait_validating while the phrase awaits the reader, success once the whole flow has finished).
Notes — vocalEndS must be strictly greater than vocalStartS; equal or inverted values are rejected before the task is created. Keep the reapi task id (task_...) returned by this call: step 2 references it, and it is the only handle you have on the phrase — the upstream phrase id is never exposed.
Step 2 — Create the custom voice
POST /api/v1/audio/generations · model: "suno-voice-generate"
Submits the reader's verification recording against a completed validation task and produces a reusable custom voice.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-voice-generate. |
taskId | string | yes | Your reapi task id (task_...) from step 1 (or from a step-3 regeneration). Must be your own task, in completed status, from the same surface, and from the voice flow. |
verifyUrl | string | yes | Public http(s) URL of the recording of the person reading the validateInfo phrase. Singing the phrase rather than speaking it produces a more accurate voice profile. Base64 / data: payloads are rejected. |
voiceName | string | no | Display name for the voice. |
description | string | no | Free-text description of the voice. |
style | string | no | Voice style, e.g. Pop, Female Vocal. |
singerSkillLevel | enum | no | One of beginner, intermediate, advanced, professional. Upstream default is beginner. |
curl https://reapi.ai/api/v1/audio/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-voice-generate",
"taskId": "task_abc123",
"verifyUrl": "https://example.com/audio/verify_read.mp3",
"voiceName": "My Voice",
"description": "created from uploaded voice",
"style": "Pop, Female Vocal",
"singerSkillLevel": "beginner"
}'Response — a structured text result: output.result.voiceId, the identifier of the finished custom voice.
Notes — feed voiceId back into a generation call as personaId, together with personaModel: "voice_persona". The persona fields only apply in custom mode (customMode: true), and personaModel is only available on V5 and V5_5. The taskId reference is resolved and rejected before any charge, so a bad or unfinished parent task costs nothing. A clean a-cappella take of the verification recording gives the most accurate voice profile.
Step 3 — Regenerate the validation phrase
POST /api/v1/audio/generations · model: "suno-voice-regenerate"
Asks upstream for a fresh validation phrase on an existing voice task, for when the previous phrase failed or expired.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Must be suno-voice-regenerate. |
taskId | string | yes | Your reapi task id (task_...) of an earlier voice-flow task. Same ownership / completed / voice-family checks as step 2. |
curl https://reapi.ai/api/v1/audio/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-voice-regenerate",
"taskId": "task_abc123"
}'Response — a structured text result carrying the NEW phrase: the task completes with output.result.validateInfo (and its status), the same shape step 1 returns.
Notes — this reissues the validation phrase, it does not produce a voice. Record yourself reading the new phrase and send that recording to step 2 (suno-voice-generate) with this task's id as taskId. Use it when the earlier phrase expired or the reading was rejected.
Synchronous helpers
These four operations do not run on /api/v1/audio/generations and have no task lifecycle — they answer inline on the same HTTP response, so there is nothing to poll. Each has its own route, accepts only the fields listed below (unknown fields are rejected), and returns id (the audit task id recording this call, task_...), credits (the credits charged), plus its result fields. A failed call is refunded in full. Pricing: reapi.ai/models/suno.
curl -X POST https://reapi.ai/api/v1/audio/suno/boost-style \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content":"Pop, Mysterious"}'Boost music style
POST /api/v1/audio/suno/boost-style
Expands a short style description into a richer, generation-ready style prompt and returns the enhanced text inline.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
content | string | yes | Style description to enhance, min 1 character. Describe the music style you expect in concise, clear language — e.g. Pop, Mysterious. |
Response — result: the enhanced style text. Feed it into the style field of a generation request.
Timestamped lyrics
POST /api/v1/audio/suno/timestamped-lyrics
Returns word-level time-aligned lyrics for one track of a completed song task.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
taskId | string | yes | Your reapi task id (task_...) of the completed song task the track belongs to, min 1 character. |
audioId | string | yes | Identifier of the specific track, min 1 character. Take it from the parent task's output.tracks[].id. |
Response
alignedWords: array of aligned words, each withword(the lyric token),success(boolean, whether that token aligned),startS/endS(word start and end time in seconds), andpalign(alignment parameter).waveformData: array of numbers for audio visualisation, ornullwhen upstream omits it.hootCer: lyrics alignment accuracy score, ornull.isStreamed: whether the source is streaming audio, ornull.
Notes — taskId must name a Suno-family task you own that has reached completed; a task that is still running, or one from outside the Suno family, is rejected before any charge. Which Suno operation produced it is not gated here — upstream expects a music-generating parent (song or extend) and answers for the rest. waveformData is delivered inline only — it is deliberately not kept in the audit row, so a later GET /api/v1/tasks/{id} on this call's id returns the other three fields plus waveform_omitted: true.
Generate persona
POST /api/v1/audio/suno/persona
Analyses a segment of an existing track and creates a reusable persona, returning its personaId.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
taskId | string | yes | Your reapi task id (task_...) of the completed song task to analyse, min 1 character. |
audioId | string | yes | Identifier of the track to build the persona from, min 1 character. Take it from the parent task's output.tracks[].id. |
name | string | yes | Name for the persona, min 1 character — something that captures the musical style or character, e.g. Electronic Pop Singer. |
description | string | yes | Description of the persona's musical characteristics, style and personality, min 1 character. Be specific about genre, mood, instrumentation and vocal qualities. |
vocalStart | number | no | Start of the analysis segment in seconds, >= 0. Defaults to 0. |
vocalEnd | number | no | End of the analysis segment in seconds, >= 0. Defaults to 30. |
style | string | no | Supplementary style tag for the persona, min 1 character — e.g. Electronic Pop, Jazz Trio. |
Response — personaId: the persona identifier, reusable in the personaId field of the song, extend, upload-cover and upload-extend operations. name and description echo the request (each null if upstream omits it).
Notes — the analysis window is validated before charging: vocalEnd - vocalStart must be between 10 and 30 seconds inclusive, using the defaults 0 and 30 for whichever bound you omit. Setting only vocalStart: 25 therefore fails (window is 5s), while vocalStart: 25, vocalEnd: 40 succeeds. taskId must name a completed Suno task you own.
Check voice availability
POST /api/v1/audio/suno/check-voice
Reports whether a custom voice produced by a completed voice task is ready to use.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
task_id | string | yes | Your reapi task id (task_...) of the completed voice task to check, min 1 character. This endpoint's field is snake_case task_id — the rest of the surface is camelCase. |
Response — isAvailable: boolean, whether the generated voice is available.
Notes — task_id must resolve to a completed voice-family task you own — in practice the suno-voice-generate or suno-voice-regenerate task that produced the voice; a song task is rejected before any charge.
Output schema
Asynchronous results land on GET /api/v1/tasks/{id}:
{
"id": "task_...",
"status": "completed",
"output": {
"audio_urls": ["https://..."],
"tracks": [
{
"id": "track id — reuse as audioId",
"url": "https://...",
"title": "Midnight Drive",
"duration": 128.5,
"tags": "synthwave, dreamy",
"lyrics": "..."
}
]
},
"error": null
}Music videos populate output.video_urls, cover art
output.image_urls; lyric / MIDI / voice tasks return a structured
text output (e.g. { "lyrics": [...] }, { "midi": ... },
{ "voiceId": "..." }, { "validateInfo": "..." }).
Pricing dimensions
Every operation bills a flat rate per request — nothing scales with
duration or output length. Generation-class operations (music, extend,
covers, vocals, mashup) share one rate covering both returned tracks;
section replacement, stem separation (three tiers by type), music
video, sound effects, lyrics, WAV conversion, and the utility
operations each have their own flat rate. Bill formula:
credits = price_usd × 1000 (1 credit = $0.001). Current rates:
Suno model page.
Errors
Failures use the standard envelope
{ "error": { "code", "message", "request_id" } } — see the
error catalog. Notable cases: content flagged by
moderation returns a policy error (80006); malformed parameter
combinations surface 80007 with the upstream reason; upstream
generation failures (80003) are refunded automatically.
Tips
- Start in inspiration mode (
customMode: false) — one prompt line is enough. Switch to custom mode when you need exact lyrics. stylereads best as comma-separated genre + mood + vocal tags ("synthwave, dreamy, female vocal"). Use the boost-style helper to expand a rough idea.- Save
output.tracks[].id— every downstream operation needs it. - For extensions, pick
continueAta beat before the natural end of the source so the transition lands cleanly. - Instrumental-only? Set
instrumental: trueand skip lyrics entirely.
Related
- Mureka V9 Song — lyrics-first song generation
- Music Video 1.0 — song + images → MV
- Vocal Remover — standalone stem separation