DDEX vocabularies
Roles, resource types, territories and many other fields hold values from DDEX's published lists. How //SCHEMA treats those lists — and the values that fall outside them.
Allowed-value sets#
DDEX publishes allowed-value sets (AVS): the permitted values for fields
such as a contributor's role (MainArtist, Producer), a resource's type
(MusicalWorkSoundRecording, FrontCoverImage), a territory (US, DE,
Worldwide) or a commercial model (SubscriptionModel). Each set is a
kind; a value is only meaningful within its kind — DJ is both a country
code and a contributor role.
This is why authoring inputs ask for both: role and roleKind,
resourceType and resourceTypeKind.
Accepted, not rejected#
A delivery can contain a value DDEX does not define — a misspelling, a sender's private extension, or a value from a newer DDEX version. //SCHEMA accepts it anyway, and records it as observed rather than DDEX-defined.
Refusing it would mean refusing the delivery, over a detail that can be fixed later by a person or a subsequent ERN. DDEX's own schemas are not always free of defects either, so treating them as a gate could reject valid music for invalid reasons. Delivery never fails on vocabulary.
vocabValues shows the difference:
ddexDefined: false marks a value that arrived in a delivery but is not in
DDEX's set.
Stored exactly as sent#
Values are never normalized: no case-folding, no trimming of accents, no
mapping of synonyms. MainArtist stays MainArtist; a sender who wrote
mainArtist is kept as mainArtist. //SCHEMA must be able to regenerate
what it received.
Storing verbatim does not mean matching strictly. Normalization happens in the comparison instead, so what you send is preserved and what you search for still finds it:
- Vocabulary filters —
role,typeand their kin — compare case-insensitively, so you do not need to match a sender's capitalisation. DDEX vocabulary values are ASCII tokens, so case is the only difference that arises. - Free-text search —
qonreleases, matching titles, display artists and labels — folds case and accents.sineadfindsSinéad, andSinéadfindssinead; neither side has to guess how the other typed it.
Two things free-text search deliberately does not fold, because both change what a title is rather than how it is spelled:
- Typographic apostrophes.
O'ConnorandO'Connordiffer by a real character (U+0027againstU+2019) and are not matched to each other. If your senders are inconsistent here, search for the distinctive part of the name —connor— rather than the whole string. - Misspellings. Matching is substring, not fuzzy:
O'Connerwill not findO'Connor.
Offering values in your UI#
- Ask vocabKindIsClosed whether a kind is a fixed list. Most are; some, such as genre, are open.
- Fetch the values once with vocabValues — the limit is high enough for the largest set — and cache them. They change only when DDEX publishes a new revision.
- Offer a picker for closed kinds, and a picker plus free text for open ones.
query Roles {
closed: vocabKindIsClosed(kind: "ResourceContributorRole")
values: vocabValues(kind: "ResourceContributorRole", limit: 1000) {
value
ddexDefined
}
}curl https://api.schema.fm/graphql \
-H "Authorization: Bearer $SCHEMA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'EOF'
{
"query": "query Roles {\n closed: vocabKindIsClosed(kind: \"ResourceContributorRole\")\n values: vocabValues(kind: \"ResourceContributorRole\", limit: 1000) {\n value\n ddexDefined\n }\n}"
}
EOFconst res = await fetch("https://api.schema.fm/graphql", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SCHEMA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
query: `
query Roles {
closed: vocabKindIsClosed(kind: "ResourceContributorRole")
values: vocabValues(kind: "ResourceContributorRole", limit: 1000) {
value
ddexDefined
}
}
`,
}),
});
const { data, errors } = await res.json();Useful kinds#
| Kind | Used by |
|---|---|
DisplayArtistRole | Release-level billing credits — MainArtist, FeaturedArtist |
ResourceContributorRole | Track credits — Producer, Mixer, AssociatedPerformer |
SoundRecordingType | resourceType for audio |
ImageType | resourceType for artwork — FrontCoverImage |
ReleaseType | releaseType — Album, Single, EP |
CurrentTerritoryCode | Territories |