Skip to main content

Overview

DDEX (Digital Data Exchange) is the industry standard for exchanging music metadata between parties in the music industry. Proper DDEX metadata is essential for delivering your products to Digital Service Providers (DSPs). This guide covers how to:
  • Update DDEX metadata for your assets
  • Validate asset DDEX readiness
  • Prepare assets for product delivery
  • Troubleshoot common DDEX issues

Quick Start

1

Update Asset DDEX Metadata

Add or update DDEX-compliant metadata for your audio asset.
curl -X PUT https://api.royalti.io/asset/asset_123/ddex-metadata \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ddexMetadata": {
      "resourceReference": "A123456789",
      "title": "My Song Title",
      "displayArtist": "Artist Name",
      "languageOfPerformance": "en",
      "duration": "PT3M45S",
      "parentalWarningType": "NotExplicit"
    },
    "technicalResourceDetails": {
      "fileFormat": "WAV",
      "sampleRate": 44100,
      "bitDepth": 16,
      "numberOfChannels": 2,
      "audioCodec": "PCM"
    },
    "soundRecordingDetails": {
      "isrc": "USRC17607839",
      "pLine": {
        "year": 2024,
        "pLineText": "2024 Record Label Name"
      },
      "genre": "Pop",
      "subGenre": "Indie Pop"
    }
  }'
2

Check Asset DDEX Readiness

Validate that your asset has all required DDEX metadata before delivery.
curl -X GET https://api.royalti.io/asset/asset_123/ddex-readiness \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
A readiness score of 100% is required for delivery. Scores below 100% indicate missing or invalid fields.
3

Review and Fix Issues

Address any missing or invalid fields identified in the readiness check.
{
  "status": "success",
  "data": {
    "isReady": false,
    "readinessScore": 75,
    "missingFields": [
      "soundRecordingDetails.isrc",
      "ddexMetadata.duration"
    ],
    "invalidFields": [
      {
        "field": "technicalResourceDetails.sampleRate",
        "issue": "Must be 44100 or 48000",
        "currentValue": 22050
      }
    ],
    "warnings": [
      "Genre 'Unknown' may not be recognized by all DSPs"
    ],
    "suggestions": [
      "Add ISRC code for proper identification",
      "Update sample rate to 44100 Hz or 48000 Hz",
      "Specify a standard genre from the approved list"
    ]
  }
}
Update your asset metadata to address each issue, then re-check readiness.
4

Integrate with Product Delivery

Once your asset is DDEX ready, you can include it in product deliveries.See the Product Delivery Guide for complete delivery workflows.

DDEX Metadata Structure

Resource Reference

Unique identifier for the audio resource within your catalog.
{
  "resourceReference": "A123456789"
}
Use a consistent naming scheme for resource references (e.g., prefix + sequential number).

Basic Metadata

Core information about the recording.
{
  "title": "Song Title",
  "displayArtist": "Artist Name",
  "languageOfPerformance": "en",
  "duration": "PT3M45S",
  "parentalWarningType": "NotExplicit"
}
Duration Format: ISO 8601 duration (e.g., PT3M45S = 3 minutes 45 seconds) Parental Warning Types:
  • NotExplicit - Clean content
  • Explicit - Contains explicit content
  • Unknown - Warning status unknown
Language Codes: ISO 639-1 two-letter codes (e.g., en, es, fr, de, ja)

Technical Resource Details

Audio file specifications required for delivery.
{
  "fileFormat": "WAV",
  "sampleRate": 44100,
  "bitDepth": 16,
  "numberOfChannels": 2,
  "audioCodec": "PCM"
}
Accepted Sample Rates: 44100 Hz, 48000 Hz, 96000 Hz Accepted Bit Depths: 16-bit, 24-bit Supported Formats:
  • WAV (recommended)
  • FLAC
  • AIFF

Sound Recording Details

Metadata specific to the sound recording.
{
  "isrc": "USRC17607839",
  "pLine": {
    "year": 2024,
    "pLineText": "2024 Record Label Name"
  },
  "genre": "Pop",
  "subGenre": "Indie Pop"
}
ISRC: International Standard Recording Code (12 characters: 2-letter country + 3-char registrant + 2-digit year + 5-digit designation) Genre Standards: Use recognized genre names from the DDEX genre list for best DSP compatibility.

Readiness Validation

Readiness Score Calculation

The readiness score is calculated based on:
  • Required fields (60%): ISRC, duration, title, artist, format, sample rate
  • Recommended fields (30%): Genre, language, P-line, parental warning
  • Technical quality (10%): Valid sample rate/bit depth, proper format

Common Validation Issues

Error: soundRecordingDetails.isrc is requiredCause: ISRC (International Standard Recording Code) is mandatory for DSP delivery.Solution: Generate or obtain an ISRC code for your recording:
// If you have an ISRC
const ddexData = {
  soundRecordingDetails: {
    isrc: 'USRC17607839'
  }
};

// If you need to generate one (contact your national ISRC agency)
// Format: CC-XXX-YY-NNNNN
// CC = Country code (e.g., US)
// XXX = Registrant code
// YY = Year
// NNNNN = Designation code
Error: ddexMetadata.duration must be in ISO 8601 formatCause: Duration must be specified in ISO 8601 format (e.g., PT3M45S).Solution: Convert your duration to ISO 8601 format:
function secondsToISO8601(seconds) {
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);

  let duration = 'PT';
  if (hours > 0) duration += `${hours}H`;
  if (minutes > 0) duration += `${minutes}M`;
  if (secs > 0) duration += `${secs}S`;

  return duration;
}

