If you distribute music digitally, you've dealt with DDEX. The Electronic Release Notification (ERN) standard is how labels and distributors exchange release metadata - track titles, ISRC codes, territory rights, audio file references, and more. Get it wrong, and your release gets rejected. Get it right, and it flows seamlessly to Spotify, Apple Music, and hundreds of other platforms.
The problem? DDEX XML files are complex, deeply nested, and easy to break. Validation usually means uploading files to web tools, running CLI scripts, or waiting for your distributor to reject your submission.
In this tutorial, we'll build a Claude skill that validates DDEX ERN files on demand - right inside Claude Code or Claude.ai. Type /ddex-validate, paste your XML, and get instant feedback with actionable error messages.
A skill is a folder with a SKILL.md file that teaches Claude how to handle a specific workflow. Think of it as a reusable prompt template with structure:
ddex-validate/
├── SKILL.md # Instructions + YAML frontmatter
├── references/
│ └── ern-structure.md # DDEX domain knowledge
└── assets/
└── ern382-sample.xml # Example file for testing
Skills use progressive disclosure - Claude loads the frontmatter first (to decide if the skill is relevant), then the full instructions only when triggered. This keeps token usage low while maintaining deep domain expertise.
Before writing any code, define what the skill should handle:
Full XML Validation
Parse XML, detect ERN version, fetch XSD schema, validate, and report errors with line numbers.
Quick Structure Check
Verify required elements exist and check ISRC/UPC format without full schema validation.
Fix Suggestions
Analyze each error, suggest a specific fix, and show corrected XML snippets the user can copy-paste.
Create the skill directory in your Claude Code skills location:
mkdir -p ~/.claude/skills/ddex-validate/references
mkdir -p ~/.claude/skills/ddex-validate/assets
This is the core of the skill. The YAML frontmatter tells Claude when to load it, and the Markdown body tells Claude what to do.
Create ~/.claude/skills/ddex-validate/SKILL.md:
The frontmatter is the most important part - it's how Claude decides whether to load your skill:
name: ddex-validate
description: Validates DDEX ERN XML files against official schemas.
Checks structure, required fields (ISRC, UPC, MessageHeader), and
schema conformance. Use when user uploads .xml files, mentions
"DDEX", "ERN", "validate release", "check metadata", or
"release notification".
The body of SKILL.md contains step-by-step instructions. Here's the core - the Python validation function that fetches the official DDEX XSD and validates against it:
from lxml import etree
import requests
def validate_ddex(xml_content: str, version: str) -> dict:
"""Validate DDEX XML against official ERN schema."""
xsd_url = (
f"https://service.ddex.net/xml/ern/"
f"{version}/release-notification.xsd"
)
# Fetch and compile schema
response = requests.get(xsd_url, timeout=10)
response.raise_for_status()
schema_root = etree.fromstring(response.content)
schema = etree.XMLSchema(schema_root)
# Parse and validate
xml_tree = etree.fromstring(xml_content.encode())
is_valid = schema.validate(xml_tree)
errors = []
if not is_valid:
for error in schema.error_log:
errors.append({
"line": error.line,
"column": error.column,
"message": error.message,
"level": error.level_name,
})
return {"valid": is_valid, "errors": errors, "version": version}
Beyond schema validation, the skill checks for issues that cause real distributor rejections:
| Check | Rule | Example |
|---|---|---|
| ISRC | Exactly 12 alphanumeric chars, no hyphens | USSM12345678 |
| UPC/EAN | 12 or 13 digits | 123456789012 |
| Territory | ISO 3166-1 alpha-2 or Worldwide | US, GB, Worldwide |
| Duration | ISO 8601 format | PT3M30S |
| Resource refs | Every ReleaseResourceReference must match a ResourceReference | A1 links to A1 |
| ParentalWarning | Must be present | NotExplicit, Explicit |
US-SM1-23-45678) but never in XML. This is one of the most common validation errors we see.The skill defines exactly how Claude should present results:
DDEX ERN 382 - Valid
Summary:
- Releases: 1
- Sound Recordings: 3
- Images: 1
- Territory: Worldwide
- Message Type: LiveMessage
And when errors are found:
DDEX ERN 382 - 2 error(s) found
| # | Line | Error | Suggested Fix |
|---|------|---------------------------------|----------------------------------|
| 1 | 36 | Element 'ISRC': '' is not valid | Add 12-char ISRC: CCXXXYYNNNNN |
| 2 | 45 | Missing element 'TerritoryCode' | Add <TerritoryCode>Worldwide</…> |
The skill needs two more pieces:
references/ern-structure.md - the complete ERN element hierarchy (MessageHeader, ResourceList, ReleaseList, DealList), field format rules, and version differences between ERN 3.8.2 and 4.1.1+. Claude loads this on demand when it needs deeper context during validation.
assets/ern382-sample.xml - a minimal but valid ERN 3.8.2 file with a MessageHeader, one SoundRecording (ISRC, artist, genre, technical details), one Image, and one Release.
git clone https://github.com/musictechlab/ddex-validate.git ~/.claude/skills/ddex-validate
Once installed, test it from three angles:
Should trigger - try prompts like these:
"Validate this DDEX file"
"Check my ERN XML for errors"
"Is this release metadata valid?"
Error detection - introduce common mistakes and verify the skill catches them:
<!-- Missing ISRC -->
<SoundRecordingId>
<CatalogNumber Namespace="PADPIDA2023001">CAT001</CatalogNumber>
</SoundRecordingId>
<!-- Invalid territory code -->
<TerritoryCode>United States</TerritoryCode>
<!-- Mismatched resource reference -->
<ReleaseResourceReference>A99</ReleaseResourceReference>
<!-- when ResourceReference is "A1" -->
Should NOT trigger - prompts like "Write a Python function" or "Help me with CSS" should not activate the skill.
When you type a prompt that matches the skill's description triggers, Claude's progressive disclosure system kicks in:
Loading diagram...
This three-level system keeps token usage minimal for non-DDEX conversations while providing deep expertise when needed:
Level 1 - Frontmatter
Claude reads name and description. Just enough to decide: "is this a DDEX request?"
Level 2 - Instructions
The full 5-step workflow: parse, validate, check industry rules, report results.
Level 3 - References
Deep ERN structure docs, field formats, version differences. Loaded only when needed.
This skill covers standalone validation - no external services required. But there are natural extensions:
You could also combine this with an AudioSalad or Revelator delivery skill - validate the DDEX, then push it to your distributor, all from one conversation.
DDEX validation is a perfect fit for a Claude skill: it's a well-defined workflow, requires domain knowledge that doesn't change often, and benefits from consistent execution. Instead of context-switching to a web tool or remembering CLI flags, you type /ddex-validate and get expert-level feedback in seconds.
The full skill is open source - clone it and start validating:
git clone https://github.com/musictechlab/ddex-validate.git ~/.claude/skills/ddex-validate
Music Tech Lab builds tools for the music industry - from metadata validation to streaming analytics. If you're working with DDEX, audio fingerprinting, or distribution pipelines, get in touch.
Have a similar project in mind? We'd love to hear about it.
Get in touch to discuss how we can help bring your vision to life.
AI Song Structure Analysis: Intro, Verse, Chorus
A technical look at automatic song structure detection using AI and signal processing. Identify song sections with MTL Audio Locators.
Building a Custom Music Delivery Platform on the Revelator API
A practical guide for music distributors evaluating a hybrid approach: custom frontend with Revelator's API as the delivery backbone. Covers architecture, DDEX integration, territory handling, and when to go fully independent.