Overview

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.

Base URL

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.

Authentication

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.

Quick Start

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" } }

Health Check

GET /api/health

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

Submission Management

GET /api/submissions/{submission_id}/validate

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

POST /api/submissions/process BATCH

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

File Validation

POST /api/artwork/validate ADVANCED

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

POST /api/audio/validate

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

System Information

GET /api/system/status

Get comprehensive system status, configuration, and service health information.

Response

{ "timestamp": "2024-01-15T10:30:00.000Z", "system_version": "2.1.0", "aws_enabled": true, "pex_enabled": true, "email_enabled": true, "google_sheets_enabled": true, "musicdash_api_connected": true, "processed_submissions": 156, "services": { "s3_storage": { "status": "active", "buckets_accessible": 3 }, "pex_api": { "status": "online", "last_check": "2024-01-15T10:25:00.000Z" }, "email_service": { "status": "ready", "provider": "AWS SES" }, "validation_engine": { "status": "operational", "version": "1.2.0" } }, "performance": { "average_processing_time": "12.5s", "uptime": "99.95%", "active_processes": 3 } }

Status Codes

200 - Successfully retrieved system status

500 - Internal server error

Admin Endpoints

PUT /admin/email/custom_reject_submission ADMIN

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

Release Status Types

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

Error Handling

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

File Upload Limits & Requirements

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

Rate Limiting

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

Webhook Notifications

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" } } }

Integration Examples

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"; } ?>