# File Upload API Quickstart Source: https://docs.api.box/file-upload-api/quickstart Get started with the File Upload API in minutes, supporting multiple upload methods ## Welcome to File Upload API The File Upload API provides flexible and efficient file upload services, supporting multiple upload methods to meet diverse business needs. Whether it's remote file migration, large file transmission, or quick small file uploads, our API offers the best solutions for your requirements. Base64 encoded file upload, suitable for small files Efficient binary file stream upload, ideal for large files Automatically download and upload files from remote URLs **File uploads are free** - No charges apply for uploading files to our service. You can upload files without worrying about upload costs or fees. **Important Notice**: Uploaded files are temporary and will be **automatically deleted after 3 days**. Please download or migrate important files promptly. ## Authentication All API requests require authentication using Bearer tokens. Please obtain your API key from the [API Key Management Page](https://api.box/api-key). Please keep your API key secure and never share it publicly. If you suspect your key has been compromised, reset it immediately. ### API Base URL ``` https://apibox.redpandaai.co ``` ### Authentication Header ```http theme={null} Authorization: Bearer YOUR_API_KEY ``` ## Quick Start Guide ### Step 1: Choose Your Upload Method Select the appropriate upload method based on your needs: Suitable for downloading and uploading files from remote servers: ```bash cURL theme={null} curl -X POST "https://apibox.redpandaai.co/api/file-url-upload" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "fileUrl": "https://example.com/sample-image.jpg", "uploadPath": "images", "fileName": "my-image.jpg" }' ``` ```javascript JavaScript theme={null} const response = await fetch('https://apibox.redpandaai.co/api/file-url-upload', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ fileUrl: 'https://example.com/sample-image.jpg', uploadPath: 'images', fileName: 'my-image.jpg' }) }); const result = await response.json(); console.log('Upload successful:', result); ``` ```python Python theme={null} import requests url = "https://apibox.redpandaai.co/api/file-url-upload" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } payload = { "fileUrl": "https://example.com/sample-image.jpg", "uploadPath": "images", "fileName": "my-image.jpg" } response = requests.post(url, json=payload, headers=headers) result = response.json() print(f"Upload successful: {result}") ``` Suitable for directly uploading local files, especially large files: ```bash cURL theme={null} curl -X POST "https://apibox.redpandaai.co/api/file-stream-upload" \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "file=@/path/to/your-file.jpg" \ -F "uploadPath=images/user-uploads" \ -F "fileName=custom-name.jpg" ``` ```javascript JavaScript theme={null} const formData = new FormData(); formData.append('file', fileInput.files[0]); formData.append('uploadPath', 'images/user-uploads'); formData.append('fileName', 'custom-name.jpg'); const response = await fetch('https://apibox.redpandaai.co/api/file-stream-upload', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY' }, body: formData }); const result = await response.json(); console.log('Upload successful:', result); ``` ```python Python theme={null} import requests url = "https://apibox.redpandaai.co/api/file-stream-upload" headers = { "Authorization": "Bearer YOUR_API_KEY" } files = { 'file': ('your-file.jpg', open('/path/to/your-file.jpg', 'rb')), 'uploadPath': (None, 'images/user-uploads'), 'fileName': (None, 'custom-name.jpg') } response = requests.post(url, headers=headers, files=files) result = response.json() print(f"Upload successful: {result}") ``` Suitable for Base64 encoded file data: ```bash cURL theme={null} curl -X POST "https://apibox.redpandaai.co/api/file-base64-upload" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "base64Data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...", "uploadPath": "images", "fileName": "base64-image.png" }' ``` ```javascript JavaScript theme={null} const response = await fetch('https://apibox.redpandaai.co/api/file-base64-upload', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ base64Data: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...', uploadPath: 'images', fileName: 'base64-image.png' }) }); const result = await response.json(); console.log('Upload successful:', result); ``` ```python Python theme={null} import requests import base64 # Read file and convert to base64 with open('/path/to/your-file.jpg', 'rb') as f: file_data = base64.b64encode(f.read()).decode('utf-8') base64_data = f'data:image/jpeg;base64,{file_data}' url = "https://apibox.redpandaai.co/api/file-base64-upload" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } payload = { "base64Data": base64_data, "uploadPath": "images", "fileName": "base64-image.jpg" } response = requests.post(url, json=payload, headers=headers) result = response.json() print(f"Upload successful: {result}") ``` ### Step 2: Handle Response Upon successful upload, you'll receive a response containing file information: ```json theme={null} { "success": true, "code": 200, "msg": "File uploaded successfully", "data": { "fileId": "file_abc123456", "fileName": "my-image.jpg", "originalName": "sample-image.jpg", "fileSize": 245760, "mimeType": "image/jpeg", "uploadPath": "images", "fileUrl": "https://apibox.redpandaai.co/files/images/my-image.jpg", "downloadUrl": "https://apibox.redpandaai.co/download/file_abc123456", "uploadTime": "2025-01-15T10:30:00Z", "expiresAt": "2025-01-18T10:30:00Z" } } ``` ## Upload Method Comparison Choose the most suitable upload method for your needs: **Best for**: File migration, batch processing **Advantages**: * No local file required * Automatic download handling * Supports remote resources **Limitations**: * Requires publicly accessible URL * 30-second download timeout * Recommended ≤100MB **Best for**: Large files, local files **Advantages**: * High transmission efficiency * Supports large files * Binary transmission **Limitations**: * Requires local file * Server processing time **Best for**: Small files, API integration **Advantages**: * JSON format transmission * Easy integration * Supports Data URL **Limitations**: * Data size increases by 33% * Not suitable for large files * Recommended ≤10MB ## Practical Examples ### Batch File Upload Using file stream upload to handle multiple files: ```javascript theme={null} class FileUploadAPI { constructor(apiKey) { this.apiKey = apiKey; this.baseUrl = 'https://apibox.redpandaai.co'; } async uploadFile(file, uploadPath = '', fileName = null) { const formData = new FormData(); formData.append('file', file); if (uploadPath) formData.append('uploadPath', uploadPath); if (fileName) formData.append('fileName', fileName); const response = await fetch(`${this.baseUrl}/api/file-stream-upload`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}` }, body: formData }); if (!response.ok) { throw new Error(`Upload failed: ${response.statusText}`); } return response.json(); } async uploadFromUrl(fileUrl, uploadPath = '', fileName = null) { const response = await fetch(`${this.baseUrl}/api/file-url-upload`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ fileUrl, uploadPath, fileName }) }); if (!response.ok) { throw new Error(`Upload failed: ${response.statusText}`); } return response.json(); } async uploadBase64(base64Data, uploadPath = '', fileName = null) { const response = await fetch(`${this.baseUrl}/api/file-base64-upload`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ base64Data, uploadPath, fileName }) }); if (!response.ok) { throw new Error(`Upload failed: ${response.statusText}`); } return response.json(); } } // Usage example const uploader = new FileUploadAPI('YOUR_API_KEY'); // Batch upload files async function uploadMultipleFiles(files) { const results = []; for (let i = 0; i < files.length; i++) { try { const result = await uploader.uploadFile( files[i], 'user-uploads', `file-${i + 1}-${files[i].name}` ); results.push(result); console.log(`File ${i + 1} uploaded successfully:`, result.data.fileUrl); } catch (error) { console.error(`File ${i + 1} upload failed:`, error.message); } } return results; } // Batch upload from URLs async function uploadFromUrls(urls) { const results = []; for (let i = 0; i < urls.length; i++) { try { const result = await uploader.uploadFromUrl( urls[i], 'downloads', `download-${i + 1}.jpg` ); results.push(result); console.log(`URL ${i + 1} uploaded successfully:`, result.data.fileUrl); } catch (error) { console.error(`URL ${i + 1} upload failed:`, error.message); } } return results; } ``` ```python theme={null} import requests import base64 import os from typing import List, Optional class FileUploadAPI: def __init__(self, api_key: str): self.api_key = api_key self.base_url = 'https://apibox.redpandaai.co' self.headers = { 'Authorization': f'Bearer {api_key}' } def upload_file(self, file_path: str, upload_path: str = '', file_name: Optional[str] = None) -> dict: """File stream upload""" files = { 'file': (os.path.basename(file_path), open(file_path, 'rb')) } data = {} if upload_path: data['uploadPath'] = upload_path if file_name: data['fileName'] = file_name response = requests.post( f'{self.base_url}/api/file-stream-upload', headers=self.headers, files=files, data=data ) if not response.ok: raise Exception(f'Upload failed: {response.text}') return response.json() def upload_from_url(self, file_url: str, upload_path: str = '', file_name: Optional[str] = None) -> dict: """URL file upload""" payload = { 'fileUrl': file_url, 'uploadPath': upload_path, 'fileName': file_name } response = requests.post( f'{self.base_url}/api/file-url-upload', headers={**self.headers, 'Content-Type': 'application/json'}, json=payload ) if not response.ok: raise Exception(f'Upload failed: {response.text}') return response.json() def upload_base64(self, base64_data: str, upload_path: str = '', file_name: Optional[str] = None) -> dict: """Base64 file upload""" payload = { 'base64Data': base64_data, 'uploadPath': upload_path, 'fileName': file_name } response = requests.post( f'{self.base_url}/api/file-base64-upload', headers={**self.headers, 'Content-Type': 'application/json'}, json=payload ) if not response.ok: raise Exception(f'Upload failed: {response.text}') return response.json() # Usage example def main(): uploader = FileUploadAPI('YOUR_API_KEY') # Batch upload local files file_paths = [ '/path/to/file1.jpg', '/path/to/file2.png', '/path/to/document.pdf' ] print("Starting batch file upload...") for i, file_path in enumerate(file_paths): try: result = uploader.upload_file( file_path, 'user-uploads', f'file-{i + 1}-{os.path.basename(file_path)}' ) print(f"File {i + 1} uploaded successfully: {result['data']['fileUrl']}") except Exception as e: print(f"File {i + 1} upload failed: {e}") # Batch upload from URLs urls = [ 'https://example.com/image1.jpg', 'https://example.com/image2.png' ] print("\nStarting batch URL upload...") for i, url in enumerate(urls): try: result = uploader.upload_from_url( url, 'downloads', f'download-{i + 1}.jpg' ) print(f"URL {i + 1} uploaded successfully: {result['data']['fileUrl']}") except Exception as e: print(f"URL {i + 1} upload failed: {e}") if __name__ == '__main__': main() ``` ## Error Handling Common errors and handling methods: ```javascript theme={null} // Check if API key is correct if (response.status === 401) { console.error('Invalid API key, please check Authorization header'); // Retrieve or update API key } ``` ```javascript theme={null} // Check request parameters if (response.status === 400) { const error = await response.json(); console.error('Request parameter error:', error.msg); // Check if required parameters are provided // Check if file format is supported // Check if URL is accessible } ``` ```javascript theme={null} // Implement retry mechanism async function uploadWithRetry(uploadFunction, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await uploadFunction(); } catch (error) { if (i === maxRetries - 1) throw error; // Exponential backoff const delay = Math.pow(2, i) * 1000; await new Promise(resolve => setTimeout(resolve, delay)); } } } ``` ## Best Practices * **Small files** (≤1MB): Recommended to use Base64 upload * **Medium files** (1MB-10MB): Recommended to use file stream upload * **Large files** (>10MB): Must use file stream upload * **Remote files**: Use URL upload, note 100MB limit * Implement concurrency control to avoid uploading too many files simultaneously * Consider chunked upload strategies for large files * Use appropriate retry mechanisms to handle network issues * Monitor upload progress and provide user feedback * Keep API keys secure and rotate them regularly * Validate file types and sizes * Consider encrypted transmission for sensitive files * Download important files promptly to avoid 3-day deletion * Implement comprehensive error handling logic * Log uploads for troubleshooting * Provide user-friendly error messages * Offer retry options for failed uploads ## File Storage Information **Important Notice**: All uploaded files are temporary and will be **automatically deleted after 3 days**. * Files are immediately accessible and downloadable after upload * File URLs remain valid for 3 days * The system provides an `expiresAt` field in the response indicating expiration time * It's recommended to download or migrate important files before expiration * Use the `downloadUrl` field to get direct download links ### File Name Behavior **fileName Parameter Details**: * **Optional**: If not provided, a random file name will be automatically generated * **File Overwriting**: If a file with the same name already exists in the same path, the old file will be overwritten * **Caching**: Due to CDN caching mechanisms, file overwrites may not take effect immediately and could take several minutes to propagate ## Status Codes Request processed successfully, file upload completed Request parameters are incorrect or missing required parameters Authentication credentials are missing or invalid Request method is not supported, please check HTTP method An unexpected error occurred while processing the request, please retry or contact support ## Next Steps Learn how to upload files from remote URLs Master efficient file stream upload methods Understand Base64 encoded file uploads ## Support Need help? Our technical support team is here to assist you. * **Email**: [support@api.box](mailto:support@api.box) * **Documentation**: [docs.api.box](https://docs.api.box) * **API Status**: Check our status page for real-time API health *** Ready to start uploading files? [Get your API key](https://api.box/api-key) and begin using the file upload service immediately! # Base64 File Upload Source: https://docs.api.box/file-upload-api/upload-file-base-64 file-upload-api/file-upload-api.json POST /api/file-base64-upload Upload temporary files via Base64 encoded data. Note: Uploaded files are temporary and automatically deleted after 3 days. Upload temporary files via Base64 encoded data. Note: Uploaded files are temporary and automatically deleted after 3 days. ### Features * Supports Base64 encoded data and data URL format * Automatic MIME type recognition and file extension inference * Support for custom file names or auto-generation * Returns complete file information and download links * API Key authentication protection * Uploaded files are temporary and automatically deleted after 3 days ### Supported Formats * **Pure Base64 String**: `iVBORw0KGgoAAAANSUhEUgAA...` * **Data URL Format**: `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...` ### Usage Recommendations * Recommended for small files like images * For large files (>10MB), use the file stream upload API * Base64 encoding increases data transmission by approximately 33% # File Stream Upload Source: https://docs.api.box/file-upload-api/upload-file-stream file-upload-api/file-upload-api.json POST /api/file-stream-upload Upload temporary files via multipart/form-data format. Note: Uploaded files are temporary and automatically deleted after 3 days. ### Features * Supports binary stream upload for various file types * Suitable for large file uploads with high transmission efficiency * Automatic MIME type recognition * Support for custom file names or using original file names * Returns complete file information and download links * API Key authentication protection * Uploaded files are temporary and automatically deleted after 3 days ### Usage Recommendations * Recommended for large files (>10MB) * Supports various formats: images, videos, documents, etc. * Transmission efficiency is approximately 33% higher than Base64 format ### Example Command ```bash theme={null} curl -X POST https://apibox.redpandaai.co/api/file-stream-upload \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "file=@/path/to/your-file.jpg" \ -F "uploadPath=images/user-uploads" \ -F "fileName=custom-name.jpg" ``` # URL File Upload Source: https://docs.api.box/file-upload-api/upload-file-url file-upload-api/file-upload-api.json POST /api/file-url-upload Download files from URLs and upload them as temporary files. Note: Uploaded files are temporary and automatically deleted after 3 days. ### Features * Supports HTTP and HTTPS file links * Automatically downloads remote files and uploads them * Automatically extracts file names from URLs or uses custom file names * Automatic MIME type recognition * Returns complete file information and download links * API Key authentication protection * Uploaded files are temporary and automatically deleted after 3 days ### Supported Protocols * **HTTP**: `http://example.com/file.jpg` * **HTTPS**: `https://example.com/file.jpg` ### Use Cases * Migrating files from other services * Batch downloading and storing web resources * Backing up remote files * Caching external resources ### Important Notes * Ensure the provided URL is publicly accessible * Download timeout is 30 seconds * Recommended file size limit is 100MB # API.box Documentation Source: https://docs.api.box/index Complete API.box documentation - Your gateway to affordable and stable AI music API services # Welcome to API.box Documentation This documentation provides comprehensive guides and references for integrating [API.box](https://api.box/), a platform offering affordable and stable AI music API services that seamlessly integrate into your projects. ## About API.box API.box delivers advanced AI music capabilities through easy-to-integrate APIs, including music generation, lyrics creation, audio processing, and video production. Our platform is designed for developers and businesses who need: * **99.9% Uptime** - Reliable and stable API performance * **Affordable Pricing** - Transparent, usage-based pricing system * **20-Second Streaming Output** - Fast delivery with streaming response * **High Concurrency** - Scalable solutions that grow with your needs * **24/7 Support** - Professional technical assistance * **Watermark-Free** - Commercial-ready music generation ## Quick Start Guides Get started quickly with our comprehensive API quick start guides: ### 🎵 Music Generation APIs Create high-quality music from text descriptions using advanced AI models with support for various styles and genres. Extend existing music tracks with AI-powered continuation, maintaining musical coherence and style. Transform existing audio with new styles and arrangements using AI music processing. Upload your own audio files and extend them with AI-generated content. Generate vocal tracks for instrumental music using advanced AI models. Create instrumental accompaniment for vocal tracks with AI-powered arrangement. ### ✍️ Lyrics Creation APIs Create AI-powered lyrics for your songs with customizable themes and styles. Retrieve lyrics with precise timestamps for synchronization with audio tracks. ### 🔊 Audio Processing APIs Extract vocals and instrumental tracks separately using advanced AI audio separation. Convert generated music to high-quality WAV format for professional use. Enhance and refine music styles with AI-powered audio processing. ### 🎬 Music Video APIs Generate visual music videos from audio tracks using AI video generation technology. ### 🛠️ Utility APIs Monitor and retrieve detailed information about your music generation tasks. Check your account credit balance and usage statistics. Track the status and details of your lyrics generation requests. Monitor WAV format conversion tasks and download status. Check the progress of vocal separation tasks and access separated audio files. Track music video generation progress and retrieve download links. ## Documentation Features * **Interactive Examples** - Test APIs directly in our documentation * **Code Samples** - Ready-to-use examples in multiple programming languages * **Comprehensive Guides** - Step-by-step integration instructions * **API Reference** - Complete parameter documentation and response schemas * **Best Practices** - Optimization tips and common use cases * **Callback Documentation** - Webhook integration guides for all endpoints ## Key Features ### 🚀 Latest AI Music Models We provide APIs for the latest AI music models, including Suno V5, V5\_5, V4.5PLUS, V4.5, V4\_5ALL, and V4, offering high-quality music generation. Supports creation of both vocal and instrumental tracks, music extension, and multi-format downloads. ### 💎 Watermark-Free Commercial Use All music generated through our API is watermark-free, making it immediately suitable for commercial projects. This removes the need for additional fees, enabling creators and developers to effortlessly integrate high-quality tracks into their workflows. ### ⚡ 20-Second Streaming Output We ensure rapid delivery with streaming output, enabling developers to integrate AI-generated music seamlessly into their workflows without delays. This feature supports real-time applications and live content creation. ### 🏗️ High-Concurrency Architecture Our API is built to handle multiple simultaneous requests, ensuring reliable performance even under heavy traffic. This makes it ideal for large-scale applications and high-demand platforms. ### 💰 Transparent and Affordable Pricing We offer cost-effective and transparent pricing plans, making it accessible to creators and enterprises. Our transparent, usage-based model ensures predictable costs as shown on [API.box](https://api.box/). ### 🔧 Comprehensive Developer Support We streamline integration with detailed, developer-friendly API documentation, ensuring a hassle-free implementation process. Supported by an experienced technical team. ## Getting Started 1. **Sign Up** - Create your free account at [API.box](https://api.box/) 2. **Get API Key** - Obtain your authentication credentials from the API key management page 3. **Choose Your API** - Select from our comprehensive API collection 4. **Follow Quick Start** - Use our [Quick Start Guide](/suno-api/quickstart) for rapid integration 5. **Test & Deploy** - Verify your integration and go live ## AI Model Versions Choose the right model for your needs: ### V4\_5ALL - Extended Capabilities Supports longer lyrics (5000 characters) and style descriptions (1000 characters). Perfect for projects requiring more detailed creative control. ### V4 - Improved Vocals Enhanced vocal quality with refined audio processing, up to 4 minutes duration. Ideal when vocal clarity is most important. ### V4\_5 - Better Song Structure Improved song organization with clear verse/chorus patterns, max 1 minute duration. Ideal for short, well-structured compositions. ### V4\_5PLUS - Richer Tones Most advanced model with enhanced tonal variety and new creative approaches, up to 8 minutes duration. Best for highest quality and longest tracks. ### V5 - Latest Model Cutting-edge model with enhanced quality and capabilities. Our newest offering for premium music generation. ### V5\_5 - Custom voice character Unleash Your Voice: Custom Models Tailored to Your Unique Taste. Use **`V5_5`** anywhere the API accepts **`V5`** for the same request parameters and character limits (see OpenAPI for each endpoint). ## Use Cases ### 🎮 Game Developers Generate dynamic background music, sound effects, and adaptive audio for gaming experiences with our music generation and extension APIs. ### 🎬 Content Creators Create royalty-free music for videos, podcasts, and social media content with unlimited commercial use through our watermark-free output. ### 🏢 Businesses Integrate AI music generation into apps, websites, and services for enhanced user experiences using our high-concurrency APIs. ### 🎭 Music Producers Prototype songs, generate ideas, and create full compositions with professional-quality output. Use vocal separation for remixing and audio processing. ### 🎤 Karaoke & Entertainment Leverage timestamped lyrics and vocal separation features for karaoke applications and interactive music experiences. ## Support & Community * **24/7 Support** - Contact our technical team anytime * **Email Support** - [support@api.box](mailto:support@api.box) * **Documentation Updates** - Regular improvements and new features * **API Status** - Monitor real-time service status * **Developer Resources** - Comprehensive guides and best practices ## Callback Integration All major endpoints support webhook callbacks for real-time notifications: * [Music Generation Callbacks](/suno-api/generate-music-callbacks) * [Lyrics Generation Callbacks](/suno-api/generate-lyrics-callbacks) * [Music Extension Callbacks](/suno-api/extend-music-callbacks) * [Audio Processing Callbacks](/suno-api/separate-vocals-from-music-callbacks) * [Music Video Callbacks](/suno-api/create-music-video-callbacks) * [WAV Conversion Callbacks](/suno-api/convert-to-wav-format-callbacks) * [Upload & Cover Callbacks](/suno-api/upload-and-cover-audio-callbacks) * [Upload & Extend Callbacks](/suno-api/upload-and-extend-audio-callbacks) * [Add Vocals Callbacks](/suno-api/add-vocals-callbacks) * [Add Instrumental Callbacks](/suno-api/add-instrumental-callbacks) ## API Base URL All API requests should be made to: ``` https://apibox.erweima.ai ``` ## Authentication All API requests require authentication using Bearer tokens: ```http theme={null} Authorization: Bearer YOUR_API_KEY ``` Get your API key from the [API Key Management Page](https://api.box/api-key). *** Ready to get started? Choose an API above and follow the quick start guide to begin integrating powerful AI music capabilities into your projects. Visit [API.box](https://api.box/) to create your account and start generating amazing music today! # Add Instrumental Source: https://docs.api.box/suno-api/add-instrumental suno-api/suno-api.json POST /api/v1/generate/add-instrumental This endpoint generates a musical accompaniment tailored to an uploaded audio file — typically a vocal stem or melody track. It helps users instantly flesh out their vocal ideas with high-quality backing music, all without needing a producer. ### Model Versions * **Current models**: `V6` (default), `V6_WILD`, `V6_MINI` * **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4` * Deprecated values remain available only for backward compatibility. New integrations should use a V6-series model. ### **Key Capabilities** * Accepts uploadUrl of an existing audio file (usually vocals or stems). * Supports fine-grained customization via parameters such as: * tags and negativeTags (musical style controls) * styleWeight, audioWeight, weirdnessConstraint (stylistic & creative blending) * vocalGender, title, callBackUrl for metadata & workflow control  . * Returns a taskId for tracking, and results are retained for 14 days. Callback workflow includes three stages: text, first, and complete  . ### **Typical Use Cases** * Singers or melody writers who want instant fuller arrangements around their vocal inputs. * Applications like karaoke platforms, demo-generation tools, or co-creation interfaces that allow users to experiment with accompaniment styles easily. ### Parameter Details * **Required fields**: `uploadUrl`, `title`, `negativeTags`, `tags`, `callBackUrl`. All other fields are optional. * **Upload URL**: Must be a valid, publicly accessible audio file URL. Source audio is enough to generate. * **Title**: Used as the title for the generated instrumental track * **Tags**: Describe the desired style, mood, and instruments for the instrumental track * **Negative Tags**: Music styles or traits to exclude from the generated instrumental * **Lyrics**: Optional. Lyrics for the generated track. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters ### Optional parameters The following fields are optional controls available for this endpoint: * lyrics (string): Lyrics for the generated track. Optional. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters. * vocalGender (string): Preferred vocal gender for any vocal elements. Allowed values: `m` (male), `f` (female) * styleWeight (number): Style adherence weight in range 0–1 (recommended two decimals) * weirdnessConstraint (number): Creativity/novelty constraint in range 0–1 (recommended two decimals) * audioWeight (number): Relative weight of audio consistency in range 0–1 (recommended two decimals) * variety (integer): Diversity of generated results. Integer from 0–4, default 1. `0` off, `1` normal (default), `2` high, `3` extra, `4` max. * model (string): Model version used for generation. Current values: `V6` (default), `V6_WILD`, `V6_MINI`. Deprecated: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4`. ### Developer Notes * Callback process has three stages: `text` (text generation), `first` (first track complete), `complete` (all tracks complete) * In some cases, `text` and `first` stages may be skipped, directly returning `complete` * See [Add Instrumental Callbacks](./add-instrumental-callbacks) for detailed callback format * Monitor task progress using [Get Music Generation Details](./get-music-generation-details) # Add Instrumental Callbacks Source: https://docs.api.box/suno-api/add-instrumental-callbacks When instrumental generation tasks are completed, the system will send results to your provided callback URL via POST request When you submit a task to the Add Instrumental API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * Text generation completed (`text` stage) * First instrumental track generated (`first` stage) * All instrumental tracks generated (`complete` stage) * Instrumental generation task failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl` in the following format: ```json Text Generation Complete Callback theme={null} { "code": 200, "msg": "Text generation completed successfully.", "data": { "callbackType": "text", "task_id": "2fac****9f72", "data": [] } } ``` ```json First Track Complete Callback theme={null} { "code": 200, "msg": "First instrumental track generated successfully.", "data": { "callbackType": "first", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Instrumental] Relaxing piano melody with ambient textures", "model_name": "chirp-v3-5", "title": "Relaxing Piano Instrumental", "tags": "relaxing, piano, instrumental, ambient", "createTime": "2025-01-01 00:00:00", "duration": 198.44 } ] } } ``` ```json All Tracks Complete Callback theme={null} { "code": 200, "msg": "All generated successfully.", "data": { "callbackType": "complete", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Instrumental] Relaxing piano melody with ambient textures", "model_name": "chirp-v3-5", "title": "Relaxing Piano Instrumental", "tags": "relaxing, piano, instrumental, ambient", "createTime": "2025-01-01 00:00:00", "duration": 198.44 }, { "id": "bd15****1873", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Instrumental] Layered instrumental arrangement", "model_name": "chirp-v3-5", "title": "Relaxing Piano Instrumental", "tags": "relaxing, piano, instrumental, ambient", "createTime": "2025-01-01 00:00:00", "duration": 228.28 } ] } } ``` ```json Failed Callback theme={null} { "code": 400, "msg": "Failed to add instrumental, invalid source audio format", "data": { "callbackType": "failed", "task_id": "2fac****9f72", "data": [] } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Instrumental generation completed | | 400 | Bad Request - Parameter error or invalid source audio | | 401 | Unauthorized - Invalid API key | | 413 | Content Too Long - Tags or style description exceeds limit | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Callback type indicating the current callback stage: * `text`: Text generation completed * `first`: First instrumental track generated * `complete`: All instrumental tracks generated * `failed`: Task failed Task ID, consistent with the taskId returned when you submitted the task Instrumental generation result information, returned on success Audio unique identifier (audioId) Audio file download link with instrumental elements **Deprecated.** Original audio file link returned by Suno. This link expires after a period of time and is no longer maintained — do not rely on it for long-term storage. Use the [Recovery Audio](/suno-api/recovery-audio) endpoint to obtain a fresh playable link. Streaming audio playback link with instrumental elements Music cover image link Prompt used for instrumental generation AI model name used for instrumental generation Music title with instrumental elements Music style tags including instrumental characteristics Creation time Audio duration (seconds) ## Callback Reception Examples Here are example codes for receiving callbacks in various popular programming languages: ```javascript theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/instrumental-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Received instrumental generation callback:', { taskId: data.task_id, callbackType: data.callbackType, status: code, message: msg }); if (code === 200) { // Task successful const { callbackType, data: instrumentalData } = data; switch (callbackType) { case 'text': console.log('Text generation completed'); break; case 'first': console.log('First instrumental track generated'); if (instrumentalData.length > 0) { console.log(`Track title: ${instrumentalData[0].title}`); console.log(`Instrumental audio link: ${instrumentalData[0].audio_url}`); console.log(`Duration: ${instrumentalData[0].duration} seconds`); console.log(`Instrumental style: ${instrumentalData[0].tags}`); } break; case 'complete': console.log('All instrumental tracks generated'); console.log(`Total ${instrumentalData.length} instrumental tracks generated:`); instrumentalData.forEach((track, index) => { console.log(`Track ${index + 1}: ${track.title} - ${track.audio_url}`); console.log(`Style: ${track.tags}`); }); // Process generated instrumental tracks // Can download audio, save locally, etc. break; } } else { // Task failed console.log('Instrumental generation failed:', msg); // Handle failure cases... if (code === 400) { console.log('Parameter error or invalid source audio'); } else if (code === 429) { console.log('Insufficient credits'); } else if (code === 500) { console.log('Server internal error'); } } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); app.listen(3000, () => { console.log('Instrumental callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import requests app = Flask(__name__) @app.route('/instrumental-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) task_id = callback_data.get('task_id') callback_type = callback_data.get('callbackType') instrumental_data = callback_data.get('data', []) print(f"Received instrumental generation callback: {task_id}, Type: {callback_type}, Status: {code}") if code == 200: # Task successful if callback_type == 'text': print("Text generation completed") elif callback_type == 'first': print("First instrumental track generated") if instrumental_data: track = instrumental_data[0] print(f"Track title: {track.get('title')}") print(f"Instrumental audio link: {track.get('audio_url')}") print(f"Duration: {track.get('duration')} seconds") print(f"Instrumental style: {track.get('tags')}") elif callback_type == 'complete': print("All instrumental tracks generated") print(f"Total {len(instrumental_data)} instrumental tracks generated:") for i, track in enumerate(instrumental_data): print(f"Track {i + 1}: {track.get('title')} - {track.get('audio_url')}") print(f"Style: {track.get('tags')}") # Download instrumental audio example try: audio_url = track.get('audio_url') if audio_url: response = requests.get(audio_url) if response.status_code == 200: filename = f"instrumental_{task_id}_{i + 1}.mp3" with open(filename, "wb") as f: f.write(response.content) print(f"Instrumental audio saved as {filename}") except Exception as e: print(f"Instrumental audio download failed: {e}") else: # Task failed print(f"Instrumental generation failed: {msg}") # Handle failure cases... if code == 400: print("Parameter error or invalid source audio") elif code == 429: print("Insufficient credits") elif code == 500: print("Server internal error") # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```php theme={null} $track) { $title = $track['title'] ?? ''; $audioUrl = $track['audio_url'] ?? ''; $tags = $track['tags'] ?? ''; error_log("Track " . ($index + 1) . ": $title - $audioUrl"); error_log("Style: $tags"); // Download instrumental audio example try { if ($audioUrl) { $audioContent = file_get_contents($audioUrl); if ($audioContent !== false) { $filename = "instrumental_{$taskId}_" . ($index + 1) . ".mp3"; file_put_contents($filename, $audioContent); error_log("Instrumental audio saved as $filename"); } } } catch (Exception $e) { error_log("Instrumental audio download failed: " . $e->getMessage()); } } break; } } else { // Task failed error_log("Instrumental generation failed: $msg"); // Handle failure cases... if ($code === 400) { error_log("Parameter error or invalid source audio"); } elseif ($code === 429) { error_log("Insufficient credits"); } elseif ($code === 500) { error_log("Server internal error"); } } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### Instrumental Generation Callback Configuration Recommendations 1. **Use HTTPS**: Ensure your callback URL uses HTTPS protocol for secure data transmission 2. **Verify Source**: Verify the legitimacy of the request source in callback processing 3. **Idempotent Processing**: Ensure processing logic is idempotent as the same taskId may receive multiple callbacks 4. **Quick Response**: Callback processing should return 200 status code quickly to avoid timeout 5. **Asynchronous Processing**: Complex business logic should be processed asynchronously to avoid blocking callback response 6. **Stage-based Processing**: Handle different callback stages (text, first, complete) with appropriate business logic 7. **Audio Quality Assessment**: Implement audio quality assessment for generated instrumental tracks 8. **Style Validation**: Validate that generated instrumental matches requested style and characteristics ### Important Reminders * Callback URL must be publicly accessible * Server must respond within 15 seconds, otherwise considered timeout * After 3 consecutive retry failures, the system will stop sending callbacks * Ensure stability of callback processing logic to avoid callback failures due to exceptions * Generated instrumental audio URLs may have time limits, recommend downloading and saving promptly * Pay attention to source audio quality to ensure optimal instrumental generation results * Instrumental generation has three stages, each stage will trigger callback notifications * Consider implementing audio format validation for source files ## Troubleshooting If you don't receive callback notifications, please check the following: * Confirm that the callback URL is accessible from the public internet * Check firewall settings to ensure inbound requests are not blocked * Verify that domain name resolution is correct * Ensure the server returns HTTP 200 status code within 15 seconds * Check server logs for error messages * Verify that the interface path and HTTP method are correct * Confirm that the received POST request body is in JSON format * Check if Content-Type is application/json * Verify that JSON parsing is correct * Confirm that instrumental audio URLs are accessible * Check instrumental audio download permissions and network connectivity * Verify audio save path and permissions * Ensure source audio format is supported and valid * Verify instrumental quality meets your application requirements * Understand the differences and handling methods of the three callback stages * text stage: Only indicates text generation completed, no audio data * first stage: First instrumental track completed, contains data for one track * complete stage: All instrumental tracks completed, contains complete instrumental track list * Implement audio format validation for source files * Check instrumental audio quality and format compatibility * Assess if generated instrumental meets style requirements * Handle different instrumental styles and arrangements appropriately ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Music Generation Details interface to regularly query task status. Recommend querying every 30 seconds. # Add Vocals Source: https://docs.api.box/suno-api/add-vocals suno-api/suno-api.json POST /api/v1/generate/add-vocals This endpoint layers AI-generated vocals on top of an existing instrumental. Given a prompt (e.g., lyrical concept or musical mood) and optional audio, it produces vocal output harmonized with the provided track. ### Model Versions * **Current models**: `V6` (default), `V6_WILD`, `V6_MINI` * **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4` * Deprecated values remain available only for backward compatibility. New integrations should use a V6-series model. ### **Key Capabilities** * Accepts an existing instrumental via uploadUrl, with optional prompt-based stylistic input. * Supports control parameters including: * prompt, style, tags, negativeTags (define lyrical content and vocal style) * vocalGender, styleWeight, weirdnessConstraint, audioWeight, callBackUrl  . * Returns a taskId, supports the same 14-day retention and three-stage callback model as the instrumental endpoint  . ### **Typical Use Cases** * Music platforms or tools enabling topline creation and rapid prototyping of lyrical ideas. * Collaborative songwriting or co-creation workflows, where lyrics or vocal styles are iteratively tested over instrumental drafts. ### Parameter Details * **Required fields**: `uploadUrl`, `callBackUrl`, `title`, `negativeTags`, `style`. All other fields are optional. * **Upload URL**: Must be a valid, publicly accessible audio file URL. Source audio is enough to generate. * **Style**: Describes the overall genre and vocal approach (Jazz, Classical, Electronic, Pop) * **Negative Tags**: Music styles or vocal traits to exclude from generation * **Title**: Used as the title for the generated vocal track * **Lyrics**: Optional. Lyrics for the generated vocals. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters * **Prompt**: Optional. Describes the desired vocal style and content ### Optional parameters The following fields are optional controls available for this endpoint: * lyrics (string): Lyrics for the generated vocals. Optional. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters. * prompt (string): Description of the audio content to generate vocals for. Optional. * vocalGender (string): Preferred vocal gender. Allowed values: `m` (male), `f` (female) * styleWeight (number): Style adherence weight in range 0–1 (recommended two decimals) * weirdnessConstraint (number): Creativity/novelty constraint in range 0–1 (recommended two decimals) * audioWeight (number): Relative weight of audio consistency in range 0–1 (recommended two decimals) * variety (integer): Diversity of generated results. Integer from 0–4, default 1. `0` off, `1` normal (default), `2` high, `3` extra, `4` max. * model (string): Model version used for generation. Current values: `V6` (default), `V6_WILD`, `V6_MINI`. Deprecated: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4`. ### Developer Notes * Callback process has three stages: `text` (text generation), `first` (first track complete), `complete` (all tracks complete) * In some cases, `text` and `first` stages may be skipped, directly returning `complete` * See [Add Vocals Callbacks](./add-vocals-callbacks) for detailed callback format * Monitor task progress using [Get Music Generation Details](./get-music-generation-details) # Add Vocals Callbacks Source: https://docs.api.box/suno-api/add-vocals-callbacks When vocal generation tasks are completed, the system will send results to your provided callback URL via POST request When you submit a task to the Add Vocals API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * Text generation completed (`text` stage) * First vocal track generated (`first` stage) * All vocal tracks generated (`complete` stage) * Vocal generation task failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl` in the following format: ```json Text Generation Complete Callback theme={null} { "code": 200, "msg": "Text generation completed successfully.", "data": { "callbackType": "text", "task_id": "2fac****9f72", "data": [] } } ``` ```json First Track Complete Callback theme={null} { "code": 200, "msg": "First vocal track generated successfully.", "data": { "callbackType": "first", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Calm and relaxing melodies with soothing vocals", "model_name": "chirp-v3-5", "title": "Relaxing Piano with Vocals", "tags": "relaxing, piano, vocals, jazz", "createTime": "2025-01-01 00:00:00", "duration": 198.44 } ] } } ``` ```json All Tracks Complete Callback theme={null} { "code": 200, "msg": "All generated successfully.", "data": { "callbackType": "complete", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Calm and relaxing melodies with soothing vocals", "model_name": "chirp-v3-5", "title": "Relaxing Piano with Vocals", "tags": "relaxing, piano, vocals, jazz", "createTime": "2025-01-01 00:00:00", "duration": 198.44 }, { "id": "bd15****1873", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Chorus] Harmonious voices singing together", "model_name": "chirp-v3-5", "title": "Relaxing Piano with Vocals", "tags": "relaxing, piano, vocals, jazz", "createTime": "2025-01-01 00:00:00", "duration": 228.28 } ] } } ``` ```json Failed Callback theme={null} { "code": 400, "msg": "Failed to add vocals, containing inappropriate vocal content", "data": { "callbackType": "failed", "task_id": "2fac****9f72", "data": [] } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Vocal generation completed | | 400 | Bad Request - Parameter error or content violation | | 401 | Unauthorized - Invalid API key | | 413 | Content Too Long - Prompt or style description exceeds limit | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Callback type indicating the current callback stage: * `text`: Text generation completed * `first`: First vocal track generated * `complete`: All vocal tracks generated * `failed`: Task failed Task ID, consistent with the taskId returned when you submitted the task Vocal generation result information, returned on success Audio unique identifier (audioId) Audio file download link with vocals **Deprecated.** Original audio file link returned by Suno. This link expires after a period of time and is no longer maintained — do not rely on it for long-term storage. Use the [Recovery Audio](/suno-api/recovery-audio) endpoint to obtain a fresh playable link. Streaming audio playback link with vocals Music cover image link Prompt/lyrics used for vocal generation AI model name used for vocal generation Music title with vocals Music style tags including vocal characteristics Creation time Audio duration (seconds) ## Callback Reception Examples Here are example codes for receiving callbacks in various popular programming languages: ```javascript theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/vocals-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Received vocal generation callback:', { taskId: data.task_id, callbackType: data.callbackType, status: code, message: msg }); if (code === 200) { // Task successful const { callbackType, data: vocalsData } = data; switch (callbackType) { case 'text': console.log('Text generation completed'); break; case 'first': console.log('First vocal track generated'); if (vocalsData.length > 0) { console.log(`Track title: ${vocalsData[0].title}`); console.log(`Vocal audio link: ${vocalsData[0].audio_url}`); console.log(`Duration: ${vocalsData[0].duration} seconds`); console.log(`Vocals prompt: ${vocalsData[0].prompt}`); } break; case 'complete': console.log('All vocal tracks generated'); console.log(`Total ${vocalsData.length} vocal tracks generated:`); vocalsData.forEach((track, index) => { console.log(`Track ${index + 1}: ${track.title} - ${track.audio_url}`); console.log(`Vocals: ${track.prompt}`); }); // Process generated vocal tracks // Can download audio, save locally, etc. break; } } else { // Task failed console.log('Vocal generation failed:', msg); // Handle failure cases... if (code === 400) { console.log('Parameter error or vocal content violation'); } else if (code === 429) { console.log('Insufficient credits'); } else if (code === 500) { console.log('Server internal error'); } } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); app.listen(3000, () => { console.log('Vocal callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import requests app = Flask(__name__) @app.route('/vocals-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) task_id = callback_data.get('task_id') callback_type = callback_data.get('callbackType') vocals_data = callback_data.get('data', []) print(f"Received vocal generation callback: {task_id}, Type: {callback_type}, Status: {code}") if code == 200: # Task successful if callback_type == 'text': print("Text generation completed") elif callback_type == 'first': print("First vocal track generated") if vocals_data: track = vocals_data[0] print(f"Track title: {track.get('title')}") print(f"Vocal audio link: {track.get('audio_url')}") print(f"Duration: {track.get('duration')} seconds") print(f"Vocals prompt: {track.get('prompt')}") elif callback_type == 'complete': print("All vocal tracks generated") print(f"Total {len(vocals_data)} vocal tracks generated:") for i, track in enumerate(vocals_data): print(f"Track {i + 1}: {track.get('title')} - {track.get('audio_url')}") print(f"Vocals: {track.get('prompt')}") # Download vocal audio example try: audio_url = track.get('audio_url') if audio_url: response = requests.get(audio_url) if response.status_code == 200: filename = f"vocals_{task_id}_{i + 1}.mp3" with open(filename, "wb") as f: f.write(response.content) print(f"Vocal audio saved as {filename}") except Exception as e: print(f"Vocal audio download failed: {e}") else: # Task failed print(f"Vocal generation failed: {msg}") # Handle failure cases... if code == 400: print("Parameter error or vocal content violation") elif code == 429: print("Insufficient credits") elif code == 500: print("Server internal error") # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```php theme={null} $track) { $title = $track['title'] ?? ''; $audioUrl = $track['audio_url'] ?? ''; $prompt = $track['prompt'] ?? ''; error_log("Track " . ($index + 1) . ": $title - $audioUrl"); error_log("Vocals: $prompt"); // Download vocal audio example try { if ($audioUrl) { $audioContent = file_get_contents($audioUrl); if ($audioContent !== false) { $filename = "vocals_{$taskId}_" . ($index + 1) . ".mp3"; file_put_contents($filename, $audioContent); error_log("Vocal audio saved as $filename"); } } } catch (Exception $e) { error_log("Vocal audio download failed: " . $e->getMessage()); } } break; } } else { // Task failed error_log("Vocal generation failed: $msg"); // Handle failure cases... if ($code === 400) { error_log("Parameter error or vocal content violation"); } elseif ($code === 429) { error_log("Insufficient credits"); } elseif ($code === 500) { error_log("Server internal error"); } } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### Vocal Generation Callback Configuration Recommendations 1. **Use HTTPS**: Ensure your callback URL uses HTTPS protocol for secure data transmission 2. **Verify Source**: Verify the legitimacy of the request source in callback processing 3. **Idempotent Processing**: Ensure processing logic is idempotent as the same taskId may receive multiple callbacks 4. **Quick Response**: Callback processing should return 200 status code quickly to avoid timeout 5. **Asynchronous Processing**: Complex business logic should be processed asynchronously to avoid blocking callback response 6. **Stage-based Processing**: Handle different callback stages (text, first, complete) with appropriate business logic 7. **Vocal Content Analysis**: Implement vocal content analysis and quality assessment for generated tracks 8. **Lyrics Extraction**: Extract and process lyrics from vocal prompts for better content management ### Important Reminders * Callback URL must be publicly accessible * Server must respond within 15 seconds, otherwise considered timeout * After 3 consecutive retry failures, the system will stop sending callbacks * Ensure stability of callback processing logic to avoid callback failures due to exceptions * Generated vocal audio URLs may have time limits, recommend downloading and saving promptly * Pay attention to vocal content compliance to avoid generation failures due to violations * Vocal generation has three stages, each stage will trigger callback notifications * Consider implementing content filtering for vocal lyrics and audio content ## Troubleshooting If you don't receive callback notifications, please check the following: * Confirm that the callback URL is accessible from the public internet * Check firewall settings to ensure inbound requests are not blocked * Verify that domain name resolution is correct * Ensure the server returns HTTP 200 status code within 15 seconds * Check server logs for error messages * Verify that the interface path and HTTP method are correct * Confirm that the received POST request body is in JSON format * Check if Content-Type is application/json * Verify that JSON parsing is correct * Confirm that vocal audio URLs are accessible * Check vocal audio download permissions and network connectivity * Verify audio save path and permissions * Note that vocal content must comply with content policies * Verify vocal quality meets your application requirements * Understand the differences and handling methods of the three callback stages * text stage: Only indicates text generation completed, no audio data * first stage: First vocal track completed, contains data for one track * complete stage: All vocal tracks completed, contains complete vocal track list * Implement lyrics extraction from vocal prompts * Check vocal content for compliance with platform policies * Assess vocal quality and appropriateness for your use case * Handle different vocal styles and languages appropriately ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Music Generation Details interface to regularly query task status. Recommend querying every 30 seconds. # Boost Music Style Source: https://docs.api.box/suno-api/boost-music-style suno-api/suno-api.json POST /api/v1/style/generate This is an exclusive capability of V4\_5. The style functionality of V4\_5 has been significantly enhanced, as stated on the official website: > One of the many advantages of the new 4.5 model is its ability to accommodate more detailed style instructions. In previous models, it was necessary to prioritize specific genre and style details, but now instructions can incorporate a more conversational prompt. > > Previously, optimal results might have been achieved with a prompt like: 'deep house, emotional, melodic.' > > Now, you can provide a prompt such as: 'Create a melodic, emotional deep house song featuring organic textures and hypnotic rhythms. Begin with soft ambient layers, natural sounds, and a deep, steady groove. Gradually build with flowing melodic synths, warm basslines, and intricate, subtle percussion.' The 'Boost Your Style' feature will significantly enhance users' ability to describe and control style. It is recommended for use. ### Parameter Description * content: Required, string type. Style description is required. # Convert to WAV Format Source: https://docs.api.box/suno-api/convert-to-wav-format suno-api/suno-api.json POST /api/v1/wav/generate Convert existing music tracks to high-quality WAV format. ### Usage Guide * Provide either taskId or audioId to identify the source track * WAV format is ideal for professional audio editing and production * The conversion preserves full audio quality ### Developer Notes 1. Generated WAV files are retained for 15 days 2. WAV files are significantly larger than MP3 files 3. This format is recommended for further audio processing or professional use 4. Callback provides a single download URL when conversion is complete # WAV Format Conversion Callbacks Source: https://docs.api.box/suno-api/convert-to-wav-format-callbacks When WAV format conversion tasks are completed, the system will send results to your provided callback URL via POST request When you submit a task to the WAV format conversion API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * WAV format conversion completed * WAV conversion task failed * Error occurred during task processing WAV format conversion has only one callback stage, providing the download URL upon completion ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl` in the following format: ```json WAV Conversion Complete Callback theme={null} { "code": 200, "msg": "success", "data": { "audioWavUrl": "https://example.com/s/04e6****e727.wav", "task_id": "988e****c8d3" } } ``` ```json WAV Conversion Failed Callback theme={null} { "code": 400, "msg": "WAV conversion failed, invalid source audio", "data": { "task_id": "988e****c8d3", "audioWavUrl": null } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - WAV conversion completed | | 400 | Bad Request - Invalid source audio or parameter error | | 401 | Unauthorized - Invalid API key | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Task ID, consistent with the taskId returned when you submitted the task WAV format audio file download URL (returned on success) ## Callback Reception Examples Here are example codes for receiving callbacks in various popular programming languages: ```javascript theme={null} const express = require('express'); const fs = require('fs'); const https = require('https'); const app = express(); app.use(express.json()); app.post('/wav-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Received WAV conversion callback:', { taskId: data.task_id, status: code, message: msg }); if (code === 200 && data.audioWavUrl) { // WAV conversion successful console.log(`WAV file ready: ${data.audioWavUrl}`); // Download WAV file downloadWavFile(data.audioWavUrl, data.task_id); } else { // Task failed console.log('WAV conversion failed:', msg); // Handle failure cases... if (code === 400) { console.log('Invalid source audio or parameter error'); } else if (code === 429) { console.log('Insufficient credits'); } else if (code === 500) { console.log('Server internal error'); } } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); function downloadWavFile(url, taskId) { const filename = `wav_${taskId}.wav`; const file = fs.createWriteStream(filename); https.get(url, (response) => { response.pipe(file); file.on('finish', () => { file.close(); console.log(`WAV file downloaded: ${filename}`); }); }).on('error', (err) => { console.error('WAV download failed:', err.message); }); } app.listen(3000, () => { console.log('WAV callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import requests app = Flask(__name__) @app.route('/wav-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) task_id = callback_data.get('task_id') wav_url = callback_data.get('audioWavUrl') print(f"Received WAV conversion callback: {task_id}, Status: {code}") if code == 200 and wav_url: # WAV conversion successful print(f"WAV file ready: {wav_url}") # Download WAV file download_wav_file(wav_url, task_id) else: # Task failed print(f"WAV conversion failed: {msg}") # Handle failure cases... if code == 400: print("Invalid source audio or parameter error") elif code == 429: print("Insufficient credits") elif code == 500: print("Server internal error") # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 def download_wav_file(url, task_id): """Download WAV file from the provided URL""" try: response = requests.get(url) if response.status_code == 200: filename = f"wav_{task_id}.wav" with open(filename, "wb") as f: f.write(response.content) print(f"WAV file downloaded: {filename}") else: print(f"Failed to download WAV file: HTTP {response.status_code}") except Exception as e: print(f"WAV download failed: {e}") if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```php theme={null} getMessage()); } } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### WAV Conversion Callback Configuration 1. **File Management**: Implement proper file naming conventions for downloaded WAV files 2. **Storage Planning**: Ensure adequate storage space for high-quality WAV files 3. **Quality Verification**: Verify WAV file integrity after download 4. **Metadata Preservation**: Maintain track information and metadata with WAV files 5. **Batch Processing**: Consider batch conversion for multiple tracks 6. **Cleanup**: Implement cleanup procedures for temporary files ### WAV-Specific Considerations * WAV files are typically larger than MP3 files due to lossless compression * Download times may be longer due to file size * Ensure sufficient bandwidth for WAV file downloads * WAV format provides maximum audio quality for professional use * Consider storage costs for large WAV file collections ## Troubleshooting Common issues specific to WAV conversion callbacks: * Verify the WAV URL is accessible and not expired * Check network connectivity and bandwidth * Ensure sufficient local storage space * Verify download permissions and file paths * Confirm the source audio quality meets WAV conversion requirements * Check if the original audio file is corrupted * Verify that the converted WAV maintains expected quality * Test WAV file playback in different audio applications * Implement proper file naming to avoid conflicts * Monitor storage usage for WAV file collections * Consider automated cleanup for old WAV files * Verify file integrity after download completion ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get WAV Conversion Details interface to regularly query conversion task status. Recommend querying every 20 seconds. # Generate Music Cover Source: https://docs.api.box/suno-api/cover-suno suno-api/suno-api.json POST /api/v1/suno/cover/generate Create personalized cover images for generated music. ### Usage Guide * Use this interface to create personalized cover images for generated music * Requires the taskId of the original music task * Each music task can only generate a Cover once; duplicate requests will return the existing taskId * Results will be notified through the callback URL upon completion ### Parameter Details * `taskId` identifies the unique identifier of the original music generation task * `callBackUrl` receives callback address for completion notifications ### Developer Notes * Cover image file URLs will be retained for 14 days * If a Cover has already been generated for this music task, a 400 status code and existing taskId will be returned * It's recommended to call this interface after music generation is complete * Usually generates 2 different style images for selection # Music Cover Generation Callbacks Source: https://docs.api.box/suno-api/cover-suno-callbacks When music cover generation is complete, the system will call this callback to notify results. When you submit a cover generation task to the Suno API, you can use the `callBackUrl` parameter to set the callback URL. When the task is complete, the system will automatically push results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will actively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * Cover generation task completed successfully * Cover generation task failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout Setting**: 15 seconds ## Callback Request Format When the task is complete, the system will send a POST request to your `callBackUrl`: ```json Success Callback theme={null} { "code": 200, "data": { "images": [ "https://tempfile.aiquickdraw.com/s/1753958521_6c1b3015141849d1a9bf17b738ce9347.png", "https://tempfile.aiquickdraw.com/s/1753958524_c153143acc6340908431cf0e90cbce9e.png" ], "taskId": "21aee3c3c2a01fa5e030b3799fa4dd56" }, "msg": "success" } ``` ```json Failure Callback theme={null} { "code": 501, "msg": "Cover generation failed", "data": { "taskId": "21aee3c3c2a01fa5e030b3799fa4dd56", "images": null } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Request processed successfully | | 400 | Validation error - Request parameters invalid | | 408 | Rate limited - Timeout | | 500 | Server error - Unexpected error occurred while processing request | | 501 | Cover generation failed | | 531 | Server error - Sorry, generation failed due to an issue. Your credits have been refunded. Please try again | Status message providing more detailed status description Task ID, consistent with the taskId returned when you submitted the task Array of generated cover image URLs, returned on success. Usually contains 2 different style cover images ## Callback Reception Examples Here are example codes for receiving callbacks in common programming languages: ```javascript theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/suno-cover-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Received cover generation callback:', { taskId: data.taskId, status: code, message: msg }); if (code === 200) { // Task completed successfully console.log('Cover generation completed'); const images = data.images; if (images && images.length > 0) { console.log('Generated cover images:'); images.forEach((imageUrl, index) => { console.log(`Cover ${index + 1}: ${imageUrl}`); }); // Process cover images // Can download images, save locally, update database, etc. downloadImages(images, data.taskId); } } else { // Task failed console.log('Cover generation failed:', msg); // Handle failure cases... } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); // Download images function async function downloadImages(imageUrls, taskId) { const fs = require('fs'); const path = require('path'); const https = require('https'); // Create directory const dir = `covers/${taskId}`; if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } for (let i = 0; i < imageUrls.length; i++) { const url = imageUrls[i]; const filename = path.join(dir, `cover_${i + 1}.png`); try { await downloadFile(url, filename); console.log(`Cover saved: ${filename}`); } catch (error) { console.error(`Download failed: ${error.message}`); } } } function downloadFile(url, filename) { return new Promise((resolve, reject) => { const file = fs.createWriteStream(filename); https.get(url, (response) => { response.pipe(file); file.on('finish', () => { file.close(); resolve(); }); }).on('error', (err) => { fs.unlink(filename, () => {}); // Delete failed file reject(err); }); }); } app.listen(3000, () => { console.log('Callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import requests import os from urllib.parse import urlparse app = Flask(__name__) @app.route('/suno-cover-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) task_id = callback_data.get('taskId') images = callback_data.get('images') print(f"Received cover generation callback: {task_id}, status: {code}, message: {msg}") if code == 200: # Task completed successfully print("Cover generation completed") if images: print("Generated cover images:") for i, image_url in enumerate(images, 1): print(f"Cover {i}: {image_url}") # Download cover images download_images(images, task_id) else: # Task failed print(f"Cover generation failed: {msg}") # Handle failure cases... # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 def download_images(image_urls, task_id): """Download cover images""" # Create directory dir_path = f"covers/{task_id}" os.makedirs(dir_path, exist_ok=True) for i, url in enumerate(image_urls, 1): try: # Get file extension parsed_url = urlparse(url) file_ext = os.path.splitext(parsed_url.path)[1] or '.png' filename = os.path.join(dir_path, f"cover_{i}{file_ext}") # Download file response = requests.get(url, stream=True) if response.status_code == 200: with open(filename, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) print(f"Cover saved: {filename}") else: print(f"Download failed {url}: HTTP {response.status_code}") except Exception as e: print(f"Download failed {url}: {e}") if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```java theme={null} /** * @param request Callback request * @return ResponseEntity * @author zj * @description Handle Suno Cover generation callback * @date 2025/1/15 **/ @PostMapping("/suno-cover-callback") @Operation(summary = "Suno Cover generation callback", description = "Receive Cover generation completion notification") public ResponseEntity> handleCoverCallback( @RequestBody CoverCallbackRequest request) { log.info("Received cover generation callback: taskId={}, status={}, message={}", request.getData().getTaskId(), request.getCode(), request.getMsg()); try { if (request.getCode() == 200) { // Task completed successfully log.info("Cover generation completed"); List images = request.getData().getImages(); if (images != null && !images.isEmpty()) { log.info("Generated cover images: {}", images); // Process cover images processCoverImages(request.getData().getTaskId(), images); } } else { // Task failed log.error("Cover generation failed: {}", request.getMsg()); // Handle failure cases handleCoverGenerationFailure(request.getData().getTaskId(), request.getCode(), request.getMsg()); } // Update task status coverTaskService.updateTaskStatus(request.getData().getTaskId(), request.getCode(), request.getMsg(), request.getData().getImages()); } catch (Exception e) { log.error("Failed to process cover generation callback", e); return ResponseEntity.status(500) .body(Map.of("status", "error", "message", e.getMessage())); } // Return 200 status code to confirm callback received return ResponseEntity.ok(Map.of("status", "received")); } /** * @param taskId Task ID * @param imageUrls Image URL list * @author zj * @description Process cover images * @date 2025/1/15 **/ private void processCoverImages(String taskId, List imageUrls) { // Asynchronously download images CompletableFuture.runAsync(() -> { try { downloadCoverImages(taskId, imageUrls); } catch (Exception e) { log.error("Failed to download cover images: taskId={}", taskId, e); } }); } /** * @param taskId Task ID * @param imageUrls Image URL list * @author zj * @description Download cover images * @date 2025/1/15 **/ private void downloadCoverImages(String taskId, List imageUrls) { String dirPath = "covers/" + taskId; File dir = new File(dirPath); if (!dir.exists()) { dir.mkdirs(); } for (int i = 0; i < imageUrls.size(); i++) { String url = imageUrls.get(i); String filename = dirPath + "/cover_" + (i + 1) + ".png"; try { downloadFile(url, filename); log.info("Cover saved: {}", filename); } catch (Exception e) { log.error("Download failed: {}", url, e); } } } @Data public class CoverCallbackRequest { private Integer code; private String msg; private CoverCallbackData data; } @Data public class CoverCallbackData { private String taskId; private List images; } ``` ```php theme={null} 0) { error_log("Generated cover images: " . implode(', ', $images)); // Download cover images downloadCoverImages($taskId, $images); } } else { // Task failed error_log("Cover generation failed: $msg"); // Handle failure cases... } /** * Download cover images * @param string $taskId Task ID * @param array $imageUrls Image URL array */ function downloadCoverImages($taskId, $imageUrls) { // Create directory $dir = "covers/$taskId"; if (!is_dir($dir)) { mkdir($dir, 0777, true); } foreach ($imageUrls as $index => $url) { $filename = $dir . "/cover_" . ($index + 1) . ".png"; try { $imageContent = file_get_contents($url); if ($imageContent !== false) { file_put_contents($filename, $imageContent); error_log("Cover saved: $filename"); } else { error_log("Download failed: $url"); } } catch (Exception $e) { error_log("Download failed $url: " . $e->getMessage()); } } } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### Callback URL Configuration Recommendations 1. **Use HTTPS**: Ensure callback URL uses HTTPS protocol for data transmission security 2. **Verify Source**: Verify the legitimacy of request sources in callback processing 3. **Idempotent Processing**: The same taskId may receive multiple callbacks, ensure processing logic is idempotent 4. **Quick Response**: Callback processing should return 200 status code quickly to avoid timeout 5. **Asynchronous Processing**: Complex business logic should be processed asynchronously to avoid blocking callback response 6. **Image Management**: Download and save images promptly, noting URL validity period 7. **Error Retry**: Implement retry mechanism for failed image downloads ### Important Reminders * Callback URL must be a publicly accessible address * Server must respond within 15 seconds, otherwise it will be considered timeout * If 3 consecutive retries fail, the system will stop sending callbacks * Please ensure stability of callback processing logic to avoid callback failures due to exceptions * Cover image URLs may have validity periods, recommend downloading and saving promptly * Usually generates 2 different style cover images for selection * Note handling exceptions for failed image downloads ## Troubleshooting If you don't receive callback notifications, please check the following: * Confirm callback URL is accessible from the public internet * Check firewall settings to ensure inbound requests are not blocked * Verify domain name resolution is correct * Ensure server returns HTTP 200 status code within 15 seconds * Check server logs for error messages * Verify interface path and HTTP method are correct * Confirm received POST request body is in JSON format * Check if Content-Type is application/json * Verify JSON parsing is correct * Confirm image URLs are accessible * Check image download permissions and network connection * Verify file save path and permissions * Note image URL validity period limitations ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Cover Details endpoint to periodically query task status. We recommend querying every 30 seconds. # Create Music Video Source: https://docs.api.box/suno-api/create-music-video suno-api/suno-api.json POST /api/v1/mp4/generate Generate an MP4 video with visualizations for a music track. ### Usage Guide * This endpoint creates a visual representation of your music track as an MP4 video * Both taskId and audioId are required to identify the specific track * Optional author and domainName parameters can be used to add branding ### Developer Notes 1. Generated video files are retained for 15 days 2. Videos include visual effects synchronized with the music 3. This feature is ideal for social media sharing, music promotion, or creating visual content 4. Videos maintain the same audio quality as the original track # Music Video Generation Callbacks Source: https://docs.api.box/suno-api/create-music-video-callbacks When music video generation tasks are completed, the system will send results to your provided callback URL via POST request When you submit a task to the music video generation API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * Music video generation completed * Music video generation task failed * Error occurred during task processing Music video generation has only one callback stage, providing the MP4 video download URL upon completion ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl` in the following format: ```json Video Generation Complete Callback theme={null} { "code": 200, "msg": "MP4 generated successfully.", "data": { "task_id": "taskId_774b9aa0422f", "video_url": "https://example.com/videos/video_847715e66259.mp4" } } ``` ```json Video Generation Failed Callback theme={null} { "code": 400, "msg": "Video generation failed, invalid source audio", "data": { "task_id": "taskId_774b9aa0422f", "video_url": null } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Music video generation completed | | 400 | Bad Request - Invalid source audio or parameter error | | 401 | Unauthorized - Invalid API key | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Task ID, consistent with the taskId returned when you submitted the task Generated MP4 video download URL (returned on success) ## Callback Reception Examples Here are example codes for receiving callbacks in various popular programming languages: ```javascript theme={null} const express = require('express'); const fs = require('fs'); const https = require('https'); const app = express(); app.use(express.json()); app.post('/video-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Received music video callback:', { taskId: data.task_id, status: code, message: msg }); if (code === 200 && data.video_url) { // Video generation successful console.log(`Music video ready: ${data.video_url}`); // Download video file downloadVideoFile(data.video_url, data.task_id); } else { // Task failed console.log('Music video generation failed:', msg); // Handle failure cases... if (code === 400) { console.log('Invalid source audio or parameter error'); } else if (code === 429) { console.log('Insufficient credits'); } else if (code === 500) { console.log('Server internal error'); } } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); function downloadVideoFile(url, taskId) { const filename = `video_${taskId}.mp4`; const file = fs.createWriteStream(filename); https.get(url, (response) => { response.pipe(file); file.on('finish', () => { file.close(); console.log(`Video file downloaded: ${filename}`); }); }).on('error', (err) => { console.error('Video download failed:', err.message); }); } app.listen(3000, () => { console.log('Video callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import requests app = Flask(__name__) @app.route('/video-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) task_id = callback_data.get('task_id') video_url = callback_data.get('video_url') print(f"Received music video callback: {task_id}, Status: {code}") if code == 200 and video_url: # Video generation successful print(f"Music video ready: {video_url}") # Download video file download_video_file(video_url, task_id) else: # Task failed print(f"Music video generation failed: {msg}") # Handle failure cases... if code == 400: print("Invalid source audio or parameter error") elif code == 429: print("Insufficient credits") elif code == 500: print("Server internal error") # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 def download_video_file(url, task_id): """Download video file from the provided URL""" try: response = requests.get(url, stream=True) if response.status_code == 200: filename = f"video_{task_id}.mp4" with open(filename, "wb") as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) print(f"Video file downloaded: {filename}") else: print(f"Failed to download video file: HTTP {response.status_code}") except Exception as e: print(f"Video download failed: {e}") if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```php theme={null} [ 'timeout' => 300 // 5 minutes timeout for large video files ] ]); $videoContent = file_get_contents($url, false, $context); if ($videoContent !== false) { $filename = "video_{$taskId}.mp4"; file_put_contents($filename, $videoContent); error_log("Video file downloaded: $filename"); } else { error_log("Failed to download video file from URL"); } } catch (Exception $e) { error_log("Video download failed: " . $e->getMessage()); } } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### Music Video Callback Configuration 1. **File Size Management**: Prepare for larger file downloads as videos are significantly bigger than audio 2. **Storage Planning**: Ensure adequate storage space for MP4 video files 3. **Download Optimization**: Use streaming downloads for large video files to avoid memory issues 4. **Quality Verification**: Verify video file integrity and playback after download 5. **Metadata Handling**: Maintain video metadata and track association with original audio 6. **Backup Strategy**: Implement backup procedures for generated video content ### Video-Specific Considerations * Video files are much larger than audio files, requiring more storage and bandwidth * Download times can be significantly longer depending on video length and quality * Ensure stable network connectivity for large file transfers * Video generation may take longer than audio processing * Consider implementing progress tracking for video downloads * Video URLs may have shorter expiration times due to storage costs ## Troubleshooting Common issues specific to music video generation callbacks: * Verify adequate storage space for video files * Check network stability for large file downloads * Implement chunked downloading for better reliability * Monitor download progress and implement retry mechanisms * Confirm the source audio quality meets video generation requirements * Verify that the generated MP4 plays correctly in different players * Check video resolution and quality settings * Test video compatibility across different devices and platforms * Implement asynchronous video processing to avoid blocking * Consider background downloading for large video files * Monitor server resources during video processing * Plan for longer processing and download times compared to audio * Ensure source audio meets minimum quality requirements * Verify that the audio ID and task ID are valid and accessible * Check if the source audio has sufficient content for video generation * Confirm that audio metadata is properly preserved in the video ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Music Video Details interface to regularly query video generation task status. Recommend querying every 45 seconds due to longer processing times. # Extend Music Source: https://docs.api.box/suno-api/extend-music suno-api/suno-api.json POST /api/v1/generate/extend Extend or modify existing music tracks. ### Model Versions * **Current models**: `V6` (default), `V6_WILD`, `V6_MINI` * **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4` * Deprecated values remain available only for backward compatibility. New integrations should use a V6-series model. ### Parameter Usage Guide * This endpoint always uses custom parameters. Simple mode is not available. * Source audio (`audioId`) is enough to generate. `lyrics`, `prompt`, `style`, and `title` are optional. * **model** (string, required): `V6`, `V6_WILD`, `V6_MINI`. Deprecated: `V4_5ALL`, `V4`, `V4_5`, `V4_5PLUS`, `V5`, `V5_5`. * `instrumental` (boolean, optional) determines whether to extend the track as instrumental music and defaults to `false`. * If `instrumental` is `false` or omitted: use `lyrics` as the lyrics when provided; otherwise use `prompt`. Both are optional. * If `instrumental` is `true`: do not provide `prompt`, `lyrics`, or `vocalGender` * `prompt` is optional and is treated as lyrics. When `lyrics` is also provided, `lyrics` takes priority and `prompt` is not used as lyrics. * `lyrics` is optional. It takes priority over `prompt` as the lyrics. If `lyrics` is omitted, `prompt` is used as the lyrics. * `continueAt`: the time point in seconds from which to start extending (must be greater than 0 and less than the source audio duration). Required. * `taskId` is optional and can be provided to identify the original generation task * Character limits by model: * **V4 (Deprecated)**: `prompt` max 3000, `style` max 200, `title` max 80 * **V4\_5ALL (Deprecated)**: `prompt` max 5000, `style` max 1000, `title` max 80 * **V4\_5, V4\_5PLUS, V5, V5\_5 (Deprecated)**: `prompt` max 5000, `style` max 1000, `title` max 100 * **V6, V6\_WILD & V6\_MINI**: `prompt` and `lyrics` max 5000, `style` max 1000, `title` max 100 ### Optional parameters The following fields are optional controls available for this endpoint: * lyrics (string): Lyrics for the extension. Optional. Takes priority over `prompt`. If omitted, `prompt` is used as the lyrics. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters. * taskId (string): Unique identifier of the original music generation task that produced the source audio. Can be a taskId returned from Generate Music or a previous Extend Music request. * instrumental (boolean): Whether to extend the track as instrumental music. Defaults to `false`. When `true`, `prompt`, `lyrics`, and `vocalGender` must not be provided. * vocalGender (string): Preferred vocal gender. Allowed values: `m` (male), `f` (female). Must not be provided when `instrumental` is `true`. * styleWeight (number): Style adherence weight in range 0–1 (recommended two decimals) * weirdnessConstraint (number): Creativity/novelty constraint in range 0–1 (recommended two decimals) * audioWeight (number): Relative weight of audio consistency in range 0–1 (recommended two decimals) * variety (integer): Diversity of generated results. Integer from 0–4, default 1. `0` off, `1` normal (default), `2` high, `3` extra, `4` max. * personaId (string): Persona ID or Suno Voice `voiceId` to apply to the generated music. If you use a Voice-generated ID, set `personaModel` to `voice_persona`. * personaModel (string): Persona type. Use `style_persona` for Generate Persona IDs, or `voice_persona` for Suno Voice IDs. ```json JSON body theme={null} { "instrumental": false, "audioId": "e231****-****-****-****-****8cadc7dc", "taskId": "5c79****be8e", "lyrics": "[Chorus] Brighter lights, we keep going on", "prompt": "[Verse] City hums under neon rain", "style": "Indie Pop", "title": "Evening Sky (Extended)", "continueAt": 60, "model": "V6", "callBackUrl": "https://example.com/callback", "vocalGender": "m", "styleWeight": 0.61, "weirdnessConstraint": 0.72, "audioWeight": 0.65, "variety": 1 } ``` ### Developer Notes 1. Generated files are retained for 15 days 2. Model version must be consistent with the source music 3. This feature is ideal for creating longer compositions by extending existing tracks # Music Extension Callbacks Source: https://docs.api.box/suno-api/extend-music-callbacks When music extension tasks are completed, the system will send results to your provided callback URL via POST request When you submit a task to the music extension API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * Text generation completed (`text` stage) * First extended music track generated (`first` stage) * All extended music tracks generated (`complete` stage) * Music extension task failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl` in the following format: ```json Text Generation Complete Callback theme={null} { "code": 200, "msg": "Text generation completed successfully.", "data": { "callbackType": "text", "task_id": "2fac****9f72", "data": [] } } ``` ```json First Track Complete Callback theme={null} { "code": 200, "msg": "First track generated successfully.", "data": { "callbackType": "first", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Night city lights shining bright", "model_name": "chirp-v3-5", "title": "Iron Man Extended", "tags": "electrifying, rock", "createTime": "2025-01-01 00:00:00", "duration": 278.44 } ] } } ``` ```json All Tracks Complete Callback theme={null} { "code": 200, "msg": "All generated successfully.", "data": { "callbackType": "complete", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Night city lights shining bright", "model_name": "chirp-v3-5", "title": "Iron Man Extended", "tags": "electrifying, rock", "createTime": "2025-01-01 00:00:00", "duration": 278.44 } ] } } ``` ```json Failed Callback theme={null} { "code": 400, "msg": "Failed to extend music, invalid audio source", "data": { "callbackType": "failed", "task_id": "2fac****9f72", "data": [] } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Music extension completed | | 400 | Bad Request - Invalid source audio or parameter error | | 401 | Unauthorized - Invalid API key | | 413 | Content Too Long - Prompt or style description exceeds limit | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Callback type indicating the current callback stage: * `text`: Text generation completed * `first`: First extended music track generated * `complete`: All extended music tracks generated * `failed`: Task failed Task ID, consistent with the taskId returned when you submitted the task Music extension result information, returned on success Audio unique identifier (audioId) Extended audio file download link **Deprecated.** Original audio file link returned by Suno. This link expires after a period of time and is no longer maintained — do not rely on it for long-term storage. Use the [Recovery Audio](/suno-api/recovery-audio) endpoint to obtain a fresh playable link. Streaming audio playback link Music cover image link Extension prompt used AI model name used for extension Extended music title Music style tags Creation time Extended audio duration (seconds) ## Callback Reception Examples Here are example codes for receiving callbacks in various popular programming languages: ```javascript theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/extend-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Received music extension callback:', { taskId: data.task_id, callbackType: data.callbackType, status: code, message: msg }); if (code === 200) { // Task successful const { callbackType, data: musicData } = data; switch (callbackType) { case 'text': console.log('Text generation completed'); break; case 'first': console.log('First extended music track generated'); if (musicData.length > 0) { console.log(`Extended music title: ${musicData[0].title}`); console.log(`Audio link: ${musicData[0].audio_url}`); console.log(`Duration: ${musicData[0].duration} seconds`); } break; case 'complete': console.log('All extended music tracks generated'); console.log(`Total ${musicData.length} extended tracks:`); musicData.forEach((track, index) => { console.log(`Track ${index + 1}: ${track.title} - ${track.audio_url}`); }); // Process extended music // Can download music, save locally, etc. break; } } else { // Task failed console.log('Music extension failed:', msg); // Handle failure cases... if (code === 400) { console.log('Invalid source audio or parameter error'); } else if (code === 429) { console.log('Insufficient credits'); } else if (code === 500) { console.log('Server internal error'); } } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); app.listen(3000, () => { console.log('Extension callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import requests app = Flask(__name__) @app.route('/extend-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) task_id = callback_data.get('task_id') callback_type = callback_data.get('callbackType') music_data = callback_data.get('data', []) print(f"Received music extension callback: {task_id}, Type: {callback_type}, Status: {code}") if code == 200: # Task successful if callback_type == 'text': print("Text generation completed") elif callback_type == 'first': print("First extended music track generated") if music_data: track = music_data[0] print(f"Extended music title: {track.get('title')}") print(f"Audio link: {track.get('audio_url')}") print(f"Duration: {track.get('duration')} seconds") elif callback_type == 'complete': print("All extended music tracks generated") print(f"Total {len(music_data)} extended tracks:") for i, track in enumerate(music_data): print(f"Track {i + 1}: {track.get('title')} - {track.get('audio_url')}") # Download extended music example try: audio_url = track.get('audio_url') if audio_url: response = requests.get(audio_url) if response.status_code == 200: filename = f"extended_music_{task_id}_{i + 1}.mp3" with open(filename, "wb") as f: f.write(response.content) print(f"Extended music saved as {filename}") except Exception as e: print(f"Music download failed: {e}") else: # Task failed print(f"Music extension failed: {msg}") # Handle failure cases... if code == 400: print("Invalid source audio or parameter error") elif code == 429: print("Insufficient credits") elif code == 500: print("Server internal error") # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```php theme={null} $track) { $title = $track['title'] ?? ''; $audioUrl = $track['audio_url'] ?? ''; error_log("Track " . ($index + 1) . ": $title - $audioUrl"); // Download extended music example try { if ($audioUrl) { $audioContent = file_get_contents($audioUrl); if ($audioContent !== false) { $filename = "extended_music_{$taskId}_" . ($index + 1) . ".mp3"; file_put_contents($filename, $audioContent); error_log("Extended music saved as $filename"); } } } catch (Exception $e) { error_log("Music download failed: " . $e->getMessage()); } } break; } } else { // Task failed error_log("Music extension failed: $msg"); // Handle failure cases... if ($code === 400) { error_log("Invalid source audio or parameter error"); } elseif ($code === 429) { error_log("Insufficient credits"); } elseif ($code === 500) { error_log("Server internal error"); } } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### Music Extension Callback Configuration 1. **Source Validation**: Verify that the original audio source is valid before processing extension callbacks 2. **Duration Tracking**: Monitor the extended duration to ensure it meets your requirements 3. **Quality Check**: Implement quality checks for the extended audio segments 4. **Version Control**: Keep track of extension iterations and maintain version history 5. **Fallback Handling**: Implement fallback mechanisms if extension fails 6. **Seamless Integration**: Ensure the extended portion integrates smoothly with the original track ### Extension-Specific Considerations * Extension tasks require a valid source audio file * The `continueAt` parameter determines where the extension begins * Extended tracks maintain the style and characteristics of the original * Extension quality depends on the source audio quality * Some complex musical structures may be challenging to extend seamlessly ## Troubleshooting Common issues specific to music extension callbacks: * Verify the source audio quality and format * Check if the `continueAt` parameter is set to an appropriate time point * Ensure the extension prompt matches the original music style * Consider the musical complexity of the source material * Confirm the source audio ID is valid and accessible * Verify the original audio file is not corrupted * Check if the source audio meets minimum quality requirements * Ensure the original track has sufficient content for extension * Verify the `continueAt` timestamp is within the valid range * Check for audio synchronization issues in the extended portion * Monitor for tempo or key changes that might affect extension quality ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Music Generation Details interface to regularly query extension task status. Recommend querying every 30 seconds. # Generate Lyrics Source: https://docs.api.box/suno-api/generate-lyrics suno-api/suno-api.json POST /api/v1/lyrics Create lyrics for music using AI models without generating audio tracks. ### Usage Guide * This endpoint generates only lyrics content based on your prompt * Multiple lyrics variations will be returned for you to choose from * Generated lyrics typically include song structure markers (e.g., \[Verse], \[Chorus]) ### Developer Notes 1. Generated lyrics are retained for 15 days 2. Callback has only one stage: complete (generation complete) 3. Use this endpoint when you only need lyrics creation without music 4. Results can be used as input for the Generate Music endpoint in custom mode # Lyrics Generation Callbacks Source: https://docs.api.box/suno-api/generate-lyrics-callbacks When lyrics generation tasks are completed, the system will send results to your provided callback URL via POST request When you submit a task to the lyrics generation API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * Lyrics generation completed (`complete` stage) * Lyrics generation task failed * Error occurred during task processing Unlike music generation, lyrics generation has only one callback stage: `complete` (generation finished) ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl` in the following format: ```json Lyrics Generation Complete Callback theme={null} { "code": 200, "msg": "All generated successfully.", "data": { "callbackType": "complete", "taskId": "11dc****8b0f", "data": [ { "text": "[Verse]\nI cross the city's darkest night\nWith burning dreams inside my heart", "title": "Iron Man", "status": "complete", "errorMessage": "" }, { "text": "[Verse]\nThe wind is calling out my name\nSteel armor gleaming in the light", "title": "Iron Man", "status": "complete", "errorMessage": "" } ] } } ``` ```json Lyrics Generation Failed Callback theme={null} { "code": 400, "msg": "Failed to generate lyrics, containing sensitive content", "data": { "callbackType": "failed", "taskId": "11dc****8b0f", "data": null } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Lyrics generation completed | | 400 | Bad Request - Parameter error or content violation | | 401 | Unauthorized - Invalid API key | | 413 | Content Too Long - Prompt exceeds limit | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Callback type, fixed as `complete` for lyrics generation Task ID, consistent with the taskId returned when you submitted the task Generated lyrics list Lyrics content with verse/chorus structure Lyrics title Generation status: `complete` or `failed` Error message, valid when status is `failed` ## Callback Reception Examples Here are example codes for receiving callbacks in various popular programming languages: ```javascript theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/lyrics-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Received lyrics generation callback:', { taskId: data.taskId, callbackType: data.callbackType, status: code, message: msg }); if (code === 200 && data.callbackType === 'complete') { // Lyrics generation successful console.log(`Generated ${data.data.length} lyrics variants:`); data.data.forEach((lyrics, index) => { if (lyrics.status === 'complete') { console.log(`\nLyrics ${index + 1}:`); console.log(`Title: ${lyrics.title}`); console.log(`Content:\n${lyrics.text}`); // Process lyrics data // Can save to database, format for display, etc. saveLyricsToDatabase(lyrics); } else { console.log(`Lyrics ${index + 1} failed: ${lyrics.errorMessage}`); } }); } else { // Task failed console.log('Lyrics generation failed:', msg); // Handle failure cases... if (code === 400) { console.log('Parameter error or content violation'); } else if (code === 429) { console.log('Insufficient credits'); } else if (code === 500) { console.log('Server internal error'); } } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); function saveLyricsToDatabase(lyrics) { // Example function to save lyrics to database console.log(`Saving lyrics: ${lyrics.title}`); // Your database logic here } app.listen(3000, () => { console.log('Lyrics callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import json app = Flask(__name__) @app.route('/lyrics-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) task_id = callback_data.get('taskId') callback_type = callback_data.get('callbackType') lyrics_data = callback_data.get('data', []) print(f"Received lyrics generation callback: {task_id}, Type: {callback_type}, Status: {code}") if code == 200 and callback_type == 'complete': # Lyrics generation successful print(f"Generated {len(lyrics_data)} lyrics variants:") for i, lyrics in enumerate(lyrics_data): if lyrics.get('status') == 'complete': print(f"\nLyrics {i + 1}:") print(f"Title: {lyrics.get('title')}") print(f"Content:\n{lyrics.get('text')}") # Process lyrics data # Can save to file, database, etc. save_lyrics_to_file(lyrics, task_id, i + 1) else: print(f"Lyrics {i + 1} failed: {lyrics.get('errorMessage')}") else: # Task failed print(f"Lyrics generation failed: {msg}") # Handle failure cases... if code == 400: print("Parameter error or content violation") elif code == 429: print("Insufficient credits") elif code == 500: print("Server internal error") # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 def save_lyrics_to_file(lyrics, task_id, index): """Save lyrics to a text file""" try: filename = f"lyrics_{task_id}_{index}.txt" with open(filename, "w", encoding="utf-8") as f: f.write(f"Title: {lyrics.get('title')}\n\n") f.write(lyrics.get('text')) print(f"Lyrics saved as {filename}") except Exception as e: print(f"Failed to save lyrics: {e}") if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```php theme={null} $lyrics) { if (($lyrics['status'] ?? '') === 'complete') { $title = $lyrics['title'] ?? ''; $text = $lyrics['text'] ?? ''; error_log("Lyrics " . ($index + 1) . ":"); error_log("Title: $title"); error_log("Content: $text"); // Process lyrics data // Can save to file, database, etc. saveLyricsToFile($lyrics, $taskId, $index + 1); } else { $errorMsg = $lyrics['errorMessage'] ?? ''; error_log("Lyrics " . ($index + 1) . " failed: $errorMsg"); } } } else { // Task failed error_log("Lyrics generation failed: $msg"); // Handle failure cases... if ($code === 400) { error_log("Parameter error or content violation"); } elseif ($code === 429) { error_log("Insufficient credits"); } elseif ($code === 500) { error_log("Server internal error"); } } function saveLyricsToFile($lyrics, $taskId, $index) { try { $title = $lyrics['title'] ?? ''; $text = $lyrics['text'] ?? ''; $filename = "lyrics_{$taskId}_{$index}.txt"; $content = "Title: $title\n\n$text"; file_put_contents($filename, $content); error_log("Lyrics saved as $filename"); } catch (Exception $e) { error_log("Failed to save lyrics: " . $e->getMessage()); } } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### Lyrics Processing Recommendations 1. **Content Filtering**: Implement content filtering to ensure lyrics meet your platform's guidelines 2. **Format Preservation**: Maintain the verse/chorus structure when processing lyrics 3. **Version Management**: Keep track of different lyrics variants for the same prompt 4. **Metadata Storage**: Store lyrics along with relevant metadata (title, theme, style) 5. **Text Processing**: Consider text processing for formatting, spell checking, or translation 6. **Copyright Compliance**: Ensure generated lyrics comply with copyright regulations ### Lyrics-Specific Considerations * Lyrics may contain creative variations that require human review * Generated content should be checked for appropriateness before publication * Multiple variants allow for selection of the best option * Lyrics generation is typically faster than music generation * Content moderation is important for user-generated lyrics prompts ## Troubleshooting Common issues specific to lyrics generation callbacks: * Review the prompt for clarity and specificity * Check if the generated lyrics match the intended theme * Verify that lyrics follow a logical song structure * Consider regenerating if quality doesn't meet expectations * Ensure the prompt clearly specifies the desired language * Check for style consistency across verses and choruses * Verify that the tone matches the intended mood * Consider more specific prompts for better style control * Implement content filtering for generated lyrics * Check for potentially inappropriate content * Verify compliance with platform guidelines * Consider human review for sensitive topics ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Lyrics Generation Details interface to regularly query task status. Recommend querying every 15 seconds for lyrics. # Generate Mashup Source: https://docs.api.box/suno-api/generate-mashup suno-api/suno-api.json POST /api/v1/generate/mashup Mix two audio files to generate a new mashup work using AI models. ### Model Versions * **Current models**: `V6` (default), `V6_WILD`, `V6_MINI` * **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4` * Deprecated values remain available only for backward compatibility. New integrations should use a V6-series model. ### Usage Guide * This endpoint always uses custom parameters. Simple mode is not available. * This endpoint creates mashup music from 2 uploaded audio files * Combines elements from multiple tracks into a cohesive new composition ### Parameter Details * `uploadUrlList` is required and must contain exactly 2 audio file URLs; only the first 2 are used * **model** (string, required): `V6`, `V6_WILD`, `V6_MINI`. Deprecated: `V4`, `V4_5`, `V4_5PLUS`, `V4_5ALL`, `V5`, `V5_5`. * `style` and `title` are required * `prompt` is optional and is treated as lyrics. When `lyrics` is also provided, `lyrics` takes priority and `prompt` is not used as lyrics * `lyrics` is optional. It takes priority over `prompt` as the lyrics. If `lyrics` is omitted, `prompt` is used as the lyrics * **Character limits (based on model):** * **V4, V4\_5, V4\_5PLUS, V4\_5ALL, V5 & V5\_5 (Deprecated)**: `prompt` 3000–5000 characters and `style` 200–1000 characters according to the legacy model. * **V6, V6\_WILD & V6\_MINI**: `prompt` and `lyrics` max 5000 characters, `style` max 1000 characters * `title` length limit: 80 characters (all models) ### Optional parameters The following fields are optional controls available for this endpoint: * lyrics (string): Lyrics for the mashup. Takes priority over `prompt`. If omitted, `prompt` is used as the lyrics. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters. * vocalGender (string): Preferred vocal gender. Allowed values: `m` (male), `f` (female) * styleWeight (number): Style adherence weight in range 0–1 (recommended two decimals) * weirdnessConstraint (number): Creativity/novelty constraint in range 0–1 (recommended two decimals) * audioWeight (number): Relative weight of audio consistency in range 0–1 (recommended two decimals) * duration (number): Duration in seconds, range 10–360. Only effective with `V5_5` (Deprecated), `V6`, `V6_WILD`, or `V6_MINI`. * variety (integer): Diversity of generated results. Integer from 0–4, default 1. `0` off, `1` normal (default), `2` high, `3` extra, `4` max. * personaId (string): Persona ID or Suno Voice `voiceId` to apply to the generated music. If you use a Voice-generated ID, set `personaModel` to `voice_persona`. * personaModel (string): Persona type, default `style_persona`. Use `style_persona` for Generate Persona IDs, or `voice_persona` for Suno Voice IDs. ```json JSON body theme={null} { "uploadUrlList": [ "https://example.com/audio1.mp3", "https://example.com/audio2.mp3" ], "lyrics": "[Chorus] Brighter lights, we keep going on", "prompt": "[Verse] City hums under neon rain", "style": "Electronic Dance Music", "title": "Mashup Work", "model": "V6", "callBackUrl": "https://example.com/callback", "vocalGender": "m", "styleWeight": 0.65, "weirdnessConstraint": 0.72, "audioWeight": 0.65, "variety": 1 } ``` ### Developer Notes * This endpoint always uses custom parameters; `style` and `title` must be provided along with the two source audio URLs * Generated files are retained for 14 days * Callback process has three stages: `text` (text generation), `first` (first track complete), `complete` (all tracks complete) * The two audio files in `uploadUrlList` must be valid and accessible URLs * Audio files should be in supported formats (MP3, WAV, etc.) # Generate MIDI from Audio Source: https://docs.api.box/suno-api/generate-midi suno-api/suno-api.json POST /api/v1/midi/generate Convert separated audio tracks into MIDI format with detailed note information for each instrument. ### Usage Guide * Convert separated audio tracks into structured MIDI data containing pitch, timing, and velocity information * Requires a completed vocal separation task ID (from the Vocal Removal API) * Generates MIDI note data for multiple detected instruments including drums, bass, guitar, keyboards, and more * Ideal for music transcription, notation, remixing, or educational analysis * Best results on clean, well-separated audio tracks with clear instrument parts ### Prerequisites You must first use the [Vocal & Instrument Stem Separation](/suno-api/separate-vocals-from-music) API to separate your audio before generating MIDI. ### Parameter Reference | Name | Type | Description | | :- | :- | :- | | `taskId` | string | **Required.** Task ID from a completed vocal separation | | `callBackUrl` | string | **Required.** URL to receive MIDI generation completion notifications | | `audioId` | string | **Optional.** Specifies which separated audio track to generate MIDI from. This audioId can be obtained from the `originData` array in the [Get Vocal Separation Details](/suno-api/get-vocal-separation-details) endpoint response. Each item in `originData` contains an `id` field that can be used here. If not provided, MIDI will be generated from all separated tracks. | ### Developer Notes * The callback will contain detailed note data for each detected instrument * Each note includes: `pitch` (MIDI note number), `start` (seconds), `end` (seconds), `velocity` (0-1) * Not all instruments may be detected - depends on audio content * **Billing:** Check current per-call credit costs at [**https://api.box/billing**](https://api.box/billing) # MIDI Generation Callbacks Source: https://docs.api.box/suno-api/generate-midi-callbacks System will call this callback when MIDI generation from separated audio is complete. When you submit a MIDI generation task to the Suno API, you can use the `callBackUrl` parameter to set a callback URL. The system will automatically push the results to your specified address when the task is completed. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * MIDI generation task completed successfully * MIDI generation task failed * Errors occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout Setting**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl`: ```json Success Callback theme={null} { "task_id": "5c79****be8e", "code": 200, "msg": "success", "data": { "state": "complete", "instruments": [ { "name": "Drums", "notes": [ { "pitch": 73, "start": "0.036458333333333336", "end": "0.18229166666666666", "velocity": 1 }, { "pitch": 61, "start": 0.046875, "end": "0.19270833333333334", "velocity": 1 }, { "pitch": 73, "start": 0.1875, "end": "0.4895833333333333", "velocity": 1 } ] }, { "name": "Electric Bass (finger)", "notes": [ { "pitch": 44, "start": 7.6875, "end": "7.911458333333333", "velocity": 1 }, { "pitch": 56, "start": 7.6875, "end": "7.911458333333333", "velocity": 1 }, { "pitch": 51, "start": 7.6875, "end": "7.911458333333333", "velocity": 1 } ] } ] } } ``` ```json Failure Callback theme={null} { "task_id": "5c79****be8e", "code": 500, "msg": "MIDI generation failed", "data": null } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - MIDI generation completed successfully | | 500 | Internal Error - Please try again or contact support | Status message providing detailed status description Task ID, consistent with the task\_id returned when you submitted the task MIDI generation result information, returned on success ## Success Response Fields Processing state. Value: `complete` when successful Array of detected instruments with their MIDI note data Instrument name (e.g., "Drums", "Electric Bass (finger)", "Acoustic Grand Piano") Array of MIDI notes for this instrument MIDI note number (0-127). Middle C = 60. [MIDI note reference](https://inspiredacoustics.com/en/MIDI_note_numbers_and_center_frequencies) Note start time in seconds from beginning of audio Note end time in seconds from beginning of audio Note velocity/intensity (0-1 range). 1 = maximum velocity ## Callback Reception Examples Below are example codes for receiving callbacks in popular programming languages: ```javascript theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/suno-midi-callback', (req, res) => { const { code, msg, task_id, data } = req.body; console.log('Received MIDI generation callback:', { taskId: task_id, status: code, message: msg }); if (code === 200) { // Task completed successfully console.log('MIDI generation completed'); if (data && data.instruments) { console.log(`Detected ${data.instruments.length} instruments`); data.instruments.forEach(instrument => { console.log(`\nInstrument: ${instrument.name}`); console.log(` Note count: ${instrument.notes.length}`); // Process each note instrument.notes.forEach((note, idx) => { if (idx < 3) { // Show first 3 notes as example console.log(` Note ${idx + 1}: Pitch ${note.pitch}, ` + `Start ${note.start}s, End ${note.end}s, ` + `Velocity ${note.velocity}`); } }); }); // Save MIDI data to database or file // processMidiData(task_id, data); } } else { // Task failed console.log('MIDI generation failed:', msg); // Handle failure scenarios... } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); app.listen(3000, () => { console.log('Callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import json app = Flask(__name__) @app.route('/suno-midi-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') task_id = data.get('task_id') callback_data = data.get('data', {}) print(f"Received MIDI generation callback: {task_id}, status: {code}, message: {msg}") if code == 200: # Task completed successfully print("MIDI generation completed") if callback_data and 'instruments' in callback_data: instruments = callback_data['instruments'] print(f"Detected {len(instruments)} instruments") for instrument in instruments: name = instrument.get('name') notes = instrument.get('notes', []) print(f"\nInstrument: {name}") print(f" Note count: {len(notes)}") # Process each note for idx, note in enumerate(notes[:3]): # Show first 3 notes print(f" Note {idx + 1}: Pitch {note['pitch']}, " f"Start {note['start']}s, End {note['end']}s, " f"Velocity {note['velocity']}") # Save MIDI data to file with open(f"midi_{task_id}.json", "w") as f: json.dump(callback_data, f, indent=2) print(f"MIDI data saved to midi_{task_id}.json") else: # Task failed print(f"MIDI generation failed: {msg}") # Handle failure scenarios... # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```php theme={null} $note) { error_log(sprintf( " Note %d: Pitch %d, Start %ss, End %ss, Velocity %s", $idx + 1, $note['pitch'], $note['start'], $note['end'], $note['velocity'] )); } } // Save MIDI data to file $filename = "midi_$taskId.json"; file_put_contents($filename, json_encode($callbackData, JSON_PRETTY_PRINT)); error_log("MIDI data saved to $filename"); } } else { // Task failed error_log("MIDI generation failed: $msg"); // Handle failure scenarios... } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### Callback URL Configuration Recommendations 1. **Use HTTPS**: Ensure callback URL uses HTTPS protocol for secure data transmission 2. **Verify Origin**: Verify the legitimacy of the request source in callback processing 3. **Idempotent Processing**: The same task\_id may receive multiple callbacks, ensure processing logic is idempotent 4. **Quick Response**: Callback processing should return 200 status code quickly to avoid timeout 5. **Asynchronous Processing**: Complex business logic (like MIDI file conversion) should be processed asynchronously 6. **Handle Missing Instruments**: Not all instruments may be detected - handle empty or missing instrument arrays gracefully 7. **Store Raw Data**: Save the complete JSON response for future reference and reprocessing ### Important Reminders * Callback URL must be publicly accessible * Server must respond within 15 seconds, otherwise will be considered timeout * If 3 consecutive retry attempts fail, the system will stop sending callbacks * Please ensure the stability of callback processing logic to avoid callback failures due to exceptions * MIDI data is retained for 14 days - download and save promptly if needed long-term * The number and types of instruments detected depends on audio content * Note times (start/end) may be strings or numbers - handle both types ## Troubleshooting If you are not receiving callback notifications, please check the following: * Confirm callback URL is accessible from public internet * Check firewall settings to ensure inbound requests are not blocked * Verify domain name resolution is correct * Ensure server returns HTTP 200 status code within 15 seconds * Check server logs for error messages * Verify endpoint path and HTTP method are correct * Confirm received POST request body is in JSON format * Check if Content-Type is application/json * Verify JSON parsing is correct * Handle both string and number types for timing values * Some instruments may have empty note arrays * Not all audio will detect all instrument types * Verify the original vocal separation used `split_stem` type (not `separate_vocal`) * Check that the source taskId is from a successfully completed separation ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get MIDI Generation Details endpoint to periodically query task status. We recommend querying every 10-30 seconds. # Generate Music Source: https://docs.api.box/suno-api/generate-music suno-api/suno-api.json POST /api/v1/generate Generate music with or without lyrics using AI models. ### Model Versions * **Current models**: `V6` (default), `V6_WILD`, `V6_MINI` * **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4` * Deprecated values remain available only for backward compatibility. New integrations should use a V6-series model. ### Usage Guide * This endpoint creates music based on your text prompt * Multiple variations will be generated for each request * You can control detail level with custom mode and instrumental settings ### Parameter Details * Always required: `customMode`, `instrumental`, `model` * In Custom Mode (`customMode: true`): * `title` is optional, maximum 80 characters. Only available in this mode * `prompt` is optional; when provided, it is used strictly as lyrics and sung in the generated track. If `lyrics` is also provided, `lyrics` takes priority * At least one of `style`, `lyrics`, or `negativeTags` must be provided; generation is rejected if all are empty * If `instrumental: true`: generate instrumental music (no vocals) * If `instrumental: false`: use `lyrics` as lyrics (fall back to `prompt` if `lyrics` is not provided) * Optional: `duration`, `negativeTags`, `vocalGender`, `styleWeight`, `weirdnessConstraint`, `audioWeight`, `variety`, `personaId`, `personaModel` * Character limits by model: * **V4 (Deprecated)**: `prompt` 3000 characters, `style` 200 characters * **V4\_5, V4\_5PLUS, V4\_5ALL, V5, V5\_5 (Deprecated)**: `prompt` 5000 characters, `style` 1000 characters * **V6, V6\_MINI, V6\_WILD**: `style` 1000 characters; `lyrics` 5000 characters; `negativeTags` 1000 characters * `title` length limit: 80 characters (all models) * In Non-custom Mode (`customMode: false`): * `prompt` is optional; it serves as the core idea, and lyrics are generated automatically (not a strict match), maximum 3000 characters * `lyrics` can be used as a lyrics attachment together with `prompt` * At least one of `imageUrls`, `videoUrls`, `audioUrls`, `style`, or `lyrics` must be provided; generation is rejected if all are empty * `imageUrls`, `videoUrls`, and `audioUrls` are only valid in this mode * Do not pass parameters that are only available in custom mode: `title`, `negativeTags`, `duration`, `vocalGender`, `styleWeight`, `weirdnessConstraint`, `audioWeight`, `variety`, `personaId`, `personaModel` * Total attachments must not exceed 10: `style` + `lyrics` + `imageUrls` + `videoUrls` + `audioUrls` ### Optional Parameters The following fields are optional controls available for this endpoint: * prompt (string): Description of the desired audio content. Optional. Used as lyrics in custom mode; used as the core idea in non-custom mode (maximum 3000 characters). * lyrics (string): Lyrics content. Optional. V6 series maximum 5000 characters. In custom mode, takes priority over `prompt` as lyrics; in non-custom mode, can be used as a lyrics attachment together with `prompt`. * imageUrls (array): Image references. Only effective when `customMode` is `false`. Up to 5 images, each no more than 10 MB. Supported formats: jpeg, png, webp, bmp. * videoUrls (array): Video references. Only effective when `customMode` is `false`. Up to 1 file, each no more than 100 MB, duration no more than 241 seconds. Supported formats: mp4, mov, webm. * audioUrls (array): Audio references. Only effective when `customMode` is `false`. Duration must be between 6 seconds and 30 minutes; each file no more than 500 MB. * style (string): Music style specification. See character limits in Parameter Details above. * title (string): Track title. Optional. Only available when `customMode` is `true`. Maximum 80 characters. Displayed in player interfaces and filenames. * negativeTags (string): Music styles or traits to exclude from the generated audio. Only available when `customMode` is `true`. For V6, V6\_MINI, and V6\_WILD: maximum 1000 characters. * vocalGender (string): Vocal gender preference. `m` for male, `f` for female. Only available when `customMode` is `true`. In practice, this only increases probability and cannot guarantee the instruction is followed. * styleWeight (number): Strength of adherence to the specified style. Range 0–1, up to 2 decimal places. Only effective when `customMode` is `true`. * weirdnessConstraint (number): Creative/experimental deviation. Range 0–1, up to 2 decimal places. Only effective when `customMode` is `true`. * audioWeight (number): Relative weight of audio features. Range 0–1, up to 2 decimal places. Only effective when `customMode` is `true`. Not supported when there are no vocals. * variety (integer): Diversity of generated results. Integer from 0–4, default 1. Only effective when `customMode` is `true`. `0` off (exact style), `1` normal (default, balanced), `2` high (distinct styles), `3` extra (bold exploration), `4` max (maximum variation). * personaId (string): Persona ID or Voice ID. Optional. Only available when `customMode` is `true`. To generate a Persona ID, see [Generate Persona](/suno-api/generate-persona). * personaModel (string): Persona model, `style_persona` or `voice_persona`. Only available when `customMode` is `true`. Only available for `V5` (Discontinued), `V5_5` (Discontinued), `V6`, `V6_MINI`, and `V6_WILD`. * duration (number): Audio duration in seconds. Range 10–360, default 20. Only available when `customMode` is `true`, and only valid when the model is `V5_5`, `V6`, `V6_MINI`, or `V6_WILD`. ```json Non-custom mode theme={null} { "customMode": false, "instrumental": false, "prompt": "A chill lo-fi beat with soft vocals", "lyrics": "[Verse] Night city lights shining bright", "style": "lo-fi, chill", "imageUrls": [ "https://example.com/reference-image.png" ], "videoUrls": [ "https://example.com/reference-video.mp4" ], "audioUrls": [ "https://example.com/reference-audio.mp3" ], "model": "V6", "callBackUrl": "https://example.com/callback" } ``` ```json Custom mode theme={null} { "customMode": true, "instrumental": false, "title": "Peaceful Piano Meditation", "style": "Classical", "lyrics": "[Verse] Night city lights shining bright", "prompt": "A calm and relaxing piano track with soft melodies", "negativeTags": "Heavy Metal, Upbeat Drums", "vocalGender": "m", "styleWeight": 0.65, "weirdnessConstraint": 0.65, "audioWeight": 0.65, "variety": 1, "duration": 20, "model": "V6", "callBackUrl": "https://example.com/callback" } ``` ### Developer Notes * Recommendation for new users: Start with `customMode: false` for simpler usage * Generated files are retained for 14 days * Callback process has three stages: `text` (text generation), `first` (first track complete), `complete` (all tracks complete) # Music Generation Callbacks Source: https://docs.api.box/suno-api/generate-music-callbacks When music generation tasks are completed, the system will send results to your provided callback URL via POST request When you submit a task to the music generation API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * Text generation completed (`text` stage) * First music track generated (`first` stage) * All music tracks generated (`complete` stage) * Music generation task failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl` in the following format: ```json Text Generation Complete Callback theme={null} { "code": 200, "msg": "Text generation completed successfully.", "data": { "callbackType": "text", "task_id": "2fac****9f72", "data": [] } } ``` ```json First Track Complete Callback theme={null} { "code": 200, "msg": "First track generated successfully.", "data": { "callbackType": "first", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Night city lights shining bright", "model_name": "chirp-v3-5", "title": "Iron Man", "tags": "electrifying, rock", "createTime": "2025-01-01 00:00:00", "duration": 198.44 } ] } } ``` ```json All Tracks Complete Callback theme={null} { "code": 200, "msg": "All generated successfully.", "data": { "callbackType": "complete", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Night city lights shining bright", "model_name": "chirp-v3-5", "title": "Iron Man", "tags": "electrifying, rock", "createTime": "2025-01-01 00:00:00", "duration": 198.44 }, { "id": "bd15****1873", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Night city lights shining bright", "model_name": "chirp-v3-5", "title": "Iron Man", "tags": "electrifying, rock", "createTime": "2025-01-01 00:00:00", "duration": 228.28 } ] } } ``` ```json Failed Callback theme={null} { "code": 400, "msg": "Failed to generate music, containing sensitive content", "data": { "callbackType": "failed", "task_id": "2fac****9f72", "data": [] } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Music generation completed | | 400 | Bad Request - Parameter error or content violation | | 401 | Unauthorized - Invalid API key | | 413 | Content Too Long - Prompt or style description exceeds limit | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Callback type indicating the current callback stage: * `text`: Text generation completed * `first`: First music track generated * `complete`: All music tracks generated * `failed`: Task failed Task ID, consistent with the taskId returned when you submitted the task Music generation result information, returned on success Audio unique identifier (audioId) Audio file download link **Deprecated.** Original audio file link returned by Suno. This link expires after a period of time and is no longer maintained — do not rely on it for long-term storage. Use the [Recovery Audio](/suno-api/recovery-audio) endpoint to obtain a fresh playable link. Streaming audio playback link Music cover image link Prompt/lyrics used for generation AI model name used Music title Music style tags Creation time Audio duration (seconds) ## Callback Reception Examples Here are example codes for receiving callbacks in various popular programming languages: ```javascript theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/music-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Received music generation callback:', { taskId: data.task_id, callbackType: data.callbackType, status: code, message: msg }); if (code === 200) { // Task successful const { callbackType, data: musicData } = data; switch (callbackType) { case 'text': console.log('Text generation completed'); break; case 'first': console.log('First music track generated'); if (musicData.length > 0) { console.log(`Music title: ${musicData[0].title}`); console.log(`Audio link: ${musicData[0].audio_url}`); console.log(`Duration: ${musicData[0].duration} seconds`); } break; case 'complete': console.log('All music tracks generated'); console.log(`Total ${musicData.length} tracks generated:`); musicData.forEach((track, index) => { console.log(`Track ${index + 1}: ${track.title} - ${track.audio_url}`); }); // Process generated music // Can download music, save locally, etc. break; } } else { // Task failed console.log('Music generation failed:', msg); // Handle failure cases... if (code === 400) { console.log('Parameter error or content violation'); } else if (code === 429) { console.log('Insufficient credits'); } else if (code === 500) { console.log('Server internal error'); } } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); app.listen(3000, () => { console.log('Callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import requests app = Flask(__name__) @app.route('/music-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) task_id = callback_data.get('task_id') callback_type = callback_data.get('callbackType') music_data = callback_data.get('data', []) print(f"Received music generation callback: {task_id}, Type: {callback_type}, Status: {code}") if code == 200: # Task successful if callback_type == 'text': print("Text generation completed") elif callback_type == 'first': print("First music track generated") if music_data: track = music_data[0] print(f"Music title: {track.get('title')}") print(f"Audio link: {track.get('audio_url')}") print(f"Duration: {track.get('duration')} seconds") elif callback_type == 'complete': print("All music tracks generated") print(f"Total {len(music_data)} tracks generated:") for i, track in enumerate(music_data): print(f"Track {i + 1}: {track.get('title')} - {track.get('audio_url')}") # Download music example try: audio_url = track.get('audio_url') if audio_url: response = requests.get(audio_url) if response.status_code == 200: filename = f"music_{task_id}_{i + 1}.mp3" with open(filename, "wb") as f: f.write(response.content) print(f"Music saved as {filename}") except Exception as e: print(f"Music download failed: {e}") else: # Task failed print(f"Music generation failed: {msg}") # Handle failure cases... if code == 400: print("Parameter error or content violation") elif code == 429: print("Insufficient credits") elif code == 500: print("Server internal error") # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```php theme={null} $track) { $title = $track['title'] ?? ''; $audioUrl = $track['audio_url'] ?? ''; error_log("Track " . ($index + 1) . ": $title - $audioUrl"); // Download music example try { if ($audioUrl) { $audioContent = file_get_contents($audioUrl); if ($audioContent !== false) { $filename = "music_{$taskId}_" . ($index + 1) . ".mp3"; file_put_contents($filename, $audioContent); error_log("Music saved as $filename"); } } } catch (Exception $e) { error_log("Music download failed: " . $e->getMessage()); } } break; } } else { // Task failed error_log("Music generation failed: $msg"); // Handle failure cases... if ($code === 400) { error_log("Parameter error or content violation"); } elseif ($code === 429) { error_log("Insufficient credits"); } elseif ($code === 500) { error_log("Server internal error"); } } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### Callback URL Configuration Recommendations 1. **Use HTTPS**: Ensure your callback URL uses HTTPS protocol for secure data transmission 2. **Verify Source**: Verify the legitimacy of the request source in callback processing 3. **Idempotent Processing**: Ensure processing logic is idempotent as the same taskId may receive multiple callbacks 4. **Quick Response**: Callback processing should return 200 status code quickly to avoid timeout 5. **Asynchronous Processing**: Complex business logic should be processed asynchronously to avoid blocking callback response 6. **Stage-based Processing**: Handle different callback stages (text, first, complete) with appropriate business logic 7. **Music Download**: Music download and processing should be done in asynchronous tasks to avoid blocking callback response ### Important Reminders * Callback URL must be publicly accessible * Server must respond within 15 seconds, otherwise considered timeout * After 3 consecutive retry failures, the system will stop sending callbacks * Ensure stability of callback processing logic to avoid callback failures due to exceptions * Generated audio URLs may have time limits, recommend downloading and saving promptly * Pay attention to content compliance to avoid generation failures due to violations * Music generation has three stages, each stage will trigger callback notifications ## Troubleshooting If you don't receive callback notifications, please check the following: * Confirm that the callback URL is accessible from the public internet * Check firewall settings to ensure inbound requests are not blocked * Verify that domain name resolution is correct * Ensure the server returns HTTP 200 status code within 15 seconds * Check server logs for error messages * Verify that the interface path and HTTP method are correct * Confirm that the received POST request body is in JSON format * Check if Content-Type is application/json * Verify that JSON parsing is correct * Confirm that audio URLs are accessible * Check music download permissions and network connectivity * Verify music save path and permissions * Note that music content must comply with content policies * Understand the differences and handling methods of the three callback stages * text stage: Only indicates text generation completed, no audio data * first stage: First music completed, contains data for one track * complete stage: All music completed, contains complete music list ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Music Generation Details interface to regularly query task status. Recommend querying every 30 seconds. # Generate Persona Source: https://docs.api.box/suno-api/generate-persona suno-api/suno-api.json POST /api/v1/generate/generate-persona Create a personalized music Persona based on generated music, giving the music a unique identity and characteristics. ### Usage Guide * Use this endpoint to create Personas (music characters) for generated music * Requires the taskId from supported music generation endpoints (generate, extend, mashup) and audio ID * Customize the Persona name and description to give music unique personality * Generated Personas can be used for subsequent music creation and style transfer * Can specify the time range (vocalStart and vocalEnd) for analysis segment to extract musical characteristics. If not specified, default values (0.0-30.0 seconds) will be used ### Parameter Details * `taskId`: Required parameter, can be obtained from the following endpoints: * [Generate Music](./generate-music) (`/api/v1/generate`) * [Extend Music](./extend-music) (`/api/v1/generate/extend`) * `audioId`: Required parameter, specifies the audio ID to create Persona for * `name`: Required parameter, assigns an easily recognizable name to the Persona * `description`: Required parameter, describes the Persona's musical characteristics, style, and personality * `vocalStart`: Optional parameter, specifies the start time (seconds) of the analysis segment. Default: 0.0 * `vocalEnd`: Optional parameter, specifies the end time (seconds) of the analysis segment. Default: 30.0. Must be greater than vocalStart * `style`: Optional parameter, music style label ### Developer Notes * **Important**: Ensure the music generation task is fully completed before calling this endpoint. If the music is still generating, this endpoint will return a failure * **Model Requirement**: Persona generation only supports taskId from music generated with V4 and above models * It is recommended to provide detailed descriptions for Personas to better capture musical characteristics * `vocalStart` and `vocalEnd` are used to specify the time range of the analysis segment. If not provided, default values (0.0-30.0 seconds) will be used. It is recommended to select a segment that best represents the musical characteristics * The returned `personaId` can be used in subsequent music generation requests to create music with similar style characteristics * You can apply the `personaId` to the following endpoints: * [Generate Music](./generate-music) * [Extend Music](./extend-music) * [Upload And Cover Audio](./upload-and-cover-audio) * [Upload And Extend Audio](./upload-and-extend-audio) * Each audio can only generate a Persona once ### Parameter Example ```json theme={null} { "taskId": "5c79****be8e", "audioId": "e231****-****-****-****-****8cadc7dc", "name": "Electronic Pop Singer", "description": "A modern electronic music style pop singer, skilled in dynamic rhythms and synthesizer tones", "vocalStart": 0.0, "vocalEnd": 30.0, "style": "Electronic Pop" } ``` Ensure that the music generation task corresponding to the taskId is complete and the audioId is valid. Providing detailed and specific descriptions for Personas helps the system more accurately capture musical style characteristics. # Generate Sounds Source: https://docs.api.box/suno-api/generate-sounds suno-api/suno-api.json POST /api/v1/generate/sounds Create a sound generation task with loop, tempo, key, and optional lyrics subtitle capture settings. ### Model Versions * **Current models**: `V6` (default), `V6_WILD`, `V6_MINI` * **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4` * Deprecated values remain available only for backward compatibility. New integrations should use a V6-series model. Used for creating a sound generation task (Sounds Task). It supports settings for looping, tempo (BPM), pitch (Key), as well as lyrics subtitle capture, etc. ## 🚀 User Guide * By using this interface, you can generate corresponding audio content based on the input `prompt`. * It supports setting up loop playback effect, which is suitable for background music, ambient sounds, and other scenarios. * It allows specifying BPM (beats per minute) and pitch (Key) to facilitate control over the style of the generated result. * Optional feature to enable lyric subtitle capture for easier display or processing of lyric content later. * Supports asynchronous reception of task completion notifications through callback address. ### `model` parameter * Allowed values: `V6`, `V6_WILD`, `V6_MINI`. Deprecated: `V5`, `V5_5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4`. ## 📌 Usage Scenarios * 🎧 Background music creation * 🎮 Game sound effects or looped ambient sounds generation * 🌐 Integration of audio content platforms and creative tools # Get Music Cover Details Source: https://docs.api.box/suno-api/get-cover-suno-details suno-api/suno-api.json GET /api/v1/suno/cover/record-info Get detailed information about music cover generation tasks. ### Usage Guide * Use this interface to check Cover generation task status * Access generated cover image URLs upon completion * Track processing progress and any errors that may occur * Supports polling to get task results, recommend querying every 30 seconds ### Developer Notes * Cover image URLs are only available upon successful completion * Error codes and messages are provided for failed tasks * After successful processing, cover images are retained for 14 days * Usually generates 2 different style cover images # Get Lyrics Generation Details Source: https://docs.api.box/suno-api/get-lyrics-generation-details suno-api/suno-api.json GET /api/v1/lyrics/record-info Retrieve detailed information about a lyrics generation task, including status, parameters, and results. ### Status Descriptions * PENDING: Task is waiting to be processed * SUCCESS: Lyrics generated successfully * CREATE\_TASK\_FAILED: Failed to create the task * GENERATE\_LYRICS\_FAILED: Failed to generate lyrics * CALLBACK\_EXCEPTION: Error occurred during callback * SENSITIVE\_WORD\_ERROR: Content contains prohibited words ### Developer Notes * Use this endpoint to check task status instead of waiting for callbacks * This returns all generated lyrics variations from a single task * Each lyrics variation includes a title and complete lyrics text # Get MIDI Generation Details Source: https://docs.api.box/suno-api/get-midi-details suno-api/suno-api.json GET /api/v1/midi/record-info Retrieve detailed information about a MIDI generation task including complete note data for all detected instruments. ### Usage Guide * Use this endpoint to check the status of a MIDI generation task * Access complete MIDI note data once processing is complete * Retrieve detailed instrument and note information * Track processing progress and any errors that may have occurred ### Query Parameters | Parameter | Type | Required | Description | | :- | :- | :- | :- | | `taskId` | string | Yes | The task ID returned from the MIDI generation request | ### Developer Notes * The `midiData` field contains the complete MIDI data as a structured object with instruments and notes * MIDI data includes all detected instruments with pitch, timing, and velocity for each note * MIDI generation records are retained for 14 days * **Important**: When using [vocal separation](/suno-api/separate-vocals-from-music) with `type: split_stem`, the `midiData` may be empty. # Get Music Generation Details Source: https://docs.api.box/suno-api/get-music-generation-details suno-api/suno-api.json GET /api/v1/generate/record-info Retrieve detailed information about a music generation task, including status, parameters, and results. ### Status Descriptions * PENDING: Task is waiting to be processed * TEXT\_SUCCESS: Lyrics/text generation completed successfully * FIRST\_SUCCESS: First track generation completed successfully * SUCCESS: All tracks generated successfully * CREATE\_TASK\_FAILED: Failed to create the generation task * GENERATE\_AUDIO\_FAILED: Failed to generate music tracks * CALLBACK\_EXCEPTION: Error occurred during callback * SENSITIVE\_WORD\_ERROR: Content contains prohibited words ### Developer Notes * For instrumental tracks (instrumental=true), no lyrics data will be included in the response * Use this endpoint to check task status instead of waiting for callbacks # Get Music Video Details Source: https://docs.api.box/suno-api/get-music-video-details suno-api/suno-api.json GET /api/v1/mp4/record-info Retrieve detailed information about a music video generation task, including status and download link. ### Status Descriptions * PENDING: Task is waiting to be processed * SUCCESS: Video generation completed successfully * CREATE\_TASK\_FAILED: Failed to create the video task * GENERATE\_MP4\_FAILED: MP4 generation failed * CALLBACK\_EXCEPTION: Callback exception # Get Recovery Audio Details Source: https://docs.api.box/suno-api/get-recovery-audio-details suno-api/suno-api.json GET /api/v1/suno/recovery/record-info Query the status and recovered audio links of a recovery task. Query a recovery task created by [Recovery Audio](/suno-api/recovery-audio) and read the recovered audio links. ### Status Descriptions * `201` — the recovery task is still running, keep polling * `200` — the recovery finished and at least one track was recovered successfully * `500` — every track failed to recover ### Per-track `status` * `success` — `audio_url` carries the recovered playable link * `failed` — `audio_url` is empty and `error` explains the reason Common `error` values: | Value | Meaning | | - | - | | `no_audio_id_mappings` | The track cannot be found for this task | | `account_missing` | The source account is unavailable | | `get_tokens_failed` | Failed to authenticate against the upstream service | | `feed_failed` | Failed to query the track from the upstream service | | `clip_error` | The upstream track is in an error state | | `clip_not_complete` | The upstream track is not finished yet | | `mango_transfer_failed` | Failed to transfer the recovered file | ### Developer Notes * Poll this endpoint instead of waiting for the callback when you cannot expose a public callback URL. A 2 second interval is recommended. * `data` is `null` while `code` is `201`. * A recovered `audio_url` may be an `.m4a` file — do not assume `.mp3` when saving it. # Get Remaining Credits Source: https://docs.api.box/suno-api/get-remaining-credits suno-api/suno-api.json GET /api/v1/generate/credit Retrieve the current balance of available credits for your account. ### Usage Guide * Credits are consumed when generating music, lyrics, or using other processing features. * This endpoint allows you to check your current credit balance before initiating tasks. * Returns a single integer value representing your available credits. * No parameters required; authentication via API key is sufficient. ### Developer Notes 1. Monitor your credit balance regularly to avoid service interruptions. 2. If credits are insufficient, generation tasks will fail with error code 429. 3. Consider integrating this check before starting expensive generation operations. 4. This endpoint is lightweight and can be called frequently as needed. # Get Timestamped Lyrics Source: https://docs.api.box/suno-api/get-timestamped-lyrics suno-api/suno-api.json POST /api/v1/generate/get-timestamped-lyrics Retrieve timestamped lyrics for synchronized display during audio playback. ### Parameter Selection Logic 1. Use audioId to identify the specific track: * The audioId parameter is used to match the exact audio track * This parameter is required to retrieve lyrics for the correct track ### Developer Notes 1. Timestamp values are in seconds 2. Returned waveform data can be used for audio visualization 3. For instrumental tracks (generated with instrumental=true), no lyrics data will be available 4. Typical use case: Karaoke-style lyrics display in music player interfaces # Get Audio Separation Details Source: https://docs.api.box/suno-api/get-vocal-separation-details suno-api/suno-api.json GET /api/v1/vocal-removal/record-info Retrieve detailed information about vocal and instrument separation tasks, including status and download links. ### Status Descriptions * PENDING: Task is waiting to be processed * SUCCESS: Vocal separation completed successfully * CREATE\_TASK\_FAILED: Failed to create the separation task * GENERATE\_AUDIO\_FAILED: Failed to perform vocal separation * CALLBACK\_EXCEPTION: Error occurred during callback ### Separation Type Description Based on the `type` parameter specified when submitting the task, the query details return different fields: #### separate\_vocal Type Results When using `separate_vocal` type for separation, the response contains the following fields: 1. `originUrl`: Original mixed track 2. `instrumentalUrl`: Instrumental track without vocals 3. `vocalUrl`: Isolated vocals only track 4. Other instrument fields are `null` #### split\_stem Type Results When using `split_stem` type for separation, the response contains the following fields: 1. `originUrl`: Original mixed track 2. `vocalUrl`: Isolated vocals only track 3. `backingVocalsUrl`: Isolated backing vocals track 4. `drumsUrl`: Isolated drums track 5. `bassUrl`: Isolated bass track 6. `guitarUrl`: Isolated guitar track 7. `keyboardUrl`: Isolated keyboard track 8. `percussionUrl`: Isolated percussion instruments track 9. `stringsUrl`: Isolated string instruments track 10. `synthUrl`: Isolated synthesizer track 11. `fxUrl`: Isolated sound effects track 12. `brassUrl`: Isolated brass instruments track 13. `woodwindsUrl`: Isolated woodwind instruments track 14. `instrumentalUrl`: Instrumental track (is null in split\_stem type) ### Developer Notes * Use this endpoint to check separation status instead of waiting for callbacks * When status is SUCCESS, the response includes multiple download URLs * Different separation types return different numbers of audio files * `separate_vocal` type returns `instrumentalUrl` and `vocalUrl` fields, other instrument fields are null * `split_stem` type returns detailed instrument separation fields, `instrumentalUrl` is null * Task creation and completion times are included in the response * All audio file URLs are retained for 14 days, download and save them promptly # Get WAV Conversion Details Source: https://docs.api.box/suno-api/get-wav-conversion-details suno-api/suno-api.json GET /api/v1/wav/record-info Retrieve detailed information about a WAV format conversion task, including status and download link. ### Status Descriptions * PENDING: Task is waiting to be processed * SUCCESS: WAV conversion completed successfully * CREATE\_TASK\_FAILED: Failed to create the conversion task * GENERATE\_WAV\_FAILED: Failed to convert to WAV format * CALLBACK\_EXCEPTION: Error occurred during callback ### Developer Notes * Use this endpoint to check conversion status instead of waiting for callbacks * The response includes the WAV file download URL when status is SUCCESS * Task creation and completion times are included in the response # Quick Start Source: https://docs.api.box/suno-api/quickstart Get started with Suno API to generate AI music, lyrics, and audio content in minutes ## Welcome to Suno API Suno API enables you to create high-quality AI-generated music, lyrics, and audio content using state-of-the-art AI models. Whether you're building music applications, automating creative workflows, or developing audio content, our API provides comprehensive tools for music generation and audio processing. Create original music tracks with or without lyrics Seamlessly extend existing music tracks Create creative lyrics from text prompts Convert audio tracks to visualized music videos Transform uploaded audio into new styles Upload audio files and seamlessly extend them Separate vocals and instrumentals from music Convert audio to high-quality WAV format Retrieve timestamped synchronized lyrics Add instrumental elements to existing audio tracks Generate vocal tracks for instrumental music Enhance style descriptions with V4\_5 conversational prompts ## Authentication All API requests require authentication using Bearer tokens. Please obtain your API key from the [API Key Management Page](https://api.box/api-key). Keep your API key secure and never share it publicly. If you suspect your key has been compromised, reset it immediately. ### API Base URL ``` https://apibox.erweima.ai ``` ### Authentication Header ```http theme={null} Authorization: Bearer YOUR_API_KEY ``` ## Quick Start Guide ### Step 1: Generate Your First Music Track Start with a simple music generation request: ```bash cURL theme={null} curl -X POST "https://apibox.erweima.ai/api/v1/generate" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "prompt": "A peaceful and soothing piano piece with soft melodies", "customMode": false, "instrumental": true, "model": "V6", "callBackUrl": "https://your-app.com/callback" }' ``` ```javascript JavaScript theme={null} const response = await fetch('https://apibox.erweima.ai/api/v1/generate', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'A peaceful and soothing piano piece with soft melodies', customMode: false, instrumental: true, model: 'V6', callBackUrl: 'https://your-app.com/callback' }) }); const data = await response.json(); console.log('Task ID:', data.data.taskId); ``` ```python Python theme={null} import requests url = "https://apibox.erweima.ai/api/v1/generate" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } payload = { "prompt": "A peaceful and soothing piano piece with soft melodies", "customMode": False, "instrumental": True, "model": "V6", "callBackUrl": "https://your-app.com/callback" } response = requests.post(url, json=payload, headers=headers) result = response.json() print(f"Task ID: {result['data']['taskId']}") ``` ```php PHP theme={null} 'A peaceful and soothing piano piece with soft melodies', 'customMode' => false, 'instrumental' => true, 'model' => 'V6', 'callBackUrl' => 'https://your-app.com/callback' ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $result = json_decode($response, true); echo "Task ID: " . $result['data']['taskId']; ?> ``` ### Step 2: Check Task Status Use the returned task ID to check generation status: ```bash cURL theme={null} curl -X GET "https://apibox.erweima.ai/api/v1/generate/record-info?taskId=YOUR_TASK_ID" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```javascript JavaScript theme={null} const response = await fetch(`https://apibox.erweima.ai/api/v1/generate/record-info?taskId=${taskId}`, { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }); const result = await response.json(); if (result.data.status === 'SUCCESS') { console.log('Generation complete!'); console.log('Audio tracks:', result.data.response.data); } else if (result.data.status === 'PENDING') { console.log('Still generating...'); } else { console.log('Generation failed:', result.data.status); } ``` ```python Python theme={null} import requests import time def check_task_status(task_id, api_key): url = f"https://apibox.erweima.ai/api/v1/generate/record-info?taskId={task_id}" headers = {"Authorization": f"Bearer {api_key}"} response = requests.get(url, headers=headers) result = response.json() status = result['data']['status'] if status == 'SUCCESS': print("Generation complete!") tracks = result['data']['response']['data'] for i, track in enumerate(tracks): print(f"Track {i+1}: {track['audio_url']}") return tracks elif status == 'PENDING': print("Still generating...") return None else: print(f"Generation failed: {status}") return None # Poll until complete task_id = "YOUR_TASK_ID" while True: tracks = check_task_status(task_id, "YOUR_API_KEY") if tracks: break time.sleep(30) # Wait 30 seconds before checking again ``` ### Response Format **Success Response:** ```json theme={null} { "code": 200, "msg": "success", "data": { "taskId": "5c79****be8e" } } ``` **Task Status Response:** ```json theme={null} { "code": 200, "msg": "success", "data": { "taskId": "5c79****be8e", "status": "SUCCESS", "response": { "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "prompt": "A peaceful and soothing piano piece", "title": "Peaceful Piano", "tags": "peaceful, soothing, piano", "duration": 198.44, "createTime": "2025-01-01 00:00:00" } ] } } } ``` ## Core Features * **Text-to-Music**: Input text descriptions to generate corresponding musical compositions * **Music Extension**: Seamlessly create longer versions based on existing audio * **Lyrics Generation**: Generate structured lyrical content from creative prompts * **Upload & Cover**: Upload audio files and transform them into different musical styles * **Upload & Extend**: Upload audio files and seamlessly extend them while preserving style * **Vocal Separation**: Separate music into independent tracks like vocals and instrumentals with advanced stem separation * **Format Conversion**: Support for WAV and other high-quality audio format outputs * **Music Videos**: Convert audio to visualized music videos * **Add Vocals**: Generate vocal tracks for existing instrumental music * **Add Instrumental**: Create instrumental accompaniment for vocal tracks * **Style Enhancement**: Enhance and optimize existing music's stylistic features with V4\_5+ conversational prompts * **Timestamped Lyrics**: Retrieve synchronized lyrics for karaoke-style applications ## AI Models Choose the right model for your needs: **Default model** Latest generation. `style` 1000 chars, `lyrics` 5000 chars, `negativeTags` 1000 chars **Bolder output** Same limits as V6, tuned for more adventurous results **Faster and lighter** Same limits as V6, optimized for speed **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4`. These values remain accepted for backward compatibility only — new integrations should use a V6-series model. ## Generation Modes Controls parameter complexity. `customMode` applies to [Generate Music](/suno-api/generate-music) only — every other generation endpoint always uses custom parameters and does not accept this switch. * `false`: Simple mode. Provide at least one of `imageUrls`, `videoUrls`, `audioUrls`, `style`, or `lyrics`. Parameters that are custom-mode only must not be sent. * `true`: Custom mode. Provide at least one of `style`, `lyrics`, or `negativeTags`. `title` is optional. Determines whether music contains vocals: * `true`: Instrumental only (no lyrics) * `false`: Contains vocals/lyrics ## Key Parameters Text description of the desired music. Optional. * Custom mode: used strictly as lyrics. If `lyrics` is also provided, `lyrics` takes priority. * Non-custom mode: used as the core idea; lyrics are generated from it and do not strictly match the input. Maximum 3000 characters. **Character Limits (custom mode):** * V6, V6\_WILD, V6\_MINI: 5000 characters * V4 (Deprecated): 3000 characters * V4\_5, V4\_5PLUS, V4\_5ALL, V5, V5\_5 (Deprecated): 5000 characters Lyrics for the generated track. Optional. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters. * Custom mode: takes priority over `prompt` as the lyrics; falls back to `prompt` when omitted. * Non-custom mode: acts as a lyrics attachment and can be combined with `prompt`. Music style specification. Optional. **Examples:** Jazz, Classical, Electronic, Pop, Rock, Hip-hop **Character Limits:** * V6, V6\_WILD, V6\_MINI: 1000 characters * V4 (Deprecated): 200 characters * V4\_5, V4\_5PLUS, V4\_5ALL, V5, V5\_5 (Deprecated): 1000 characters Title for the generated music track. Optional, and only available in custom mode. **Maximum Length:** 80 characters Diversity of the generated results. Optional. Integer from 0 to 4, default `1`. `0` off (exact style), `1` normal (default, balanced), `2` high (distinct styles), `3` extra (bold exploration), `4` max (maximum variation). ## Complete Workflow Example Here's a complete example of generating music with lyrics and waiting for completion: ```javascript theme={null} class SunoAPI { constructor(apiKey) { this.apiKey = apiKey; this.baseUrl = 'https://apibox.erweima.ai/api/v1'; } async generateMusic(prompt, options = {}) { const response = await fetch(`${this.baseUrl}/generate`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt, customMode: options.customMode || false, instrumental: options.instrumental || false, model: options.model || 'V6', lyrics: options.lyrics, style: options.style, // title, negativeTags, vocalGender, styleWeight, weirdnessConstraint, // audioWeight and variety are custom-mode only — omit them when customMode is false title: options.title, negativeTags: options.negativeTags, callBackUrl: options.callBackUrl || 'https://your-app.com/callback', vocalGender: options.vocalGender, styleWeight: options.styleWeight, weirdnessConstraint: options.weirdnessConstraint, audioWeight: options.audioWeight, variety: options.variety }) }); const result = await response.json(); if (result.code !== 200) { throw new Error(`Generation failed: ${result.msg}`); } return result.data.taskId; } async extendMusic(audioId, options = {}) { const response = await fetch(`${this.baseUrl}/generate/extend`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ // Extend always uses custom parameters — there is no simple-mode switch here audioId, model: options.model || 'V6', lyrics: options.lyrics, prompt: options.prompt, style: options.style, title: options.title, continueAt: options.continueAt, callBackUrl: options.callBackUrl || 'https://your-app.com/callback', vocalGender: options.vocalGender, styleWeight: options.styleWeight, weirdnessConstraint: options.weirdnessConstraint, audioWeight: options.audioWeight, variety: options.variety }) }); const result = await response.json(); if (result.code !== 200) { throw new Error(`Extension failed: ${result.msg}`); } return result.data.taskId; } async generateLyrics(prompt, callBackUrl) { const response = await fetch(`${this.baseUrl}/lyrics`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt, callBackUrl }) }); const result = await response.json(); if (result.code !== 200) { throw new Error(`Lyrics generation failed: ${result.msg}`); } return result.data.taskId; } async addVocals(uploadUrl, prompt, style, title, negativeTags, options = {}) { const response = await fetch(`${this.baseUrl}/generate/add-vocals`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ uploadUrl, prompt, style, title, negativeTags, model: options.model || 'V6', callBackUrl: options.callBackUrl || 'https://your-app.com/callback', vocalGender: options.vocalGender, styleWeight: options.styleWeight, weirdnessConstraint: options.weirdnessConstraint, audioWeight: options.audioWeight }) }); const result = await response.json(); if (result.code !== 200) { throw new Error(`Add vocals failed: ${result.msg}`); } return result.data.taskId; } async addInstrumental(uploadUrl, title, tags, negativeTags, options = {}) { const response = await fetch(`${this.baseUrl}/generate/add-instrumental`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ uploadUrl, title, tags, negativeTags, model: options.model || 'V6', callBackUrl: options.callBackUrl || 'https://your-app.com/callback', vocalGender: options.vocalGender, styleWeight: options.styleWeight, weirdnessConstraint: options.weirdnessConstraint, audioWeight: options.audioWeight }) }); const result = await response.json(); if (result.code !== 200) { throw new Error(`Add instrumental failed: ${result.msg}`); } return result.data.taskId; } async waitForCompletion(taskId, maxWaitTime = 600000) { // Max wait 10 minutes const startTime = Date.now(); while (Date.now() - startTime < maxWaitTime) { const status = await this.getTaskStatus(taskId); if (status.status === 'SUCCESS') { return status.response; } else if (status.status.includes('FAILED') || status.status === 'SENSITIVE_WORD_ERROR') { throw new Error(`Generation failed: ${status.errorMessage || status.status}`); } // Wait 10 seconds before checking again await new Promise(resolve => setTimeout(resolve, 10000)); } throw new Error('Generation timeout'); } async getTaskStatus(taskId) { const response = await fetch(`${this.baseUrl}/generate/record-info?taskId=${taskId}`, { headers: { 'Authorization': `Bearer ${this.apiKey}` } }); const result = await response.json(); return result.data; } async getRemainingCredits() { const response = await fetch(`${this.baseUrl}/generate/credit`, { headers: { 'Authorization': `Bearer ${this.apiKey}` } }); const result = await response.json(); return result.data.credits; } } // Usage example async function main() { const api = new SunoAPI('YOUR_API_KEY'); try { // Check remaining credits const credits = await api.getRemainingCredits(); console.log(`Remaining credits: ${credits}`); // Generate music with lyrics console.log('Starting music generation...'); const taskId = await api.generateMusic( 'A nostalgic folk song about childhood memories', { customMode: true, instrumental: false, model: 'V6', style: 'folk, acoustic guitar, nostalgic', title: 'Childhood Dreams' } ); // Wait for completion console.log(`Task ID: ${taskId}. Waiting for completion...`); const result = await api.waitForCompletion(taskId); console.log('Music generation successful!'); console.log('Generated tracks:'); result.data.forEach((track, index) => { console.log(`Track ${index + 1}:`); console.log(` Title: ${track.title}`); console.log(` Audio URL: ${track.audio_url}`); console.log(` Duration: ${track.duration} seconds`); console.log(` Tags: ${track.tags}`); }); // Extend the first track const firstTrack = result.data[0]; console.log('\nExtending first track...'); const extendTaskId = await api.extendMusic(firstTrack.id, { lyrics: '[Chorus] And the morning finds us singing', prompt: 'Continue with a hopeful chorus', style: 'folk, uplifting', title: 'Childhood Dreams Extended', continueAt: 60, model: 'V6' }); const extendResult = await api.waitForCompletion(extendTaskId); console.log('Music extension successful!'); console.log('Extended track URL:', extendResult.data[0].audio_url); } catch (error) { console.error('Error:', error.message); } } main(); ``` ```python theme={null} import requests import time class SunoAPI: def __init__(self, api_key): self.api_key = api_key self.base_url = 'https://apibox.erweima.ai/api/v1' self.headers = { 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' } def generate_music(self, prompt, **options): data = { 'prompt': prompt, 'customMode': options.get('customMode', False), 'instrumental': options.get('instrumental', False), 'model': options.get('model', 'V6'), 'callBackUrl': options.get('callBackUrl', 'https://your-app.com/callback') } if options.get('lyrics'): data['lyrics'] = options['lyrics'] if options.get('style'): data['style'] = options['style'] # title, negativeTags, vocalGender, styleWeight, weirdnessConstraint, # audioWeight and variety are custom-mode only — omit them when customMode is False if options.get('title'): data['title'] = options['title'] if options.get('negativeTags'): data['negativeTags'] = options['negativeTags'] if options.get('vocalGender'): data['vocalGender'] = options['vocalGender'] if options.get('styleWeight'): data['styleWeight'] = options['styleWeight'] if options.get('weirdnessConstraint'): data['weirdnessConstraint'] = options['weirdnessConstraint'] if options.get('audioWeight'): data['audioWeight'] = options['audioWeight'] if options.get('variety') is not None: data['variety'] = options['variety'] response = requests.post(f'{self.base_url}/generate', headers=self.headers, json=data) result = response.json() if result['code'] != 200: raise Exception(f"Generation failed: {result['msg']}") return result['data']['taskId'] def extend_music(self, audio_id, **options): # Extend always uses custom parameters — there is no simple-mode switch here data = { 'audioId': audio_id, 'model': options.get('model', 'V6'), 'callBackUrl': options.get('callBackUrl', 'https://your-app.com/callback') } if options.get('lyrics'): data['lyrics'] = options['lyrics'] if options.get('prompt'): data['prompt'] = options['prompt'] if options.get('style'): data['style'] = options['style'] if options.get('title'): data['title'] = options['title'] if options.get('continueAt'): data['continueAt'] = options['continueAt'] if options.get('vocalGender'): data['vocalGender'] = options['vocalGender'] if options.get('styleWeight'): data['styleWeight'] = options['styleWeight'] if options.get('weirdnessConstraint'): data['weirdnessConstraint'] = options['weirdnessConstraint'] if options.get('audioWeight'): data['audioWeight'] = options['audioWeight'] if options.get('variety') is not None: data['variety'] = options['variety'] response = requests.post(f'{self.base_url}/generate/extend', headers=self.headers, json=data) result = response.json() if result['code'] != 200: raise Exception(f"Extension failed: {result['msg']}") return result['data']['taskId'] def generate_lyrics(self, prompt, callback_url): data = { 'prompt': prompt, 'callBackUrl': callback_url } response = requests.post(f'{self.base_url}/lyrics', headers=self.headers, json=data) result = response.json() if result['code'] != 200: raise Exception(f"Lyrics generation failed: {result['msg']}") return result['data']['taskId'] def add_vocals(self, upload_url, prompt, style, title, negative_tags, **options): data = { 'uploadUrl': upload_url, 'prompt': prompt, 'style': style, 'title': title, 'negativeTags': negative_tags, 'model': options.get('model', 'V6'), 'callBackUrl': options.get('callBackUrl', 'https://your-app.com/callback') } if options.get('vocalGender'): data['vocalGender'] = options['vocalGender'] if options.get('styleWeight'): data['styleWeight'] = options['styleWeight'] if options.get('weirdnessConstraint'): data['weirdnessConstraint'] = options['weirdnessConstraint'] if options.get('audioWeight'): data['audioWeight'] = options['audioWeight'] response = requests.post(f'{self.base_url}/generate/add-vocals', headers=self.headers, json=data) result = response.json() if result['code'] != 200: raise Exception(f"Add vocals failed: {result['msg']}") return result['data']['taskId'] def add_instrumental(self, upload_url, title, tags, negative_tags, **options): data = { 'uploadUrl': upload_url, 'title': title, 'tags': tags, 'negativeTags': negative_tags, 'model': options.get('model', 'V6'), 'callBackUrl': options.get('callBackUrl', 'https://your-app.com/callback') } if options.get('vocalGender'): data['vocalGender'] = options['vocalGender'] if options.get('styleWeight'): data['styleWeight'] = options['styleWeight'] if options.get('weirdnessConstraint'): data['weirdnessConstraint'] = options['weirdnessConstraint'] if options.get('audioWeight'): data['audioWeight'] = options['audioWeight'] response = requests.post(f'{self.base_url}/generate/add-instrumental', headers=self.headers, json=data) result = response.json() if result['code'] != 200: raise Exception(f"Add instrumental failed: {result['msg']}") return result['data']['taskId'] def wait_for_completion(self, task_id, max_wait_time=600): start_time = time.time() while time.time() - start_time < max_wait_time: status = self.get_task_status(task_id) if status['status'] == 'SUCCESS': return status['response'] elif 'FAILED' in status['status'] or status['status'] == 'SENSITIVE_WORD_ERROR': error_msg = status.get('errorMessage', status['status']) raise Exception(f"Generation failed: {error_msg}") time.sleep(10) # Wait 10 seconds raise Exception('Generation timeout') def get_task_status(self, task_id): response = requests.get(f'{self.base_url}/generate/record-info?taskId={task_id}', headers={'Authorization': f'Bearer {self.api_key}'}) return response.json()['data'] def get_remaining_credits(self): response = requests.get(f'{self.base_url}/generate/credit', headers={'Authorization': f'Bearer {self.api_key}'}) return response.json()['data']['credits'] # Usage example def main(): api = SunoAPI('YOUR_API_KEY') try: # Check remaining credits credits = api.get_remaining_credits() print(f'Remaining credits: {credits}') # Generate music with lyrics print('Starting music generation...') task_id = api.generate_music( 'A nostalgic folk song about childhood memories', customMode=True, instrumental=False, model='V6', style='folk, acoustic guitar, nostalgic', title='Childhood Dreams' ) # Wait for completion print(f'Task ID: {task_id}. Waiting for completion...') result = api.wait_for_completion(task_id) print('Music generation successful!') print('Generated tracks:') for i, track in enumerate(result['data']): print(f"Track {i + 1}:") print(f" Title: {track['title']}") print(f" Audio URL: {track['audio_url']}") print(f" Duration: {track['duration']} seconds") print(f" Tags: {track['tags']}") # Extend the first track first_track = result['data'][0] print('\nExtending first track...') extend_task_id = api.extend_music( first_track['id'], lyrics='[Chorus] And the morning finds us singing', prompt='Continue with a hopeful chorus', style='folk, uplifting', title='Childhood Dreams Extended', continueAt=60, model='V6' ) extend_result = api.wait_for_completion(extend_task_id) print('Music extension successful!') print(f"Extended track URL: {extend_result['data'][0]['audio_url']}") except Exception as error: print(f'Error: {error}') if __name__ == '__main__': main() ``` ## Status Codes and Task Status Task is waiting for processing or currently generating Lyrics/text generation successfully completed First track generation completed All tracks generated successfully Task creation failed Audio generation failed Content filtered due to sensitive words ## HTTP Status Codes Request successful Invalid parameters or missing required fields No access permission, check API key Invalid request method or path Call limit exceeded Prompt or theme too long Account credits insufficient System maintenance in progress Internal server error ## Best Practices * Be specific about genre, mood, and instruments * Use descriptive adjectives for better style control * Include tempo and energy level descriptions * Reference musical eras or specific artists for style guidance * V6: The default. Use it unless you have a specific reason not to * V6\_WILD: Choose when you want bolder, more adventurous results * V6\_MINI: Choose when generation speed matters more than maximum quality * V5\_5, V5, V4\_5PLUS, V4\_5ALL, V4\_5, V4 are deprecated and kept only for backward compatibility * Use callbacks instead of frequent polling * Start with non-custom mode for simple needs * Implement proper error handling for generation failures * Cache generated content as files expire after 14-15 days * Avoid using copyrighted material in prompts * Use original lyrics and music descriptions * Be mindful of content policies for lyrical content * Test prompt variations to avoid sensitive word filters ## Error Handling ```javascript theme={null} try { const taskId = await api.generateMusic('copyrighted lyrics'); } catch (error) { if (error.data.code === 400) { console.log('Please use only original content'); } } ``` ```javascript theme={null} try { const taskId = await api.generateMusic('original composition'); } catch (error) { if (error.data.code === 429) { console.log('Please add more credits to your account'); } } ``` ```javascript theme={null} const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); async function generateWithRetry(prompt, options, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await api.generateMusic(prompt, options); } catch (error) { if (error.data.code === 405 && i < maxRetries - 1) { await delay(Math.pow(2, i) * 1000); // Exponential backoff continue; } throw error; } } } ``` ## Support Need help? Our technical support team is here to assist you. * **Email**: [support@api.box](mailto:support@api.box) * **Documentation**: Check detailed API documentation and examples * **API Status**: View our status page for real-time API health information *** Ready to start creating amazing AI music? [Get your API key](https://api.box/api-key) and start creating today! # Recovery Audio Source: https://docs.api.box/suno-api/recovery-audio suno-api/suno-api.json POST /api/v1/suno/recovery Recover playable audio links for an existing music generation task. Used to recover playable audio links for a music generation task that has already completed. Submit the `sunoTaskId` of the original task and the service regenerates accessible audio URLs for every track that belongs to it. ## 🚀 User Guide * Suno's original links are only valid for a limited period of time. Once they expire, the audio can no longer be played or downloaded from those URLs. * Submit the `sunoTaskId` of the original music generation task — all tracks of that task are recovered together. * This endpoint only creates the task: it returns a recovery `task_id` immediately and the recovery itself runs asynchronously. * The result is pushed to `callBackUrl` when the task finishes, and can also be read by polling [Get Recovery Audio Details](/suno-api/get-recovery-audio-details). **`source_audio_url` is deprecated.** `source_audio_url` in the generation responses and callbacks points to Suno's original file. That link expires after a period of time and is no longer maintained, so it must not be stored for long-term use. Call this endpoint to obtain a fresh playable link instead. ## 📌 Usage Scenarios * 🔗 Restoring playback for songs that were generated a long time ago * 📦 Refreshing audio links before archiving or migrating your own library * 🛠️ Repairing broken audio URLs reported by your end users ## ⚠️ Notes * `sunoTaskId` in the request body is the **music generation task ID** (for example the one returned by [Generate Music](/suno-api/generate-music)), not the ID returned by this endpoint. * The `task_id` in the response is the **recovery task ID** and is only accepted by [Get Recovery Audio Details](/suno-api/get-recovery-audio-details). * `callBackUrl` is required. The recovery result is pushed to it once the task finishes. * Creating the task successfully does not guarantee that every track can be recovered — check the final result for the per-track `status`. ## 📩 Callback Once the recovery task finishes, a `POST` request is sent to `callBackUrl`: ```json theme={null} { "code": 200, "msg": "success", "task_id": "bbbb****0f7b", "data": [ { "id": "3bc3****48fc", "audio_url": "https://example.com/****.m4a", "title": "Sunrise Love", "status": "success", "error": "" } ] } ``` The task level `code` is `200` when at least one track was recovered, and `500` when all of them failed. The order of `data` matches the tracks of the original task. # Replace Music Section Source: https://docs.api.box/suno-api/replace-section suno-api/suno-api.json POST /api/v1/generate/replace-section Replace a specific time segment within existing music. ### Model Versions * **Current models**: `V6` (default), `V6_WILD`, `V6_MINI` * **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4` * Deprecated values remain available only for backward compatibility. New integrations should use a V6-series model. ### Parameter Usage Guide This endpoint always uses custom parameters. Simple mode is not available. This endpoint supports two modes for specifying the source audio: **Mode 1: Replace section using existing audio** * `taskId` and `audioId` are required * `uploadUrl` and `model` must NOT be provided **Mode 2: Replace section using uploaded custom audio** * `uploadUrl` and `model` are required * `taskId` and `audioId` must NOT be provided ### Common Required Parameters * **prompt** (string, required): Replaced lyrics * **tags** (string, required): Music style tags, such as jazz, electronic, etc. * **title** (string, required): Music title * **infillStartS** (number, required): Start time point for replacement (seconds), 2 decimal places. Must be less than infillEndS. The time interval (infillEndS - infillStartS) must be at least 10 seconds. * **infillEndS** (number, required): End time point for replacement (seconds), 2 decimal places. Must be greater than infillStartS. The time interval (infillEndS - infillStartS) must be at least 10 seconds. * **fullLyrics** (string, required): Complete lyrics after modification, combining both modified and unmodified lyrics ### Lyrics Fields Three fields carry lyrics, each with a different scope: * **fullLyrics** (required): the complete lyrics of the **whole song** after the replacement, combining modified and unmodified parts. The upstream service uses it to re-align the prompt for the infill segment. * **lyrics** (optional): lyrics for the **replaced segment only**. * **prompt** (required): the replaced lyrics, kept for backward compatibility. ### Optional Parameters The following fields are optional controls available for this endpoint: * lyrics (string): Lyrics for the replaced section. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters. * negativeTags (string): Excluded music styles, used to avoid specific style elements in the replacement segment * vocalGender (string): Preferred vocal gender. Allowed values: `m` (male), `f` (female) * styleWeight (number): Style adherence weight in range 0–1 (recommended two decimals) * weirdnessConstraint (number): Creativity/novelty constraint in range 0–1 (recommended two decimals) * audioWeight (number): Relative weight of audio consistency in range 0–1 (recommended two decimals) * variety (integer): Diversity of generated results. Integer from 0–4, default 1. `0` off, `1` normal (default), `2` high, `3` extra, `4` max. * personaId (string): Persona ID or Suno Voice `voiceId` to apply to the generated music. If you use a Voice-generated ID, set `personaModel` to `voice_persona`. * personaModel (string): Persona type, default `style_persona`. Use `style_persona` for Generate Persona IDs, or `voice_persona` for Suno Voice IDs. * callBackUrl (string): Callback URL for task completion notification. For detailed callback format, see [Replace Music Section Callbacks](/suno-api/replace-section-callbacks). ### Time Range Instructions * `infillStartS` must be less than `infillEndS` * Time values are precise to 2 decimal places, e.g., `10.50` seconds * The replacement time must be at least **10 seconds**. * Replacement duration should not exceed **50%** of the original music's total duration ```json Replace using existing audio theme={null} { "taskId": "2fac****9f72", "audioId": "e231****-****-****-****-****8cadc7dc", "prompt": "A calm and relaxing piano track.", "lyrics": "[Chorus]\nModified lyrics for this section", "tags": "Jazz", "title": "Relaxing Piano", "negativeTags": "Rock", "infillStartS": 10.5, "infillEndS": 20.75, "fullLyrics": "[Verse 1]\nOriginal lyrics here\n[Chorus]\nModified lyrics for this section\n[Verse 2]\nMore original lyrics", "vocalGender": "m", "styleWeight": 0.61, "weirdnessConstraint": 0.72, "audioWeight": 0.65, "variety": 1, "callBackUrl": "https://example.com/callback" } ``` ```json Replace using uploaded audio theme={null} { "uploadUrl": "https://example.com/audio.mp3", "model": "V6", "prompt": "A calm and relaxing piano track.", "lyrics": "[Chorus]\nModified lyrics for this section", "tags": "Jazz", "title": "Relaxing Piano", "negativeTags": "Rock", "infillStartS": 10.5, "infillEndS": 20.75, "fullLyrics": "[Verse 1]\nOriginal lyrics here\n[Chorus]\nModified lyrics for this section\n[Verse 2]\nMore original lyrics", "vocalGender": "m", "styleWeight": 0.61, "weirdnessConstraint": 0.72, "audioWeight": 0.65, "variety": 1, "callBackUrl": "https://example.com/callback" } ``` ### Developer Notes 1. Replacement segments will be regenerated based on the provided `prompt` and `tags` 2. Generated replacement segments will automatically blend with the original music's preceding and following parts 3. Generated files will be retained for **14 days** 4. Query task status using the same interface as generating music: [Get Music Details](/suno-api/get-music-generation-details) # Replace Music Section Callbacks Source: https://docs.api.box/suno-api/replace-section-callbacks Understand the callback mechanism for replace music section tasks When you submit a replace music section task to the API, you can provide a `callBackUrl` to receive real-time notifications about task progress and completion. ## Callback Mechanism ### When Callbacks Are Sent The system sends callbacks at the following times: * **Complete**: When the replacement task is fully completed ### Callback Method * **HTTP Method**: POST * **Content-Type**: application/json * **Timeout**: 10 seconds * **Retry Policy**: Up to 3 attempts with exponential backoff ## Request Format ### Success Callback When the replacement task completes successfully: ```json theme={null} { "code": 200, "msg": "All generated successfully.", "data": { "callbackType": "complete", "task_id": "2fac****9f72", "data": [ { "id": "e231****-****-****-****-****8cadc7dc", "audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] The city at night is ablaze with lights.", "model_name": "chirp-v4-5", "title": "Iron Man", "createTime": 1786343609818, "duration": 198.44, "tags": "electrifying, rock", "source_audio_url":"https://example.cn/****.jpeg", "source_image_url":"https://example.cn/****.mp3", "source_stream_audio_url":"https://example.cn/****" }, { "id": "e231****-****-****-****-****8cadc7dc", "audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] The city at night is ablaze with lights.", "model_name": "chirp-v4-5", "title": "Iron Man", "createTime": 1786343609818, "duration": 198.44, "tags": "electrifying, rock", "source_audio_url":"https://example.cn/****.jpeg", "source_image_url":"https://example.cn/****.mp3", "source_stream_audio_url":"https://example.cn/****" } ] } } ``` ### Failure Callback When the replacement task fails: ```json theme={null} { "code": 501, "msg": "Audio generation failed.", "data": { "callbackType": "error", "task_id": "2fac****9f72", "error": "Generation failed due to technical issues" } } ``` ## Status Codes | Code | Description | | - | - | | 200 | Success - Task completed successfully | | 400 | Validation error - Parameter validation failed | | 408 | Timeout - Request timeout | | 500 | Server error - Unexpected error occurred | | 501 | Audio generation failed | | 531 | Server error - Generation failed, credits refunded | ## Response Fields ### Success Response Fields Status code indicating the result of the replacement task Status message describing the result Container for callback data Type of callback: `complete` or `error` The task ID for the replacement request Array of replaced music data (only present on success) Unique identifier for the music segment Direct URL to the audio file Streaming URL for the audio URL to the cover image The prompt used for generating the replacement Name of the AI model used Title of the music Style tags for the music Creation timestamp Duration of the audio in seconds Source audio file URL. Source cover image URL. Source streaming audio URL. ## Implementation Examples ### Node.js (Express) ```javascript theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/replace-section-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Replace section callback received:', { code, msg, taskId: data.task_id, callbackType: data.callbackType }); if (code === 200 && data.callbackType === 'complete') { // Handle successful replacement console.log('Replacement completed successfully'); data.data.forEach((music, index) => { console.log(`Music ${index + 1}:`, { id: music.id, title: music.title, duration: music.duration, audioUrl: music.audio_url }); }); } else { // Handle failure console.log('Replacement failed:', msg); } // Always respond with success to acknowledge receipt res.json({ code: 200, msg: 'success' }); }); app.listen(3000, () => { console.log('Callback server running on port 3000'); }); ``` ### Python (Flask) ```python theme={null} from flask import Flask, request, jsonify import logging app = Flask(__name__) logging.basicConfig(level=logging.INFO) @app.route('/replace-section-callback', methods=['POST']) def replace_section_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) logging.info(f"Replace section callback received: code={code}, msg={msg}") if code == 200 and callback_data.get('callbackType') == 'complete': # Handle successful replacement logging.info("Replacement completed successfully") music_data = callback_data.get('data', []) for i, music in enumerate(music_data): logging.info(f"Music {i + 1}: {music.get('title')} - {music.get('duration')}s") else: # Handle failure logging.error(f"Replacement failed: {msg}") # Always respond with success return jsonify({"code": 200, "msg": "success"}) if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ### PHP ```php theme={null} 400, 'msg' => 'Invalid JSON']); exit; } $code = $data['code'] ?? null; $msg = $data['msg'] ?? ''; $callbackData = $data['data'] ?? []; error_log("Replace section callback received: code=$code, msg=$msg"); if ($code === 200 && ($callbackData['callbackType'] ?? '') === 'complete') { // Handle successful replacement error_log("Replacement completed successfully"); $musicData = $callbackData['data'] ?? []; foreach ($musicData as $index => $music) { $title = $music['title'] ?? 'Unknown'; $duration = $music['duration'] ?? 0; error_log("Music " . ($index + 1) . ": $title - {$duration}s"); } } else { // Handle failure error_log("Replacement failed: $msg"); } // Always respond with success echo json_encode(['code' => 200, 'msg' => 'success']); ?> ``` ## Callback Security ### Verification Recommendations 1. **IP Whitelist**: Restrict callback endpoints to known IP addresses 2. **HTTPS Only**: Always use HTTPS for callback URLs in production 3. **Request Validation**: Validate the structure and content of callback requests 4. **Timeout Handling**: Implement proper timeout handling for callback processing ### Example Security Implementation ```javascript theme={null} const crypto = require('crypto'); function verifyCallback(req, res, next) { // Verify request structure const { code, msg, data } = req.body; if (typeof code !== 'number' || typeof msg !== 'string' || !data) { return res.status(400).json({ code: 400, msg: 'Invalid callback format' }); } // Verify task ID format const taskId = data.task_id; if (!taskId || !/^[a-f0-9\*]{12}$/.test(taskId)) { return res.status(400).json({ code: 400, msg: 'Invalid task ID' }); } next(); } app.post('/replace-section-callback', verifyCallback, (req, res) => { // Process verified callback // ... callback handling logic }); ``` ## Troubleshooting ### Common Issues **Q: Callbacks are not being received** * Verify your callback URL is publicly accessible * Check that your server is responding within 10 seconds * Ensure your endpoint accepts POST requests with JSON content **Q: Receiving duplicate callbacks** * This can happen due to network issues or timeouts * Implement idempotency using the task\_id to handle duplicates **Q: Callback data is missing or incomplete** * Check the `callbackType` field to understand the callback stage * For error callbacks, check the error message for details **Q: How to handle callback failures?** * Always return a 200 status code to acknowledge receipt * Use the [Get Music Details](/suno-api/get-music-generation-details) endpoint to poll task status as a fallback ### Best Practices 1. **Always Acknowledge**: Return HTTP 200 even if your processing fails 2. **Implement Retry Logic**: Handle temporary failures gracefully 3. **Log Everything**: Keep detailed logs for debugging 4. **Use Fallback Polling**: Don't rely solely on callbacks for critical workflows 5. **Validate Data**: Always validate callback data before processing # Vocal and Instrument Separation Source: https://docs.api.box/suno-api/separate-vocals-from-music suno-api/suno-api.json POST /api/v1/vocal-removal/generate Use advanced audio processing technology to separate music into vocal, instrumental, and individual instrument tracks. ### Usage Guide * Separate a platform‑generated mix into vocal, instrumental, and individual instrument components. * Three processing modes are available: * `separate_vocal` — 2‑stem split (Vocals + Instrumental) * `split_stem` — up to 12‑stem split * `split_stem_advanced` — advanced multi‑stem separation with specific instrument selection * Ideal for karaoke creation, remixes, sample extraction, or detailed post‑production. * Best results on professionally mixed AI tracks with clear vocal and instrumental layers. * **Billing notice:** Each call consumes credits; **re‑calling the same track is charged again** (no server‑side caching). * **Pricing:** Check current per‑call credit costs at [**https://api.box/billing**](https://api.box/billing). ### Separation Mode Details | **Mode (type)** | **Stems Returned** | **Typical Use** | **Credit Cost** | | :- | :- | :- | :- | | `separate_vocal` *(default)* | **2 stems** – Vocals + Instrumental | Quick vocal removal, karaoke, basic remixes | **10 Credits** | | `split_stem` | **Up to 12 stems** – Vocals, Backing Vocals, Drums, Bass, Guitar, Keyboard, Strings, Brass, Woodwinds, Percussion, Synth, FX/Other | Advanced mixing, remixing, sound design | **50 Credits** | | `split_stem_advanced` | **Specified instrument stems** — extract specific instruments via `stemName` | Precise instrument extraction, professional post‑production | **20 Credits** | ### Parameter Reference | **Name** | **Type** | **Required** | **Description** | | :- | :- | :- | :- | | `taskId` | string | Conditional | Unique identifier of the music generation task. Should be the taskId returned by the "Generate Music" or "Extend Music" endpoint. **Required when using existing audio.** | | `audioUrl` | string | Conditional | URL of the audio file uploaded by the user. The maximum file size is 20MB. **Required when using user-uploaded audio.** Cannot be used together with `audioId`. | | `audioId` | string | Conditional | Unique identifier of the specific audio track to process. This ID is returned in the callback data after music generation completes. **Required when using existing audio.** Cannot be used together with `audioUrl`. | | `type` | string | Optional | Separation type: `separate_vocal` (default), `split_stem`, or `split_stem_advanced` | | `stemName` | string | Conditional | Only used when `type` is `split_stem_advanced`, specifies the name of the specific track/instrument to separate. Supported instruments include: Lead Vocal, Drum Kit, Piano, Guitar, Bass, Synth, Percussion, etc. | | `callBackUrl` | string | Required | URL for receiving vocal separation task completion updates | ### Developer Notes * All returned audio-file URLs remain accessible for **14 days**. * Separation quality depends on the complexity and mixing of the original track. * `separate_vocal` returns **2 stems** — vocals + instrumental. * `split_stem` returns **up to 12 independent stems** — vocals, backing vocals, drums, bass, guitar, keyboard, strings, brass, woodwinds, percussion, synth, FX/other. * `split_stem_advanced` returns independent stems for specified instruments. Use the `stemName` parameter to specify the instrument name. * **Billing:** Every request is charged. Re‑submitting the same track triggers **a new credit deduction** (no server‑side caching). # Audio Separation Callbacks Source: https://docs.api.box/suno-api/separate-vocals-from-music-callbacks When vocal and instrument separation generation is complete, the system will call this callback to notify the results. When you submit a task to the vocal and instrument separation API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. The callback data structure varies based on the `type` parameter specified in the request. ### Callback Timing The system will send callback notifications in the following situations: * Vocal separation completed * Vocal separation task failed * Error occurred during task processing Vocal separation has only one callback stage, but different numbers of separated audio file URLs are provided based on the separation type (`separate_vocal` or `split_stem`) ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl` in the following format. The callback data structure varies based on the requested `type` parameter: ```json separate_vocal Type Callback theme={null} { "code": 200, "msg": "vocal Removal generated successfully.", "data": { "task_id": "3e63b4cc88d52611159371f6af5571e7", "vocal_removal_info": { "instrumental_url": "https://file.aiquickdraw.com/s/d92a13bf-c6f4-4ade-bb47-f69738435528_Instrumental.mp3", "origin_url": "", "vocal_url": "https://file.aiquickdraw.com/s/3d7021c9-fa8b-4eda-91d1-3b9297ddb172_Vocals.mp3" } } } ``` ```json split_stem Type Callback theme={null} { "code": 200, "msg": "vocal Removal generated successfully.", "data": { "task_id": "e649edb7abfd759285bd41a47a634b10", "vocal_removal_info": { "origin_url": "", "backing_vocals_url": "https://file.aiquickdraw.com/s/aadc51a3-4c88-4c8e-a4c8-e867c539673d_Backing_Vocals.mp3", "bass_url": "https://file.aiquickdraw.com/s/a3c2da5a-b364-4422-adb5-2692b9c26d33_Bass.mp3", "brass_url": "https://file.aiquickdraw.com/s/334b2d23-0c65-4a04-92c7-22f828afdd44_Brass.mp3", "drums_url": "https://file.aiquickdraw.com/s/ac75c5ea-ac77-4ad2-b7d9-66e140b78e44_Drums.mp3", "fx_url": "https://file.aiquickdraw.com/s/a8822c73-6629-4089-8f2a-d19f41f0007d_FX.mp3", "guitar_url": "https://file.aiquickdraw.com/s/064dd08e-d5d2-4201-9058-c5c40fb695b4_Guitar.mp3", "keyboard_url": "https://file.aiquickdraw.com/s/adc934e0-df7d-45da-8220-1dba160d74e0_Keyboard.mp3", "percussion_url": "https://file.aiquickdraw.com/s/0f70884d-047c-41f1-a6d0-7044618b7dc6_Percussion.mp3", "strings_url": "https://file.aiquickdraw.com/s/49829425-a5b0-424e-857a-75d4c63a426b_Strings.mp3", "synth_url": "https://file.aiquickdraw.com/s/56b2d94a-eb92-4d21-bc43-3460de0c8348_Synth.mp3", "vocal_url": "https://file.aiquickdraw.com/s/07420749-29a2-4054-9b62-e6a6f8b90ccb_Vocals.mp3", "woodwinds_url": "https://file.aiquickdraw.com/s/d81545b1-6f94-4388-9785-1aaa6ecabb02_Woodwinds.mp3" } } } ``` ```json split_stem_advanced Type Callback theme={null} { "code": 200, "msg": "vocal Removal generated successfully.", "data": { "task_id": "7220be2955295dda60de46ec6e4ead4c", "vocal_removal_info": { "origin_data": [ { "extract": { "duration": 194.92, "audio_url": "https://tempfile.aiquickdraw.com/r/eb7d0f18-8349-4735-a65e-1812705d5ddf_Lead Vocal.mp3", "stem_type_group_name": "Lead Vocal", "id": "eb7d0f18-8349-4735-a65e-1812705d5ddf" }, "remove": { "duration": 194.92, "audio_url": "https://tempfile.aiquickdraw.com/r/706d32df-e988-412e-bce4-42c9302e5478_Lead Vocal.mp3", "stem_type_group_name": "Lead Vocal", "id": "706d32df-e988-412e-bce4-42c9302e5478" } }, { "extract": { "duration": 194.92, "audio_url": "https://tempfile.aiquickdraw.com/r/a7c503f6-1265-4f7e-bf5d-c50fb3b07238_Lead Vocal.mp3", "stem_type_group_name": "Lead Vocal", "id": "a7c503f6-1265-4f7e-bf5d-c50fb3b07238" }, "remove": { "duration": 194.92, "audio_url": "https://tempfile.aiquickdraw.com/r/a3a0c954-1980-410f-9b34-8539b8eb23f8_Lead Vocal.mp3", "stem_type_group_name": "Lead Vocal", "id": "a3a0c954-1980-410f-9b34-8539b8eb23f8" } } ] } } } ``` ```json Vocal Separation Failed Callback theme={null} { "code": 400, "msg": "Vocal separation failed, invalid source audio", "data": { "task_id": "5e72d367bdfbe44785e28d72cb1697c7", "vocal_removal_info": null } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Vocal separation completed | | 400 | Bad Request - Invalid source audio or parameter error | | 401 | Unauthorized - Invalid API key | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Task ID, consistent with the taskId returned when you submitted the task Vocal separation result information, returned on success. Fields vary based on separation type ### separate\_vocal Type Fields Original audio file URL Separated vocal audio file URL Separated instrumental audio file URL (no vocals) ### split\_stem Type Fields Original audio file URL Separated vocal audio file URL Separated backing vocals audio file URL Separated drums audio file URL Separated bass audio file URL Separated guitar audio file URL Separated keyboard audio file URL Separated percussion instruments audio file URL Separated string instruments audio file URL Separated synthesizer audio file URL Separated sound effects audio file URL Separated brass instruments audio file URL Separated woodwind instruments audio file URL ### split\_stem\_advanced Type Fields An array of separation results for the original audio, containing extraction and removal information for multiple stem groups. Each element represents an independent stem group (e.g., Lead Vocal). Information about the extracted target stem (isolates this stem while removing others). The duration of the extracted audio, in seconds. The download URL of the extracted target stem audio file. The stem type group name (e.g., Lead Vocal), indicating which type of stem this group extracts. The unique identifier for the extracted audio. Information about the remaining audio after removing the target stem (removes this stem while keeping others). The duration of the audio after removal, in seconds. The download URL of the remaining audio file after the target stem has been removed. The stem type group name (e.g., Lead Vocal), consistent with the corresponding extract entry. The unique identifier for the remaining audio. ## Callback Reception Examples Here are example codes for receiving callbacks in various popular programming languages, supporting both separation types: ```javascript theme={null} const express = require('express'); const fs = require('fs'); const https = require('https'); const app = express(); app.use(express.json()); app.post('/vocal-separation-callback', (req, res) => { const { code, msg, data } = req.body; console.log('Received vocal separation callback:', { taskId: data.task_id, status: code, message: msg }); if (code === 200 && data.vocal_removal_info) { // Vocal separation successful const vocalInfo = data.vocal_removal_info; console.log('Vocal separation completed successfully'); // Determine separation type and download corresponding files let audioTypes = []; if (vocalInfo.instrumental_url) { // separate_vocal type audioTypes = [ { name: 'original', url: vocalInfo.origin_url }, { name: 'vocal', url: vocalInfo.vocal_url }, { name: 'instrumental', url: vocalInfo.instrumental_url } ]; } else { // split_stem type audioTypes = [ { name: 'original', url: vocalInfo.origin_url }, { name: 'vocal', url: vocalInfo.vocal_url }, { name: 'backing_vocals', url: vocalInfo.backing_vocals_url }, { name: 'drums', url: vocalInfo.drums_url }, { name: 'bass', url: vocalInfo.bass_url }, { name: 'guitar', url: vocalInfo.guitar_url }, { name: 'keyboard', url: vocalInfo.keyboard_url }, { name: 'percussion', url: vocalInfo.percussion_url }, { name: 'strings', url: vocalInfo.strings_url }, { name: 'synth', url: vocalInfo.synth_url }, { name: 'fx', url: vocalInfo.fx_url }, { name: 'brass', url: vocalInfo.brass_url }, { name: 'woodwinds', url: vocalInfo.woodwinds_url } ]; } // Download all separated audio files audioTypes.forEach(audio => { if (audio.url) { const filename = `${data.task_id}_${audio.name}.mp3`; const file = fs.createWriteStream(filename); https.get(audio.url, (response) => { response.pipe(file); file.on('finish', () => { file.close(); console.log(`${audio.name} audio downloaded as ${filename}`); }); }).on('error', (err) => { console.error(`${audio.name} audio download failed:`, err.message); }); } }); } else { // Task failed console.log('Vocal separation failed:', msg); // Handle failure cases... if (code === 400) { console.log('Invalid source audio or parameter error'); } else if (code === 429) { console.log('Insufficient credits'); } else if (code === 500) { console.log('Server internal error'); } } // Return 200 status code to confirm callback received res.status(200).json({ status: 'received' }); }); app.listen(3000, () => { console.log('Vocal separation callback server running on port 3000'); }); ``` ```python theme={null} from flask import Flask, request, jsonify import requests import os app = Flask(__name__) @app.route('/vocal-separation-callback', methods=['POST']) def handle_callback(): data = request.json code = data.get('code') msg = data.get('msg') callback_data = data.get('data', {}) task_id = callback_data.get('task_id') vocal_info = callback_data.get('vocal_removal_info') print(f"Received vocal separation callback: {task_id}, Status: {code}") if code == 200 and vocal_info: # Vocal separation successful print("Vocal separation completed successfully") # Determine separation type based on callback content if vocal_info.get('instrumental_url'): # separate_vocal type audio_types = [ ('original', vocal_info.get('origin_url')), ('vocal', vocal_info.get('vocal_url')), ('instrumental', vocal_info.get('instrumental_url')) ] else: # split_stem type audio_types = [ ('original', vocal_info.get('origin_url')), ('vocal', vocal_info.get('vocal_url')), ('backing_vocals', vocal_info.get('backing_vocals_url')), ('drums', vocal_info.get('drums_url')), ('bass', vocal_info.get('bass_url')), ('guitar', vocal_info.get('guitar_url')), ('keyboard', vocal_info.get('keyboard_url')), ('percussion', vocal_info.get('percussion_url')), ('strings', vocal_info.get('strings_url')), ('synth', vocal_info.get('synth_url')), ('fx', vocal_info.get('fx_url')), ('brass', vocal_info.get('brass_url')), ('woodwinds', vocal_info.get('woodwinds_url')) ] # Download all separated audio files for audio_name, audio_url in audio_types: if audio_url: try: response = requests.get(audio_url) if response.status_code == 200: filename = f"{task_id}_{audio_name}.mp3" with open(filename, "wb") as f: f.write(response.content) # Check file size file_size = os.path.getsize(filename) print(f"{audio_name} audio downloaded as {filename}, size: {file_size} bytes") except Exception as e: print(f"{audio_name} audio download failed: {e}") else: # Task failed print(f"Vocal separation failed: {msg}") # Handle failure cases... if code == 400: print("Invalid source audio or parameter error") elif code == 429: print("Insufficient credits") elif code == 500: print("Server internal error") # Return 200 status code to confirm callback received return jsonify({'status': 'received'}), 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=3000) ``` ```php theme={null} $vocalInfo['origin_url'] ?? '', 'vocal' => $vocalInfo['vocal_url'] ?? '', 'instrumental' => $vocalInfo['instrumental_url'] ?? '' ]; } else { // split_stem type $audioTypes = [ 'original' => $vocalInfo['origin_url'] ?? '', 'vocal' => $vocalInfo['vocal_url'] ?? '', 'backing_vocals' => $vocalInfo['backing_vocals_url'] ?? '', 'drums' => $vocalInfo['drums_url'] ?? '', 'bass' => $vocalInfo['bass_url'] ?? '', 'guitar' => $vocalInfo['guitar_url'] ?? '', 'keyboard' => $vocalInfo['keyboard_url'] ?? '', 'percussion' => $vocalInfo['percussion_url'] ?? '', 'strings' => $vocalInfo['strings_url'] ?? '', 'synth' => $vocalInfo['synth_url'] ?? '', 'fx' => $vocalInfo['fx_url'] ?? '', 'brass' => $vocalInfo['brass_url'] ?? '', 'woodwinds' => $vocalInfo['woodwinds_url'] ?? '' ]; } // Download all separated audio files foreach ($audioTypes as $audioName => $audioUrl) { if ($audioUrl) { try { $audioContent = file_get_contents($audioUrl); if ($audioContent !== false) { $filename = "{$taskId}_{$audioName}.mp3"; file_put_contents($filename, $audioContent); // Check file size $fileSize = filesize($filename); error_log("$audioName audio downloaded as $filename, size: $fileSize bytes"); } } catch (Exception $e) { error_log("$audioName audio download failed: " . $e->getMessage()); } } } } else { // Task failed error_log("Vocal separation failed: $msg"); // Handle failure cases... if ($code === 400) { error_log("Invalid source audio or parameter error"); } elseif ($code === 429) { error_log("Insufficient credits"); } elseif ($code === 500) { error_log("Server internal error"); } } // Return 200 status code to confirm callback received http_response_code(200); echo json_encode(['status' => 'received']); ?> ``` ## Best Practices ### Vocal Separation Callback Configuration 1. **Multi-track Management**: Organize separated tracks with clear naming conventions 2. **Quality Assessment**: Verify separation quality for each track type 3. **Storage Organization**: Create folder structures for different separation projects 4. **Batch Processing**: Implement efficient batch downloads for multiple tracks 5. **Track Analysis**: Analyze separated tracks for remix and production purposes 6. **Backup Strategy**: Maintain backups of both original and separated tracks ### Separation-Specific Considerations * Separation quality depends on the complexity of the original mix * Some instruments may not separate cleanly in all cases * Vocal separation works best with clear, well-mixed source material * Multiple separated files require significant storage space * Processing time varies based on track length and complexity ## Troubleshooting Common issues specific to vocal separation callbacks: * Verify the source audio quality and mixing * Check if the original track has clear instrument separation * Consider the complexity of the musical arrangement * Test with different source materials to understand limitations * Ensure stable network connection for multiple large file downloads * Implement error handling for partial download failures * Verify all track URLs are accessible and not expired * Monitor download progress for all separated tracks * Plan adequate storage for multiple separated track files * Implement consistent naming conventions for track identification * Consider automated organization based on task IDs * Monitor disk space usage for large separation projects ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Vocal Separation Details interface to regularly query separation task status. Recommend querying every 30 seconds. # Suno Voice Check Availability Source: https://docs.api.box/suno-api/suno-voice-check-voice suno-api/suno-voice-api.json POST /api/v1/voice/check-voice Check whether a generated Suno custom voice is available for use. ### Usage Guide * Use this endpoint after the custom voice generation task succeeds. * Submit the related task ID in `task_id`. * If `isAvailable` is `true`, the generated voice is ready for supported Suno generation workflows. ### When to Use Call this endpoint before starting a generation request that depends on a custom voice. It helps avoid submitting downstream tasks while the voice is still unavailable. ### Related Endpoint Query the latest task status and generated voice information before checking availability # Suno Voice Create Custom Voice Source: https://docs.api.box/suno-api/suno-voice-generate suno-api/suno-voice-api.json POST /api/v1/voice/generate Generate a reusable Suno custom voice from the user's verification recording. ### Usage Guide * Call this API after the validation phrase is generated and the user has recorded the verification audio. * The validation phrase is the `validateInfo` text returned by the server. For best voice generation results, have the user record the server-provided phrase in a singing voice rather than plain speech. * Submit the original validation `taskId` and the verification audio URL in `verifyUrl`. * Optional metadata such as `voiceName`, `description`, `style`, and `singerSkillLevel` helps organize and tune the generated voice. * The API returns a `taskId`; use it to query the final `voiceId`. * When `callBackUrl` is provided, the system sends a POST callback when the voice is created or the task fails. The callback URL must be publicly accessible and return HTTP 200 within 15 seconds. ### Workflow 1. Generate and retrieve the validation phrase. 2. Record clear verification audio for the phrase; singing is recommended for best voice generation results. 3. Upload or host the verification audio and pass the URL as `verifyUrl`. 4. Submit the voice generation task and store the returned `taskId`. 5. Receive `voiceId` through the record query API or callback when the task succeeds. ### Callback Learn the callback payload sent when the custom voice is created or the task fails ### Developer Notes * `taskId` must come from the validation phrase task for the same voice workflow. * `verifyUrl` should point to the user's recording of the exact validation phrase returned by the server; for best results, recording it in a singing voice is recommended. * After receiving `voiceId`, use the availability check endpoint before starting generation workflows that depend on the custom voice. # Suno Voice Generation Callbacks Source: https://docs.api.box/suno-api/suno-voice-generate-callbacks Receive POST callbacks when a Suno Voice custom voice task succeeds or fails. When you submit a custom voice generation task with `callBackUrl`, the system sends a POST request to your callback URL when the task completes. ## Callback Mechanism Overview The callback contains the generated `voiceId` when custom voice creation succeeds. ### Callback Timing * Custom voice created successfully * Voice verification or creation failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format ```json Custom Voice Ready Callback theme={null} { "code": 200, "msg": "success", "data": { "taskId": "xxx_task_id_xxx", "voiceId": "voice_xxx", "status": "success", "errorCode": 0, "errorMessage": "" } } ``` ```json Custom Voice Failed Callback theme={null} { "code": 400, "msg": "Voice generation failed", "data": { "taskId": "xxx_task_id_xxx", "voiceId": "", "status": "fail", "errorCode": 500, "errorMessage": "Verification audio did not match the validation phrase" } } ``` ## Field Description Callback status code. `200` indicates success; non-200 values indicate task failure or processing error. Status message describing the callback result. Task ID returned by the custom voice generation API. Generated custom voice ID. Returned when `status` is `success`. Task status. Common callback statuses are `success`, `processing_validate_fail`, and `fail`. Error code returned when the task fails. Detailed error message returned when the task fails. ## Receiving Callbacks ```javascript Node.js theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/suno/voice-generate-callback', (req, res) => { const { code, msg, data } = req.body; if (code === 200 && data.status === 'success') { console.log('Custom voice ready:', data.voiceId); } else { console.error('Custom voice task failed:', msg, data.errorMessage); } res.status(200).json({ status: 'received' }); }); app.listen(3000); ``` ## Related Endpoint Query the same voice generation task manually with taskId # Suno Voice Get Custom Voice Record Source: https://docs.api.box/suno-api/suno-voice-record-info suno-api/suno-voice-api.json GET /api/v1/voice/record-info Query the custom Suno Voice generation result and obtain the generated voiceId. ### Usage Guide * Use the `taskId` returned by the custom voice generation API. * When `status` is `success`, the response contains the generated `voiceId`. * If the task fails, use `errorCode` and `errorMessage` to decide whether to retry validation or generation. ### Status Handling | Status | Meaning | | - | - | | `wait_processing` | Task is waiting to be processed | | `processing_validate` | Verification is being processed | | `processing_validate_fail` | Verification failed | | `wait_validating` | Waiting for validation to complete | | `success` | Voice is ready and `voiceId` can be used | | `fail` | Task failed | ### Related Endpoint Confirm whether the generated custom voice is available for supported Suno generation APIs # Suno Voice Regenerate Verification Phrase Source: https://docs.api.box/suno-api/suno-voice-regenerate suno-api/suno-voice-api.json POST /api/v1/voice/regenerate Regenerate the validation phrase for an existing Suno Voice task. ### Usage Guide * Use this API when the previous validation phrase failed, expired, or the user needs a new phrase. * Submit the existing `taskId` from the voice validation workflow. * The API schema uses `calBackUrl` for the callback URL field. The system sends a POST callback when the regenerated phrase is ready or the task fails. The callback URL must be publicly accessible and return HTTP 200 within 15 seconds. * Query the validation phrase result again with the returned `taskId`. ### Workflow 1. Submit the existing validation task ID. 2. Store the returned `taskId`. 3. Wait for the regenerated `validateInfo` through the query API or callback. 4. Ask the user to record the new phrase and submit the verification audio to the voice generation API. For best voice generation results, singing is recommended. ### Callback Learn the callback payload sent when the regenerated phrase is ready or the task fails ### Developer Notes * Keep the regenerated phrase and verification recording paired with the same task flow. * If phrase generation repeatedly fails, choose a cleaner source vocal segment and restart the validation step. # Suno Voice Regenerate Phrase Callbacks Source: https://docs.api.box/suno-api/suno-voice-regenerate-callbacks Receive POST callbacks when a regenerated Suno Voice validation phrase is ready or fails. When you submit a phrase regeneration task, provide the callback URL using the `calBackUrl` field from the API schema. The system sends a POST request when the regenerated phrase is ready or the task fails. ## Callback Mechanism Overview The regenerated phrase callback uses the same response shape as validation phrase generation callbacks. ### Callback Timing * New validation phrase generated and ready for the user to record * Phrase regeneration failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format ```json Regenerated Phrase Ready Callback theme={null} { "code": 200, "msg": "success", "data": { "taskId": "xxx_task_id_xxx", "validateInfo": "Please record this new validation phrase clearly.", "status": "wait_validating", "errorCode": 0, "errorMessage": "" } } ``` ```json Regenerated Phrase Failed Callback theme={null} { "code": 400, "msg": "Validation phrase regeneration failed", "data": { "taskId": "xxx_task_id_xxx", "validateInfo": "", "status": "processing_validate_fail", "errorCode": 500, "errorMessage": "Failed to regenerate validation phrase" } } ``` ## Field Description Callback status code. `200` indicates success; non-200 values indicate task failure or processing error. Status message describing the callback result. Task ID returned by the phrase regeneration API. Regenerated validation phrase text. Returned when `status` is `wait_validating`. Task status. Common callback statuses are `wait_validating`, `processing_validate_fail`, and `fail`. Error code returned when the task fails. Detailed error message returned when the task fails. ## Related Endpoint Query the regenerated phrase manually with taskId # Suno Voice Generate Verification Phrase Source: https://docs.api.box/suno-api/suno-voice-validate suno-api/suno-voice-api.json POST /api/v1/voice/validate Generate the validation phrase required for the Suno Voice custom voice workflow. ### Usage Guide * Submit the source recording URL and the vocal segment you want to use for voice creation. * The API returns a `taskId`; use it to query the generated validation phrase. * When `callBackUrl` is provided, the system sends a POST callback when the phrase is ready or the task fails. The callback URL must be publicly accessible and return HTTP 200 within 15 seconds. * After receiving `validateInfo`, ask the user to record the phrase and upload the verification audio to the voice generation API. For best voice generation results, singing is recommended. ### Workflow 1. Upload or host the source audio and make sure `voiceUrl` is publicly accessible. 2. Choose a clean vocal segment with `vocalStartS` and `vocalEndS`. 3. Submit the validation phrase task and store the returned `taskId`. 4. Wait for `validateInfo` through the query API or callback. 5. Record the user performing the validation phrase, then call the custom voice generation API. For best voice generation results, singing is recommended. ### Callback Learn the callback payload sent when the validation phrase is ready or the task fails ### Developer Notes * `vocalEndS` must be greater than `vocalStartS`. * Use a segment with clear speech and minimal background noise for better validation. * `language` controls the validation phrase language. Supported values include `en`, `zh`, `es`, `fr`, `pt`, `de`, `ja`, `ko`, `hi`, and `ru`. # Suno Voice Validation Phrase Callbacks Source: https://docs.api.box/suno-api/suno-voice-validate-callbacks Receive POST callbacks when a Suno Voice validation phrase task is ready or fails. When you submit a validation phrase task with `callBackUrl`, the system sends a POST request to your callback URL after the validation phrase task reaches a terminal state. ## Callback Mechanism Overview Use callbacks in production to avoid polling the validation phrase query endpoint. ### Callback Timing * Validation phrase generated and ready for the user to record * Validation phrase generation failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format ```json Validation Phrase Ready Callback theme={null} { "code": 200, "msg": "success", "data": { "taskId": "xxx_task_id_xxx", "validateInfo": "Please record this validation phrase clearly.", "status": "wait_validating", "errorCode": 0, "errorMessage": "" } } ``` ```json Validation Phrase Failed Callback theme={null} { "code": 400, "msg": "Validation phrase generation failed", "data": { "taskId": "xxx_task_id_xxx", "validateInfo": "", "status": "processing_validate_fail", "errorCode": 500, "errorMessage": "Failed to generate validation phrase" } } ``` ## Field Description Callback status code. `200` indicates success; non-200 values indicate task failure or processing error. Status message describing the callback result. Task ID returned by the validation phrase generation API. Validation phrase text. Returned when `status` is `wait_validating`. Task status. Common callback statuses are `wait_validating`, `processing_validate_fail`, and `fail`. Error code returned when the task fails. Detailed error message returned when the task fails. ## Receiving Callbacks ```javascript Node.js theme={null} const express = require('express'); const app = express(); app.use(express.json()); app.post('/suno/voice-validate-callback', (req, res) => { const { code, msg, data } = req.body; if (code === 200 && data.status === 'wait_validating') { console.log('Validation phrase ready:', data.taskId, data.validateInfo); } else { console.error('Validation phrase task failed:', msg, data.errorMessage); } res.status(200).json({ status: 'received' }); }); app.listen(3000); ``` ## Related Endpoint Query the same task status manually with taskId # Suno Voice Get Verification Phrase Source: https://docs.api.box/suno-api/suno-voice-validate-info suno-api/suno-voice-api.json GET /api/v1/voice/validate-info Query the validation phrase generation result for a Suno Voice task. ### Usage Guide * Use the `taskId` returned by the validation phrase generation or regeneration API. * When the task reaches `wait_validating`, read `validateInfo` and ask the user to record that phrase. * If the task fails, inspect `errorCode` and `errorMessage` before retrying. ### Status Handling | Status | Meaning | | - | - | | `wait_processing` | Task is waiting to be processed | | `processing_validate` | Validation phrase is being generated | | `processing_validate_fail` | Validation phrase generation failed | | `wait_validating` | Phrase is ready and waiting for user verification | | `success` | The full voice creation flow has completed | | `fail` | Task failed | ### Next Step Submit the verification audio and create the final custom voice # Upload And Cover Audio Source: https://docs.api.box/suno-api/upload-and-cover-audio suno-api/suno-api.json POST /api/v1/generate/upload-cover This API covers an audio track by transforming it into a new style while retaining its core melody. It incorporates Suno's upload capability, enabling users to upload an audio file for processing. The expected result is a refreshed audio track with a new style, keeping the original melody intact. ### Model Versions * **Current models**: `V6` (default), `V6_WILD`, `V6_MINI` * **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4` * Deprecated values remain available only for backward compatibility. New integrations should use a V6-series model. ### Parameter Usage Guide * This endpoint always uses custom parameters. Simple mode is not available. * Source audio (`uploadUrl`) is enough to generate. `lyrics`, `prompt`, `style`, and `title` are optional. * instrumental (boolean, optional) determines whether to generate instrumental music and defaults to false. * If instrumental is true: generate instrumental music. `prompt` and `lyrics` do not need to be provided. * If instrumental is false: use `lyrics` as the lyrics when provided; otherwise use `prompt`. Both are optional. * `prompt` is optional and is treated as lyrics. When `lyrics` is also provided, `lyrics` takes priority and `prompt` is not used as lyrics. * `lyrics` is optional. It takes priority over `prompt` as the lyrics. If `lyrics` is omitted, `prompt` is used as the lyrics. * **Character limits (based on model):** * **V4 model (Deprecated)**: prompt max 3000 characters, style max 200 characters, title max 80 characters * **V4\_5, V4\_5PLUS, V5, V5\_5 & V4\_5ALL models (Deprecated)**: prompt max 5000 characters, style max 1000 characters; title max 80 characters for V4\_5ALL, otherwise max 100 characters * **V6, V6\_WILD & V6\_MINI models**: prompt and lyrics max 5000 characters, style max 1000 characters, title max 80 characters * **model** (string, required): `V6`, `V6_WILD`, `V6_MINI`. Deprecated: `V4_5ALL`, `V4`, `V4_5`, `V4_5PLUS`, `V5`, `V5_5`. * uploadUrl is the source audio URL, required; ensure the uploaded audio does not exceed 8 minutes in length. ### Optional parameters The following fields are optional controls available for this endpoint: * lyrics (string): Lyrics for the cover. Optional. Takes priority over `prompt`. If omitted, `prompt` is used as the lyrics. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters. * vocalGender (string): Preferred vocal gender. Allowed values: `m` (male), `f` (female) * styleWeight (number): Style adherence weight in range 0–1 (recommended two decimals) * weirdnessConstraint (number): Creativity/novelty constraint in range 0–1 (recommended two decimals) * audioWeight (number): Relative weight of audio consistency in range 0–1 (recommended two decimals) * variety (integer): Diversity of generated results. Integer from 0–4, default 1. `0` off, `1` normal (default), `2` high, `3` extra, `4` max. * personaId (string): Persona ID or Suno Voice `voiceId` to apply to the generated music. If you use a Voice-generated ID, set `personaModel` to `voice_persona`. * personaModel (string): Persona type. Use `style_persona` for Generate Persona IDs, or `voice_persona` for Suno Voice IDs. ```json JSON body theme={null} { "instrumental": false, "lyrics": "[Chorus] Brighter lights, we keep going on", "prompt": "[Verse] City hums under neon rain", "style": "Cinematic", "title": "Dark Reprise", "uploadUrl": "https://storage.example.com/upload", "model": "V6", "callBackUrl": "https://example.com/callback", "vocalGender": "m", "styleWeight": 0.61, "weirdnessConstraint": 0.72, "audioWeight": 0.65, "variety": 1 } ``` ### Developer Notes 1. Recommended settings for new users: Set instrumental to false and provide only uploadUrl. This is the simplest configuration to quickly test the API and experience the results. 2. Generated files will be deleted after 15 days 3. This endpoint always uses custom parameters; providing the source audio (uploadUrl) is enough to generate 4. Pay attention to character limits for prompt, lyrics, style, and title to ensure successful processing 5. Callback process has three stages: text (text generation complete), first (first track complete), complete (all tracks complete) 6. You can use the Get Music Generation Details endpoint to actively check task status instead of waiting for callbacks 7. The uploadUrl parameter is used to specify the upload location of the audio file; please provide a valid URL. # Upload and Cover Audio Callbacks Source: https://docs.api.box/suno-api/upload-and-cover-audio-callbacks When upload and cover audio tasks are completed, the system will send results to your provided callback URL via POST request When you submit a task to the upload and cover audio API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * Text generation completed (`text` stage) * First covered audio track generated (`first` stage) * All covered audio tracks generated (`complete` stage) * Audio cover task failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When the task is completed, the system will send a POST request to your `callBackUrl` in the following format: ```json Text Generation Complete Callback theme={null} { "code": 200, "msg": "Text generation completed successfully.", "data": { "callbackType": "text", "task_id": "2fac****9f72", "data": [] } } ``` ```json First Track Complete Callback theme={null} { "code": 200, "msg": "First track generated successfully.", "data": { "callbackType": "first", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Night city lights shining bright", "model_name": "chirp-v3-5", "title": "Iron Man (Cover Version)", "tags": "electrifying, rock, cover", "createTime": "2025-01-01 00:00:00", "duration": 198.44 } ] } } ``` ```json All Tracks Complete Callback theme={null} { "code": 200, "msg": "All generated successfully.", "data": { "callbackType": "complete", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Night city lights shining bright", "model_name": "chirp-v3-5", "title": "Iron Man (Cover Version)", "tags": "electrifying, rock, cover", "createTime": "2025-01-01 00:00:00", "duration": 198.44 }, { "id": "bd15****1873", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Night city lights shining bright", "model_name": "chirp-v3-5", "title": "Iron Man (Cover Version)", "tags": "electrifying, rock, cover", "createTime": "2025-01-01 00:00:00", "duration": 228.28 } ] } } ``` ```json Failed Callback theme={null} { "code": 400, "msg": "Failed to cover audio, invalid upload source", "data": { "callbackType": "failed", "task_id": "2fac****9f72", "data": [] } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Audio cover completed | | 400 | Bad Request - Invalid upload source or parameter error | | 401 | Unauthorized - Invalid API key | | 413 | Content Too Long - Prompt or style description exceeds limit | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Callback type indicating the current callback stage: * `text`: Text generation completed * `first`: First covered audio track generated * `complete`: All covered audio tracks generated * `failed`: Task failed Task ID, consistent with the taskId returned when you submitted the task Audio cover result information, returned on success Audio unique identifier (audioId) Covered audio file download link **Deprecated.** Original audio file link returned by Suno. This link expires after a period of time and is no longer maintained — do not rely on it for long-term storage. Use the [Recovery Audio](/suno-api/recovery-audio) endpoint to obtain a fresh playable link. Streaming audio playback link Music cover image link Cover prompt used AI model name used for cover generation Covered music title Music style tags Creation time Covered audio duration (seconds) ## Best Practices ### Audio Cover Callback Configuration 1. **Upload Validation**: Verify that the uploaded audio source is valid and accessible 2. **Style Consistency**: Ensure cover style parameters match your artistic vision 3. **Quality Monitoring**: Implement quality checks for covered audio output 4. **Original Preservation**: Keep track of original upload sources for reference 5. **Version Control**: Maintain version history of different cover attempts 6. **Content Rights**: Ensure you have rights to cover the uploaded audio content ### Cover-Specific Considerations * Cover tasks require a valid uploaded audio file * The uploaded audio should not exceed 8 minutes in length * Cover quality depends on the original upload quality * Style transformation may vary based on source material complexity * Consider copyright implications when covering existing music ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Music Generation Details interface to regularly query cover task status. Recommend querying every 30 seconds. # Upload And Extend Audio Source: https://docs.api.box/suno-api/upload-and-extend-audio suno-api/suno-api.json POST /api/v1/generate/upload-extend This API extends audio tracks while preserving the original style of the audio track. It includes Suno's upload functionality, allowing users to upload audio files for processing. The expected result is a longer track that seamlessly continues the input style. ### Model Versions * **Current models**: `V6` (default), `V6_WILD`, `V6_MINI` * **Deprecated models**: `V5_5`, `V5`, `V4_5PLUS`, `V4_5ALL`, `V4_5`, `V4` * Deprecated values remain available only for backward compatibility. New integrations should use a V6-series model. ### Parameter Usage Guide * This endpoint always uses custom parameters. Simple mode is not available. * Source audio (`uploadUrl`) is enough to generate. `lyrics`, `prompt`, `style`, and `title` are optional. * instrumental (boolean, optional) determines whether to generate instrumental music and defaults to false. * If instrumental is true: generate instrumental music. `prompt`, `lyrics`, and vocalGender do not need to be provided. * If instrumental is false: use `lyrics` as the lyrics when provided; otherwise use `prompt`. Both are optional. vocalGender is optional. * `prompt` is optional and is treated as lyrics. When `lyrics` is also provided, `lyrics` takes priority and `prompt` is not used as lyrics. * `lyrics` is optional. It takes priority over `prompt` as the lyrics. If `lyrics` is omitted, `prompt` is used as the lyrics. * **Character limits (based on model):** * **V4 model (Deprecated)**: prompt max 3000 characters, style max 200 characters, title max 80 characters * **V4\_5, V4\_5PLUS, V5, V5\_5 & V4\_5ALL models (Deprecated)**: prompt max 5000 characters, style max 1000 characters; title max 80 characters for V4\_5ALL, otherwise max 100 characters * **V6, V6\_WILD & V6\_MINI models**: prompt and lyrics max 5000 characters, style max 1000 characters, title max 100 characters * **model** (string, required): `V6`, `V6_WILD`, `V6_MINI`. Deprecated: `V4_5ALL`, `V4`, `V4_5`, `V4_5PLUS`, `V5`, `V5_5`. * continueAt: the time point in seconds from which to start extending (must be greater than 0 and less than the uploaded audio duration). Required. * uploadUrl: source audio URL. Required. Ensure uploaded audio does not exceed 8 minutes. ### Optional parameters The following fields are optional controls available for this endpoint: * lyrics (string): Lyrics for the extension. Optional. Takes priority over `prompt`. If omitted, `prompt` is used as the lyrics. For V6, V6\_WILD, and V6\_MINI: maximum 5000 characters. * vocalGender (string): Optional and not required whether instrumental is true or false. Allowed values: `m` (male), `f` (female). * styleWeight (number): Style adherence weight in range 0–1 (recommended two decimals) * weirdnessConstraint (number): Creativity/novelty constraint in range 0–1 (recommended two decimals) * audioWeight (number): Relative weight of audio consistency in range 0–1 (recommended two decimals) * variety (integer): Diversity of generated results. Integer from 0–4, default 1. `0` off, `1` normal (default), `2` high, `3` extra, `4` max. * personaId (string): Persona ID or Suno Voice `voiceId` to apply to the generated music. If you use a Voice-generated ID, set `personaModel` to `voice_persona`. * personaModel (string): Persona type. Use `style_persona` for Generate Persona IDs, or `voice_persona` for Suno Voice IDs. ```json JSON body theme={null} { "instrumental": false, "lyrics": "[Chorus] Brighter lights, we keep going on", "prompt": "[Verse] City hums under neon rain", "style": "Electropop", "title": "Shimmer (Extended)", "continueAt": 45, "uploadUrl": "https://storage.example.com/upload", "model": "V6", "callBackUrl": "https://example.com/callback", "styleWeight": 0.61, "weirdnessConstraint": 0.72, "audioWeight": 0.65, "variety": 1 } ``` ### Developer Notes 1. Generated files will be retained for 14 days 2. Model version must be consistent with the source music 3. This feature is ideal for creating longer works by extending existing music 4. Pay attention to character limits for prompt, lyrics, style, and title to ensure successful processing 5. uploadUrl is the source audio URL and is enough to generate; provide a valid URL. # Upload and Extend Audio Callbacks Source: https://docs.api.box/suno-api/upload-and-extend-audio-callbacks When upload and extend audio tasks are completed, the system will send results to your provided callback URL via POST request When you submit a task to the upload and extend audio API, you can use the `callBackUrl` parameter to set a callback URL. When the task is completed, the system will automatically push the results to your specified address. ## Callback Mechanism Overview The callback mechanism eliminates the need to poll the API for task status. The system will proactively push task completion results to your server. ### Callback Timing The system will send callback notifications in the following situations: * Text generation completed (`text` stage) * First extended audio track generated (`first` stage) * All extended audio tracks generated (`complete` stage) * Audio extension task failed * Error occurred during task processing ### Callback Method * **HTTP Method**: POST * **Content Type**: application/json * **Timeout**: 15 seconds ## Callback Request Format When a task is completed, the system will send a POST request to your `callBackUrl` in the following format: ```json Text Generation Complete Callback theme={null} { "code": 200, "msg": "Text generation completed successfully.", "data": { "callbackType": "text", "task_id": "2fac****9f72", "data": [] } } ``` ```json First Track Complete Callback theme={null} { "code": 200, "msg": "First track extended successfully.", "data": { "callbackType": "first", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Continue the beautiful melody of the uploaded audio", "model_name": "chirp-v3-5", "title": "Extended Music", "tags": "extended, original style", "createTime": "2025-01-01 00:00:00", "duration": 298.44 } ] } } ``` ```json All Complete Callback theme={null} { "code": 200, "msg": "All extended successfully.", "data": { "callbackType": "complete", "task_id": "2fac****9f72", "data": [ { "id": "8551****662c", "audio_url": "https://example.cn/****.mp3", "source_audio_url": "https://example.cn/****.mp3", "stream_audio_url": "https://example.cn/****", "source_stream_audio_url": "https://example.cn/****", "image_url": "https://example.cn/****.jpeg", "source_image_url": "https://example.cn/****.jpeg", "prompt": "[Verse] Continue the beautiful melody of the uploaded audio", "model_name": "chirp-v3-5", "title": "Extended Music", "tags": "extended, original style", "createTime": "2025-01-01 00:00:00", "duration": 298.44 } ] } } ``` ```json Failed Callback theme={null} { "code": 400, "msg": "Extension failed, uploaded audio file is corrupted", "data": { "callbackType": "failed", "task_id": "2fac****9f72", "data": [] } } ``` ## Status Code Description Callback status code indicating task processing result: | Status Code | Description | | - | - | | 200 | Success - Extension completed | | 400 | Bad Request - Parameter error or invalid audio file | | 401 | Unauthorized - Invalid API key | | 413 | Content Too Long - Audio file too large or duration exceeds limit | | 429 | Insufficient Credits - Account credit balance insufficient | | 500 | Server Error - Please retry later | Status message providing detailed status description Callback type indicating current callback stage: * `text`: Text generation complete * `first`: First extension complete * `complete`: All extensions complete * `failed`: Task failed Task ID, consistent with the taskId returned when you submitted the task Extension result information, returned on success Unique audio identifier (audioId) Extended audio file download link **Deprecated.** Original audio file link returned by Suno. This link expires after a period of time and is no longer maintained — do not rely on it for long-term storage. Use the [Recovery Audio](/suno-api/recovery-audio) endpoint to obtain a fresh playable link. Streaming audio playback link Music cover image link Prompt/lyrics used for extension AI model name used Music title Music style tags Creation time Extended audio duration (seconds) ## Best Practices ### Callback URL Configuration Recommendations 1. **Use HTTPS**: Ensure callback URLs use HTTPS protocol for secure data transmission 2. **Verify Source**: Validate the legitimacy of request sources in callback processing 3. **Idempotent Processing**: The same taskId may receive multiple callbacks, ensure processing logic is idempotent 4. **Quick Response**: Callback processing should return 200 status code quickly to avoid timeout 5. **Asynchronous Processing**: Complex business logic should be processed asynchronously to avoid blocking callback response 6. **Stage-based Processing**: Perform appropriate business processing based on different callback stages 7. **Audio Comparison**: Compare audio duration and quality changes before and after extension 8. **Upload Validation**: Ensure uploaded audio file quality and integrity ### Important Reminders * Callback URL must be a publicly accessible address * Server must respond within 15 seconds, otherwise considered timeout * After 3 consecutive retry failures, the system will stop sending callbacks * Please ensure the stability of callback processing logic to avoid callback failures due to exceptions * Extended audio URLs may have time limits, recommend downloading and saving promptly * Uploaded audio files must not exceed 8 minutes, ensure compliance with limits * Extension function will extend audio length while maintaining original style * Music extension has three stages, each stage will trigger callback notifications ## Troubleshooting If you don't receive callback notifications, please check the following: * Confirm that the callback URL is accessible from the public internet * Check firewall settings to ensure inbound requests are not blocked * Verify that domain name resolution is correct * Ensure the server returns HTTP 200 status code within 15 seconds * Check server logs for error information * Verify that the interface path and HTTP method are correct * Confirm that the upload URL is valid and accessible * Check the uploaded audio file format and quality * Verify that the audio file duration does not exceed the 2-minute limit * Confirm that extension parameters (continueAt, etc.) are set correctly * Understand the differences and processing methods of the three callback stages * text stage: Only indicates text generation complete, no audio data * first stage: First extended music complete, contains data for one track * complete stage: All extended music complete, contains complete music list ## Alternative Solutions If you cannot use the callback mechanism, you can also use polling: Use the Get Music Generation Details interface to regularly query extension task status. Recommend querying every 30 seconds.