Developers (API)
API Pricing Plans
This is pricing for the API only. Generating songs using our website is free!
FREE TRIAL: Simply by registering an account, you will receive 1,500 credits for FREE. This is enough to generate at least 15 songs to test out the API.
Currently, one 1 minute 35 second song costs 100 credits. Generating 2 songs in one request by setting num_songs to 2 costs 150 credits. This pricing is subject to change.
Any user-facing implementation of our API requires proper attribution to Sonauto.
- 20,000 credits (200 songs) per month
- Additional credits for $0.06 per 100 credits
- Priority support
- 160,000 credits (1,600 songs) per month
- Additional credits for $0.06 per 100 credits
- Priority support
- 660,000 credits (6,600 songs) per month
- Additional credits for $0.05 per 100 credits
- Priority support
- 2,875,000 credits (28,750 songs) per month
- Additional credits for $0.04 per 100 credits
- Priority support
Need an even bigger plan? Contact us.
API Documentation
Our api domain is https://api.sonauto.ai/v1. This is v1 of our API specification. Model versions are specified in the endpoint like:https://api.sonauto.ai/v1/generations/v2 or https://api.sonauto.ai/v1/generations/v3.
Authentication
All endpoints require an API key to be passed in the Authorization header:
Authorization: Bearer your_api_key_here
Generation Endpoints
Core Parameters
- For all generation endpoints, you must provide at least one of
tags,lyrics, orprompt. Iftagsorlyricsis left blank, then it will be generated by AI based on theprompt. You can view a list of supported tags using our Tag Explorer. - Providing only
lyricsortags(without a prompt) is not supported. However, you can pass an empty string as thepromptto leave the style/lyrics entirely up to the AI. - For instrumental songs, set
instrumentalto true and don't pass anylyrics. In the instrumental case, only thetagsorpromptcan be set (where thepromptwill only be used to generatetags).
Other Parameters
prompt_strength- Greater values adhere more to the prompt but sound less natural.balance_strength- Greater means more natural vocals. Lower means sharper instrumentals. We recommend 0.7.seed- The number used to seed the random number generator. The sametagsandlyricswith the sameseedwill generate the same song.webhook_url- This URL will receive POST requests while the song is being generated with status updates.num_songs- The number of songs to generate. Must be 1 or 2. Generating 2 songs will use 150 credits instead of 100! Also, this value controls the length of thesong_pathsarray returned by the status endpoint.align_lyrics- When true, performs lyrics alignment after generation completes. This produces word-level timing data that syncs lyrics to the audio. For v2, requiresnum_songs=1. See the Lyrics Alignment section for more details.
Output Audio Formats
- The default output format is variable bitrate opus in an ogg container (a .ogg file). You can change this by setting the
output_formatoption. - Supported formats: mp3, flac, wav, ogg (opus), m4a (aac)
- Additionally, for mp3 and m4a, you can set a bitrate with the
output_bit_rateoption. This can be left null to use reasonable defaults. Supported bit rates for mp3 and m4a (in kbps): 128, 192, 256, 320.
Statuses
You can view the current status of your generation request using the GET /generations/{task_id} endpoint described below. Alternatively, you can specify a webhook_url to get updates in real-time. Either way, you will recieve the following status updates in order:
RECEIVED- Sent immediately after we parse your request.TRANSCRIBE_TASK_STARTED(inpaint/extend only)TRANSCRIBE_STAGE_1(inpaint/extend only)TRANSCRIBE_STAGE_2(inpaint/extend only)TRANSCRIBE_STAGE_3(inpaint/extend only)TRANSCRIBE_DONE(inpaint/extend only)PROMPT- We are converting your prompt to tags and/or lyrics.TASK_SENT- Everything is ready and we've sent your task to our GPU cluster.GENERATE_TASK_STARTED- A GPU worker has been assigned to your task and has started working on it.LOADING_SOURCE(inpaint/extend only) - We are fetching your source song to inpaint or extend.BEGINNING_GENERATION- Sent right before your song starts generating.GENERATING- The main event! Your song is being generated.GENERATING_STREAMING_READY- v3 only. Indicates that you can connect to the streaming endpoint to start listening to the song while it generates.DECOMPRESSING- Decompressing your song from our latent space.SAVING- Uploading your song to our CDN.SUCCESS- Everything worked! Your song URL(s) will be posted in the body of this request at the keysong_paths, or you can fetch them using the GET/generations/{task_id}endpoint. Note: These URLs expire and are not permanent. See Data Fetching Endpoints for more information.FAILURE- Something went wrong. Don't worry, no credits were deducted. Please try again or contact us :)
v3
v3 Preview
prompt_strength value may shift between updates without notice. For best results, we recommend the default values.Unlike v2, v3 does not support seed, balance_strength, bpm, or num_songs (v3 always generates 1 song).
/generations/v3
enable_streaming to true in your request. See the Streaming section for more information. Use the stream_format parameter to control the audio format of the stream (ogg or mp3).Request Body
{
"tags": "array[string] (optional)",
"lyrics": "string (optional)",
"prompt": "string (optional)",
"instrumental": "boolean (default: false)",
"prompt_strength": "float (default: 2.0)",
"webhook_url": "string (optional)",
"output_format": "string (default: ogg)",
"output_bit_rate": "integer (optional)",
"enable_streaming": "boolean (default: false)",
"stream_format": "string (default: ogg, options: 'ogg' | 'mp3')",
"align_lyrics": "boolean (default: false)"
}Code Samples
import requests
url = "https://api.sonauto.ai/v1/generations/v3"
headers = {
"Authorization": "Bearer your_api_key_here",
"Content-Type": "application/json"
}
payload = {
"tags": ["rock", "energetic"],
"prompt": "An upbeat rock song with heavy guitar riffs"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())Response
{
"task_id": "string"
}v2
/generations/v2
bpm- The beats per minute of the song. This can be set to an integer or the literal string "auto" to pick a suitable bpm based on thetags. Setbpmto null to not condition the model on bpm information.
Request Body
{
"tags": "array[string] (optional)",
"lyrics": "string (optional)",
"prompt": "string (optional)",
"instrumental": "boolean (default: false)",
"prompt_strength": "float",
"balance_strength": "float (default: 0.7)",
"seed": "integer (optional)",
"webhook_url": "string (optional)",
"num_songs": "integer (default: 1)",
"output_format": "string (default: ogg)",
"output_bit_rate": "integer (optional)",
"align_lyrics": "boolean (default: false)",
"bpm": "'auto' or integer (optional)"
}Code Samples
import requests
url = "https://api.sonauto.ai/v1/generations/v2"
headers = {
"Authorization": "Bearer your_api_key_here",
"Content-Type": "application/json"
}
payload = {
"tags": ["rock", "energetic"],
"prompt": "An upbeat rock song with heavy guitar riffs"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())Response
{
"task_id": "string"
}/generations/v2/extend
- Set the
audio_urlto the song you want to extend. This must be a publicly available URL. Alternatively, you can directly pass the audio file bytes as a base64 encoded string using theaudio_base64parameter (see the "Python (upload)" example below). Please note the the file size limit for base64 encoded audio is 40MB. - You can extend from the start or end of the song by setting the
sideto "left" or "right," respectively.extend_durationdetermines how much new audio to generate. This must be between 0 and 85.0 seconds. - Finally, the
crop_durationcan be used to crop the end (or start, depending on the value ofside) of the original audio before extending.
Note
audio_url to the path of the audio file on our CDN (instead of a version you downloaded, for instance). This will prevent quality degradation over time because, internally, we will reuse our latent representation of the song instead of re-encoding the audio.Request Body
{
"tags": "array[string] (optional)",
"lyrics": "string (optional)",
"prompt": "string (optional)",
"instrumental": "boolean (default: false)",
"prompt_strength": "float",
"balance_strength": "float (default: 0.7)",
"seed": "integer (optional)",
"webhook_url": "string (optional)",
"num_songs": "integer (default: 1)",
"output_format": "string (default: ogg)",
"output_bit_rate": "integer (optional)",
"align_lyrics": "boolean (default: false)",
"audio_url": "string (URL)",
"audio_base64": "string (base64)",
"side": "string (left | right)",
"extend_duration": "float (optional)",
"crop_duration": "float (default: 0.0)"
}import requests
url = "https://api.sonauto.ai/v1/generations/v2/extend"
headers = {
"Authorization": "Bearer your_api_key_here",
"Content-Type": "application/json"
}
payload = {
"audio_url": "https://cdn.sonauto.ai/generations2/audio_a598194b-d464-474c-b1e6-1c99f8f8e457_0.ogg",
"tags": ["rock", "energetic"],
"prompt": "Write another verse for my song",
"side": "right",
"extend_duration": 45.0
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())Response
{
"task_id": "string"
}/generations/v2/inpaint
- Set the
audio_urlto the song you want to extend. This must be a publicly available URL. Alternatively, you can directly pass the audio file bytes as a base64 encoded string using theaudio_base64parameter (see the "Python (upload)" example below). Please note the the file size limit for base64 encoded audio is 40MB. sectionsrepresents the sections you want to replace. Currently, it is only possible to inpaint one section. Thus, the outer list must be of length 1. The inner list must have two floats representing the start and end timestamps (in seconds) of the section to replace.selection_cropwill crop the final output to only contain the inpainted section.
Note
audio_url to the path of the audio file on our CDN (instead of a version you downloaded, for instance). This will prevent quality degradation over time because, internally, we will reuse our latent representation of the song instead of re-encoding the audio.Request Body
{
"tags": "array[string] (optional)",
"lyrics": "string",
"prompt": "string (optional)",
"instrumental": "boolean (default: false)",
"prompt_strength": "float",
"balance_strength": "float (default: 0.7)",
"seed": "integer (optional)",
"webhook_url": "string (optional)",
"num_songs": "integer (default: 1)",
"output_format": "string (default: ogg)",
"output_bit_rate": "integer (optional)",
"align_lyrics": "boolean (default: false)",
"audio_url": "string (URL)",
"audio_base64": "string (base64)",
"sections": "array[array[float]]",
"selection_crop": "boolean (default: false)"
}import requests
url = "https://api.sonauto.ai/v1/generations/v2/inpaint"
headers = {
"Authorization": "Bearer your_api_key_here",
"Content-Type": "application/json"
}
payload = {
"audio_url": "https://cdn.sonauto.ai/generations2/audio_a598194b-d464-474c-b1e6-1c99f8f8e457_0.ogg",
"tags": ["rock", "energetic"],
"sections": [[0.0, 30.0]],
"lyrics": "New lyrics for the sections"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())Response
{
"task_id": "string"
}Data Fetching Endpoints
Important Details
- Songs will be deleted from our severs one week (168 hours) after they were generated. This means the URLs in
song_pathswill not work after this time. In some circumstances, songs may be accessible after this time, but this is not guaranteed. Make sure to download any songs you want to keep!
/generations/{task_id}
Retrieve the final generated song and all the parameters you used to generate it. The final audio URL is also sent over the webhook_url if you set it.
Code Samples
import requests
task_id = "your_task_id"
url = f"https://api.sonauto.ai/v1/generations/{task_id}"
headers = {
"Authorization": "Bearer your_api_key_here"
}
response = requests.get(url, headers=headers)
print(response.json())Response
{
"id": "string (UUID)",
"created_at": "string (ISO 8601 timestamp)",
"status": "string",
"alignment_status": "string | null",
"model_version": "string (e.g. 'v2.2', 'v3-preview')",
"song_paths": "array[string] (URLs)",
"error_message": "string | null",
"lyrics": "string",
"prompt": "string | null",
"prompt_strength": "float",
"tags": "array[string]",
"v2_params": {
"balance_strength": "float",
"seed": "integer",
"bpm": "'auto' | integer | null"
},
"inpaint_params": {
"sections": "array[array[float]]",
"selection_crop": "boolean",
"audio_url": "string (URL)",
"lyrics": "string"
},
"extend_params": {
"side": "string",
"crop_duration": "float",
"audio_url": "string (URL)",
"duration": "float",
"lyrics": "string"
}
}Field Descriptions
id: Unique identifier for the generationcreated_at: Timestamp when the generation was createdstatus: Current status of the generationalignment_status: Status of lyrics alignment post-processing (null if alignment was not requested)model_version: The model version used for generation (e.g. "v2.2", "v3-preview")song_paths: Array of URLs to the generated audio fileserror_message: If the generation state is FAILURE, this may contain helpful information to understand what went wrong.lyrics: Generated or provided lyricsprompt: The prompt used for generation (if any)prompt_strength: Greater values adhere more to the prompt but sound less natural.tags: Array of musical style tagsv2_params: Parameters specific to v2 generations (null for v3). Contains:balance_strength: Greater means more natural vocals. Lower means sharper instrumentals. We recommend 0.7.seed: Random seed used for generationbpm: The beats per minute used for generation
inpaint_params: Parameters used if this was an inpainting operationextend_params: Parameters used if this was an extension operation
/generations/status/{task_id}
Check the status of a generation task.
Parameters
task_id- The ID of the generation taskinclude_alignment- Optional query parameter (default: false). When true, returns a JSON object with both the generation status and alignment status. Alignment is an optional post-processing step that syncs lyrics to the audio.
Code Samples
import requests
task_id = "your_task_id"
url = f"https://api.sonauto.ai/v1/generations/status/{task_id}"
headers = {
"Authorization": "Bearer your_api_key_here"
}
response = requests.get(url, headers=headers)
print(response.json()) # Returns: "GENERATING"Response
By default, returns a plain string with the generation status:
"SUCCESS"
With include_alignment=true, returns a JSON object:
{
"status": "string",
"alignment_status": "string | null"
}The alignment_status will be null if alignment was not requested for this generation.
/credits/balance
Check the number of credits you have left.
import requests
url = "https://api.sonauto.ai/v1/credits/balance"
headers = {
"Authorization": "Bearer your_api_key_here"
}
response = requests.get(url, headers=headers)
print(response.json())Response
{
"num_credits": "integer",
"num_credits_payg": "integer"
}Field Descriptions
num_credits: The number of subscription credits remainingnum_credits_payg: The number of pay-as-you-go credits remaining
Streaming
v3 generations can be streamed in real time as the audio is being generated. This allows you to start playing a song before it has finished generating. Streaming is only available for v3 generations.
Important
- You must set
enable_streamingtotruein your generation request. Streaming is disabled by default. If you did not enable it when creating the generation, the streaming endpoint will not work for that track. - The streaming endpoint is only available while the song is being generated and for a few seconds after generation completes. Once the stream expires, you must use the final audio URL from the
song_pathsfield returned by the GET /generations/{task_id} endpoint.
https://api-stream.sonauto.ai/stream/{task_id}
Stream audio for a v3 generation as it's being created. The endpoint returns audio chunks as they are produced by the model. If you connect after generation has started, you will receive all previously generated audio immediately, then continue receiving new chunks as they are generated.
Parameters
task_id - The task ID returned when you created the v3 generation
Response
Returns a streaming audio response. Returns opus in an ogg container by default, but can also return mp3 if requested during the generation request. The Content-Type header will be one of:
audio/ogg; codecs="opus"(default)audio/mpeg(mp3)
Errors
- 400 Bad Request - The track is not ready for streaming yet. Wait for the generation to reach the
GENERATING_STREAMING_READYstatus before attempting to stream.
Code Samples
<!-- The streaming endpoint can be used directly with an HTML audio element --> <audio controls autoplay> <source src="https://api-stream.sonauto.ai/stream/your_task_id" type="audio/ogg" /> </audio>
Lyrics Alignment
Lyrics alignment is an optional post-processing step that produces word-level timing data, syncing your lyrics to the generated audio.
Requirements
- Alignment only works for non-instrumental songs with lyrics. If the song is instrumental or has no lyrics, alignment will not run (you can still set
align_lyrics, it will simply be ignored). - For v2 generations: You must set
num_songs=1when usingalign_lyrics=true.
Alignment Status Flow
When you set align_lyrics=true in your generation request, the alignment process follows these status updates:
REQUESTED- Alignment has been requested and will run after the generation completes successfully.TASK_SENT- The generation succeeded and the alignment task has been sent to our workers.ALIGNING- A worker is actively processing the alignment.SUCCESS- Alignment completed successfully. The aligned lyrics are now available.FAILURE- Something went wrong during alignment.
Important
If the main generation fails (status becomes FAILURE), the alignment_status will remain in REQUESTED state because the alignment task never runs. Always check the main status first before checking alignment_status.
If alignment fails, but the generation succeeds, credits will be deducted.
Checking Alignment Status
Use the GET /generations/status/{task_id} endpoint with include_alignment=true to check both the generation and alignment status:
{
"status": "SUCCESS",
"alignment_status": "ALIGNING"
}Webhook Updates
If you specified a webhook_url, you will receive webhook updates for alignment status changes. The webhook payload will include an alignment_status field when alignment is in progress or complete.