Skip to main content

Overview

DDEX (Digital Data Exchange) is the industry-standard XML format for communicating music metadata and rights information to Digital Service Providers (DSPs). The Royalti.io API supports generating ERN, MEAD, and PIE messages.

Authentication

DDEX endpoints require authentication. Some providers also use additional DDEX-specific authentication.

Message Types

ERN (Electronic Release Notification)

Used for delivering release metadata to DSPs:
Node.js
const response = await fetch('https://api.royalti.io/ddex/ern/generate', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    productId: 'prod-123',
    providerId: 'spotify',
    messageType: 'NewReleaseMessage'
  })
});

MEAD (Music Enrichment and Description)

Rich metadata for enhanced discovery:
Node.js
const response = await fetch('https://api.royalti.io/ddex/mead/generate', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    assetId: 'asset-123',
    providerId: 'apple-music',
    includeCredits: true
  })
});

PIE (Party Information Exchange)

Rights holder information:
Node.js
const response = await fetch('https://api.royalti.io/ddex/pie/generate', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    artistId: 'artist-123',
    providerId: 'universal'
  })
});

DDEX Workflow

1

Configure Provider

Set up delivery credentials and preferences for each DSP.
Node.js
const response = await fetch('https://api.royalti.io/ddex/providers/', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Spotify',
    deliveryMethod: 'SFTP',
    credentials: {
      host: 'sftp.spotify.com',
      username: 'your-username',
      // Store password in environment
    }
  })
});
2

Generate Message

Create DDEX XML from your release data.
The system automatically validates against XSD schemas and applies business rules.
3

Validate Message

Ensure compliance with DDEX standards.
Node.js
const response = await fetch(`https://api.royalti.io/ddex/messages/${messageId}/validate`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`
  }
});
4

Deliver to Provider

Send via SFTP, API, or HTTP depending on provider requirements.
Node.js
const response = await fetch(`https://api.royalti.io/ddex/messages/${messageId}/deliver`, {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

Provider-Specific Configuration

Different DSPs have different requirements:
Node.js
const providerConfigs = {
  spotify: {
    deliveryMethod: 'SFTP',
    ernProfile: 'ERN-4',
    territories: ['Worldwide']
  },
  appleMusic: {
    deliveryMethod: 'API',
    ernProfile: 'ERN-4.1',
    requiresPreview: true
  },
  tidal: {
    deliveryMethod: 'HTTP',
    ernProfile: 'ERN-3.8.2',
    audioQuality: 'lossless'
  }
};

Best Practices

Territory Management

Ensure territory configurations don’t overlap and cover 100% of intended distribution.

Deal Configuration

Set up usage rights and release dates:
Node.js
const dealConfig = {
  territories: ['US', 'CA', 'GB'],
  usageType: 'PermanentDownload',
  startDate: '2024-06-01',
  priceCategory: 'Mid'
};

Error Handling

Implement comprehensive validation:
Node.js
async function generateAndValidateDDEX(productId, providerId) {
  try {
    // Generate message
    const message = await generateERN(productId, providerId);

    // Validate
    const validation = await validateMessage(message.id);

    if (!validation.isValid) {
      console.error('Validation errors:', validation.errors);
      return { success: false, errors: validation.errors };
    }

    // Deliver
    await deliverMessage(message.id);

    return { success: true, messageId: message.id };
  } catch (error) {
    console.error('DDEX generation failed:', error);
    throw error;
  }
}