// Example: 225 seconds = 3 minutes 45 seconds
const duration = secondsToISO8601(225); // "PT3M45S"
Error: technicalResourceDetails.sampleRate must be 44100, 48000, or 96000Cause: DSPs require specific sample rates for audio delivery.Solution: Re-encode your audio file at an accepted sample rate (44.1 kHz recommended):
# Using ffmpeg to convert sample rate
ffmpeg -i input.wav -ar 44100 -sample_fmt s16 output.wav
Then update your metadata:
{
  "technicalResourceDetails": {
    "sampleRate": 44100,
    "bitDepth": 16
  }
}
Error: soundRecordingDetails.pLine is recommendedCause: P-Line (phonographic copyright) is recommended for proper rights attribution.Solution: Add P-Line information:
{
  "soundRecordingDetails": {
    "pLine": {
      "year": 2024,
      "pLineText": "2024 Your Record Label Name"
    }
  }
}
P-Line year should be the year of first publication, not the current year.
Warning: Genre 'Unknown' may not be recognized by all DSPsCause: Using non-standard or generic genre names.Solution: Use standard DDEX genre classifications:Primary Genres:
  • Alternative
  • Blues
  • Children’s Music
  • Classical
  • Comedy
  • Country
  • Dance
  • Electronic
  • Folk
  • Hip-Hop/Rap
  • Jazz
  • Latin
  • Pop
  • R&B/Soul
  • Reggae
  • Rock
  • Soundtrack
  • World
Example:
{
  "soundRecordingDetails": {
    "genre": "Electronic",
    "subGenre": "House"
  }
}
Warning: musicalWorkReference is recommended for publishing metadataCause: No link between the sound recording and the underlying musical work.Solution: Add musical work reference if you have publishing information:
{
  "musicalWorkReference": {
    "workId": "work_456",
    "iswc": "T-123.456.789-0",
    "composers": ["Composer Name"],
    "publishers": ["Publisher Name"]
  }
}
ISWC (International Standard Musical Work Code) helps with publishing royalty collection.

Best Practices

Validate Early

Check DDEX readiness before creating products to catch issues early in your workflow.

Use High-Quality Audio

Upload lossless formats (WAV, FLAC) at 44.1 kHz or higher for best quality across all DSPs.

Maintain Metadata Consistency

Keep asset metadata synchronized with your product metadata for smooth delivery.

Monitor Readiness Scores

Aim for 100% readiness scores to ensure compatibility with all delivery providers.

Complete Integration Example

const axios = require('axios');

class DDEXAssetManager {
  constructor(accessToken) {
    this.client = axios.create({
      baseURL: 'https://api.royalti.io',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      }
    });
  }

  async updateAssetMetadata(assetId, metadata) {
    try {
      const response = await this.client.put(
        `/asset/${assetId}/ddex-metadata`,
        metadata
      );
      console.log(`✓ Updated DDEX metadata for ${assetId}`);
      return response.data;
    } catch (error) {
      console.error('Failed to update metadata:', error.response?.data);
      throw error;
    }
  }

  async checkReadiness(assetId) {
    try {
      const response = await this.client.get(
        `/asset/${assetId}/ddex-readiness`
      );
      return response.data.data;
    } catch (error) {
      console.error('Failed to check readiness:', error.response?.data);
      throw error;
    }
  }

  async ensureAssetReady(assetId, metadata) {
    // Step 1: Update metadata
    await this.updateAssetMetadata(assetId, metadata);

    // Step 2: Check readiness
    const readiness = await this.checkReadiness(assetId);

    // Step 3: Report results
    if (readiness.isReady) {
      console.log(`✓ Asset ${assetId} is ready (score: ${readiness.readinessScore}%)`);
      return true;
    } else {
      console.log(`✗ Asset ${assetId} is NOT ready (score: ${readiness.readinessScore}%)`);

      if (readiness.missingFields.length > 0) {
        console.log('\nMissing fields:');
        readiness.missingFields.forEach(field => {
          console.log(`  - ${field}`);
        });
      }

      if (readiness.invalidFields.length > 0) {
        console.log('\nInvalid fields:');
        readiness.invalidFields.forEach(({ field, issue, currentValue }) => {
          console.log(`  - ${field}: ${issue} (current: ${currentValue})`);
        });
      }

      if (readiness.suggestions.length > 0) {
        console.log('\nSuggestions:');
        readiness.suggestions.forEach(suggestion => {
          console.log(`  - ${suggestion}`);
        });
      }

      return false;
    }
  }
}

// Example usage
async function prepareAssetForDelivery() {
  const manager = new DDEXAssetManager(process.env.ROYALTI_ACCESS_TOKEN);

  const assetMetadata = {
    ddexMetadata: {
      resourceReference: 'A123456789',
      title: 'My New Single',
      displayArtist: 'The Artist',
      languageOfPerformance: 'en',
      duration: 'PT3M45S',
      parentalWarningType: 'NotExplicit'
    },
    technicalResourceDetails: {
      fileFormat: 'WAV',
      sampleRate: 44100,
      bitDepth: 16,
      numberOfChannels: 2,
      audioCodec: 'PCM'
    },
    soundRecordingDetails: {
      isrc: 'USRC17607839',
      pLine: {
        year: 2024,
        pLineText: '2024 Independent Records'
      },
      genre: 'Pop',
      subGenre: 'Indie Pop'
    }
  };

  const isReady = await manager.ensureAssetReady('asset_123', assetMetadata);

  if (isReady) {
    console.log('\n✓ Asset is ready for product delivery!');
    // Proceed with product delivery workflow
  } else {
    console.log('\n✗ Please fix the issues above before delivery');
  }
}

prepareAssetForDelivery().catch(console.error);

Delivery Workflow Integration

Once your assets are DDEX ready:
  1. Create a product with your DDEX-ready assets
  2. Validate the product for delivery
  3. Deliver to DSPs using the Product Delivery API