The Musicdash Release Automation System provides a comprehensive REST API for managing music submissions, validating artwork and audio files, checking copyright, and automating distribution workflows.
File Validation
Advanced validation for artwork and audio files with platform-specific requirements.
Copyright Detection
Automated copyright checking using PEX to prevent infringement.
Advanced Analysis
Comprehensive artwork analysis with OCR, logo detection, and content filtering.
Automated Notifications
Comprehensive email notifications for all submission status changes.
All API endpoints return JSON responses with consistent error handling and status codes.
https://releases.musicdash.ai
Production Environment: All production traffic should be directed to the base URL above.
Development Environment: For testing and development, use http://localhost:5000.
Most endpoints do not require authentication. For admin endpoints, use Bearer token authentication:
Authorization: Bearer eyJraWQiOiJmVlpnTzZHcHAxUXErVnlpakI1aEMyTEg2NW9ZaGxJM0RlRlhVSXhsZDg0PSIsImFsZyI6IlJTMjU2In0...
Admin endpoints require authentication while public endpoints are accessible without tokens.
Get started with the Musicdash API in three simple steps:
1. Validate a Submission
// Validate a submission from Musicdash
GET /api/submissions/{submission_id}/validate
// Example response
{
"status": "success",
"submission": {
"release_id": "sub_123456",
"status": "approved",
"validation_errors": [],
"artwork_validation": { ... },
"copyright_result": { ... }
}
}
2. Check Artwork Compliance
// Upload and validate artwork
POST /api/artwork/validate
// Form data with file field 'file'
// Example response
{
"is_valid": true,
"validation_result": {
"analysis": { ... },
"platform_results": {
"spotify": { "approved": true, "score": 92.5 },
"apple": { "approved": true, "score": 95.0 }
}
}
}
3. Verify Copyright Status
// Check audio for copyright issues
POST /api/copyright/check
// Form data with file field 'file'
// Example response
{
"has_copyright_issue": false,
"result": {
"has_copyright_issue": false,
"matches": [],
"match_count": 0,
"status": "completed"
}
}
Check API service status, version, and overall system health.
Response
{
"status": "healthy",
"timestamp": "2024-01-15T10:30:00.000Z",
"version": "2.1.0",
"services": {
"database": "connected",
"file_storage": "active",
"copyright_api": "online",
"email_service": "ready"
}
}
Status Codes
200 - Service is healthy and operational
500 - Service is experiencing issues
Validate and process a specific submission by ID from Musicdash. This endpoint performs comprehensive validation including artwork analysis, audio quality checks, and copyright verification.
Path Parameters
| Parameter |
Type |
Description |
| submission_id |
string |
Unique identifier for the submission from Musicdash |
Response
{
"status": "success",
"submission": {
"release_id": "sub_123456",
"status": "approved",
"validation_errors": [],
"artwork_validation": {
"is_valid": true,
"platform_results": {
"spotify": {
"approved": true,
"score": 95.0,
"pass_count": 8,
"fail_count": 0
},
"apple": {
"approved": true,
"score": 92.5,
"pass_count": 9,
"fail_count": 0
}
},
"analysis": {
"width": 3000,
"height": 3000,
"format": "jpeg",
"has_watermark": false,
"has_text": true,
"detected_text": [
{
"text": "Album Title",
"confidence": 85.2
}
]
}
},
"copyright_result": {
"has_copyright_issue": false,
"matches": [],
"match_count": 0,
"status": "completed"
},
"submission_data": {
"title": "Summer Vibes",
"artist": "DJ Producer",
"album": "Beach Sessions",
"genre": "Electronic",
"release_date": "2024-06-01"
},
"user_email": "artist@example.com",
"processing_time": "2024-01-15T10:30:00.000Z"
}
}
Status Codes
200 - Successfully validated submission
404 - Submission not found
500 - Internal server error
Process a batch of submissions from Musicdash. This is optimized for processing multiple submissions efficiently with parallel processing.
Request Body
{
"submission_ids": ["sub_123456", "sub_789012", "sub_345678"]
}
Parameters
| Parameter |
Type |
Description |
| submission_ids |
array |
Array of submission IDs to process |
Response
{
"status": "success",
"message": "Processed 3 submissions",
"processed_submissions": [
{
"release_id": "sub_123456",
"status": "approved",
"validation_errors": [],
"copyright_result": {
"has_copyright_issue": false,
"matches": []
}
},
{
"release_id": "sub_789012",
"status": "validation_failed",
"validation_errors": [
"Artwork resolution too low (800x800px)",
"Audio file contains excessive silence"
]
},
{
"release_id": "sub_345678",
"status": "copyright_issue",
"copyright_result": {
"has_copyright_issue": true,
"matches": [
{
"confidence": 85.5,
"title": "Existing Hit Song",
"artist": "Popular Artist"
}
]
}
}
],
"summary": {
"total": 3,
"approved": 1,
"validation_failed": 1,
"copyright_issue": 1,
"processing_time": "45.2s"
}
}
Status Codes
200 - Successfully processed submissions
400 - Invalid request body
500 - Internal server error
Validate artwork image file with comprehensive analysis including platform-specific requirements, OCR text detection, logo detection, and content filtering.
Request
Method: POST
Content-Type: multipart/form-data
Body: Form data with file field file
Supported Formats
JPEG, JPG, PNG (RGB color space, square aspect ratio)
Response
{
"is_valid": true,
"validation_result": {
"analysis": {
"width": 3000,
"height": 3000,
"format": "jpeg",
"aspect_ratio": 1.0,
"sharpness": 150.5,
"brightness": 120.3,
"contrast": 45.8,
"has_watermark": false,
"has_text": true,
"detected_text": [
{
"text": "Album Title",
"confidence": 85.2
},
{
"text": "Artist Name",
"confidence": 92.1
}
],
"has_logos": false,
"logo_count": 0,
"bad_words_found": false,
"weapon_words_found": false,
"forbidden_text_found": false,
"artist_info_found": true,
"processing_time": 2.45
},
"platform_results": {
"spotify": {
"approved": true,
"score": 92.5,
"pass_count": 8,
"fail_count": 0,
"total_tests": 8
},
"apple": {
"approved": true,
"score": 95.0,
"pass_count": 9,
"fail_count": 0,
"total_tests": 9
}
},
"recommendations": [
{
"priority": "low",
"message": "Consider adding track list information",
"category": "content"
}
],
"eligibility": {
"eligible": true,
"reason": "Artwork meets requirements for all platforms",
"issues": [],
"platform_approvals": {
"spotify": true,
"apple": true
}
}
}
}
Status Codes
200 - Validation completed
400 - Invalid file or no file uploaded
413 - File too large
500 - Internal server error
Validate audio file for quality, format compliance, and technical specifications.
Request
Method: POST
Content-Type: multipart/form-data
Body: Form data with file field file
Supported Formats
WAV, FLAC, MP3, AAC, M4A (16-bit or higher, 44.1kHz or higher)
Response
{
"is_valid": true,
"errors": [],
"analysis": {
"duration": 215.5,
"sample_rate": 44100,
"bit_depth": 16,
"channels": 2,
"format": "wav",
"file_size_mb": 45.2,
"loudness": -14.2,
"dynamic_range": 12.5
}
}
Error Response
{
"is_valid": false,
"errors": [
"Audio duration 15.2s is below minimum 30s",
"Audio contains excessive silence (65%)",
"Sample rate 22050Hz is below minimum 44100Hz"
],
"analysis": {
"duration": 15.2,
"sample_rate": 22050,
"bit_depth": 16,
"channels": 2,
"format": "mp3",
"file_size_mb": 1.2
}
}
Status Codes
200 - Validation completed
400 - Invalid file or no file uploaded
500 - Internal server error
Check audio file for copyright infringement using PEX/ACRCloud audio fingerprinting technology.
Request
Method: POST
Content-Type: multipart/form-data
Body: Form data with file field file
Response
{
"has_copyright_issue": false,
"result": {
"has_copyright_issue": false,
"matches": [],
"match_count": 0,
"status": "completed",
"file_size_mb": 25.8,
"pex_success": true,
"copyright_detected": false,
"query_duration_seconds": 3.2
}
}
Copyright Issue Response
{
"has_copyright_issue": true,
"result": {
"has_copyright_issue": true,
"matches": [
{
"confidence": 85.5,
"title": "Existing Song Title",
"artist": "Popular Artist",
"album": "Chart Album",
"label": "Major Label",
"isrc": "USRC17607839",
"duration_seconds": 215.0,
"dsp_links": [
"https://open.spotify.com/track/...",
"https://music.apple.com/us/album/..."
],
"match_percentage": 85.5
}
],
"match_count": 1,
"status": "completed",
"file_size_mb": 25.8,
"pex_success": true,
"copyright_detected": true,
"query_duration_seconds": 4.1
}
}
Status Codes
200 - Copyright check completed
400 - Invalid file or no file uploaded
500 - Internal server error
Send custom rejection email for a submission with detailed rejection reasons and improvement suggestions.
Headers
Authorization: Bearer {admin_token}
Content-Type: application/json
Query Parameters
| Parameter |
Type |
Description |
| submission_id |
string |
Submission ID to reject |
Request Body
{
"reasons": [
"Artwork quality does not meet platform standards",
"Audio file contains excessive background noise",
"Metadata is incomplete or inaccurate",
"Copyright clearance required for samples used"
],
"additional_notes": [
"Please use higher resolution artwork (min 1400x1400px)",
"Consider re-recording in a professional studio environment",
"Provide complete metadata including ISRC codes if available"
]
}
Response
{
"status": "success",
"message": "Custom rejection email sent successfully to artist@example.com",
"submission_id": "sub_123456",
"user_email": "artist@example.com",
"user_id": "user_789012",
"email_details": {
"subject": "Submission Rejected: sub_123456",
"reasons_count": 4,
"notes_count": 3,
"sent_at": "2024-01-15T10:30:00.000Z"
}
}
Status Codes
200 - Email sent successfully
401 - Unauthorized (invalid or missing token)
400 - Invalid request (missing parameters)
404 - Submission not found
500 - Internal server error
| Status |
Description |
Next Action |
| pending |
Submission is waiting to be processed |
System will process automatically |
| approved |
Submission passed all validations and is ready for distribution |
Proceed with platform distribution |
| validation_failed |
Submission failed file validation checks (artwork or audio) |
Fix issues and resubmit |
| copyright_issue |
Potential copyright infringement detected |
Manual review required |
| processing_error |
Technical error during processing |
System administrator intervention |
All endpoints follow consistent error response format for easy integration and debugging:
{
"status": "error",
"message": "Detailed error description for developers",
"error_code": "VALIDATION_ERROR",
"timestamp": "2024-01-15T10:30:00.000Z",
"request_id": "req_123456789"
}
Common HTTP Status Codes
200 - Success: Request completed successfully
400 - Bad Request: Invalid input parameters or malformed request
401 - Unauthorized: Authentication required or invalid credentials
404 - Not Found: Resource not found
413 - Payload Too Large: File exceeds size limits
500 - Internal Server Error: Unexpected server error
503 - Service Unavailable: Service temporarily unavailable
General Limits
- Maximum File Size: 50MB per request
- Request Timeout: 300 seconds
- Concurrent Uploads: 5 per IP address
Artwork Requirements
- Formats: JPEG, JPG, PNG
- Minimum Size: 640x640px
- Recommended: 1400x1400px to 3000x3000px
- Aspect Ratio: 1:1 (square)
- Color Space: RGB
Audio Requirements
- Formats: WAV, FLAC, MP3, AAC, M4A
- Minimum Duration: 30 seconds
- Sample Rate: 44.1kHz or higher
- Bit Depth: 16-bit or higher
- Maximum Silence: 50% of duration
Content Restrictions
- No watermarks or logos
- No copyrighted material
- No offensive or explicit content
- No URLs or contact information
- No low-quality or blurry images
To ensure fair usage and system stability, the following rate limits are enforced:
| Endpoint Type |
Limit |
Window |
Notes |
| Health & System Status |
60 requests |
per minute |
Per IP address |
| File Validation |
20 requests |
per minute |
Per IP address |
| Submission Processing |
10 requests |
per minute |
Per API key |
| Copyright Checking |
5 requests |
per minute |
Per API key |
| Admin Endpoints |
30 requests |
per minute |
Per admin token |
Rate limit headers are included in all responses:
X-RateLimit-Limit, X-RateLimit-Remaining,
X-RateLimit-Reset
The system automatically sends email notifications for important events. Configure webhooks for real-time integration:
Supported Webhook Events
| Event Type |
Description |
Payload Example |
submission.approved |
Submission passed all validations |
Includes distribution metadata |
submission.rejected |
Submission failed validation |
Includes detailed error reasons |
copyright.flag |
Potential copyright issue detected |
Includes match details |
processing.error |
Technical error during processing |
Includes error details and stack trace |
distribution.complete |
Release distributed to platforms |
Includes platform URLs and IDs |
Webhook Payload Example
{
"event": "submission.approved",
"timestamp": "2024-01-15T10:30:00.000Z",
"data": {
"submission_id": "sub_123456",
"status": "approved",
"user_id": "user_789012",
"user_email": "artist@example.com",
"artwork_validation": { ... },
"copyright_result": { ... },
"distribution_metadata": {
"spotify_id": "7ouMYWpwJ422jRcDASZB7P",
"apple_id": "1440857781",
"amazon_id": "B07XQXZXMX"
}
}
}
cURL
Python
JavaScript
PHP
Validate Artwork with cURL
curl -X POST \
https://releases.musicdash.ai/api/artwork/validate \
-F "file=@/path/to/artwork.jpg" \
-H "Accept: application/json"
Process Submission with cURL
curl -X GET \
"https://releases.musicdash.ai/api/submissions/sub_123456/validate" \
-H "Accept: application/json"
Batch Process with cURL
curl -X POST \
https://releases.musicdash.ai/api/submissions/process \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"submission_ids": ["sub_123456", "sub_789012", "sub_345678"]
}'
Admin Rejection Email with cURL
curl -X PUT \
"https://releases.musicdash.ai/admin/email/custom_reject_submission?submission_id=sub_123456" \
-H "Authorization: Bearer {admin_token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"reasons": [
"Artwork does not meet quality standards",
"Audio file has technical issues"
],
"additional_notes": [
"Please resubmit with corrected files"
]
}'
Python Integration Example
import requests
import json
BASE_URL = "https://releases.musicdash.ai"
class MusicdashClient:
def __init__(self):
self.base_url = BASE_URL
self.session = requests.Session()
self.session.headers.update({
'Accept': 'application/json',
'User-Agent': 'Musicdash-Integration/1.0'
})
def validate_submission(self, submission_id):
"""Validate a specific submission"""
url = f"{self.base_url}/api/submissions/{submission_id}/validate"
response = self.session.get(url)
response.raise_for_status()
return response.json()
def validate_artwork(self, image_path):
"""Validate artwork file"""
url = f"{self.base_url}/api/artwork/validate"
with open(image_path, 'rb') as f:
files = {'file': f}
response = self.session.post(url, files=files)
response.raise_for_status()
return response.json()
def check_copyright(self, audio_path):
"""Check audio for copyright issues"""
url = f"{self.base_url}/api/copyright/check"
with open(audio_path, 'rb') as f:
files = {'file': f}
response = self.session.post(url, files=files)
response.raise_for_status()
return response.json()
def process_batch(self, submission_ids):
"""Process batch of submissions"""
url = f"{self.base_url}/api/submissions/process"
data = {'submission_ids': submission_ids}
response = self.session.post(url, json=data)
response.raise_for_status()
return response.json()
# Usage example
client = MusicdashClient()
# Validate a submission
try:
result = client.validate_submission('sub_123456')
print(f"Submission status: {result['submission']['status']}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
# Validate artwork
try:
validation = client.validate_artwork('cover.jpg')
print(f"Artwork valid: {validation['is_valid']}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
JavaScript/Node.js Integration
const BASE_URL = 'https://releases.musicdash.ai';
class MusicdashAPI {
constructor() {
this.baseUrl = BASE_URL;
}
async validateSubmission(submissionId) {
const response = await fetch(
`${this.baseUrl}/api/submissions/${submissionId}/validate`,
{
method: 'GET',
headers: {
'Accept': 'application/json'
}
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
async validateArtwork(file) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch(
`${this.baseUrl}/api/artwork/validate`,
{
method: 'POST',
body: formData
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
async checkCopyright(file) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch(
`${this.baseUrl}/api/copyright/check`,
{
method: 'POST',
body: formData
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
async processBatch(submissionIds) {
const response = await fetch(
`${this.baseUrl}/api/submissions/process`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({
submission_ids: submissionIds
})
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
}
}
// Usage example
const api = new MusicdashAPI();
// Validate submission
api.validateSubmission('sub_123456')
.then(result => {
console.log(`Submission status: ${result.submission.status}`);
})
.catch(error => {
console.error('Error:', error);
});
// Validate artwork from file input
const artworkFile = document.getElementById('artwork-file').files[0];
api.validateArtwork(artworkFile)
.then(validation => {
console.log(`Artwork valid: ${validation.is_valid}`);
})
.catch(error => {
console.error('Error:', error);
});
PHP Integration Example
baseUrl . '/api/submissions/' . $submissionId . '/validate';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Accept: application/json'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception('HTTP error: ' . $httpCode);
}
return json_decode($response, true);
}
public function validateArtwork($filePath) {
$url = $this->baseUrl . '/api/artwork/validate';
$postData = [
'file' => new CURLFile($filePath)
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception('HTTP error: ' . $httpCode);
}
return json_decode($response, true);
}
public function processBatch($submissionIds) {
$url = $this->baseUrl . '/api/submissions/process';
$postData = json_encode([
'submission_ids' => $submissionIds
]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Accept: application/json'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception('HTTP error: ' . $httpCode);
}
return json_decode($response, true);
}
}
// Usage example
$client = new MusicdashClient();
try {
// Validate submission
$result = $client->validateSubmission('sub_123456');
echo "Submission status: " . $result['submission']['status'] . "\n";
// Validate artwork
$validation = $client->validateArtwork('/path/to/artwork.jpg');
echo "Artwork valid: " . ($validation['is_valid'] ? 'Yes' : 'No') . "\n";
// Process batch
$batchResult = $client->processBatch(['sub_123456', 'sub_789012']);
echo "Processed " . count($batchResult['processed_submissions']) . " submissions\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>