Quickstart
By the end of this tutorial you will have an API key, have confirmed it works, and have read a release from your catalog with its tracks and credits.
You need a //SCHEMA account with the owner or admin role, and a
terminal with curl. Nothing else.
1. Create an API key#
Sign in to the console, open API Access,
and create a key named Quickstart with these scopes:
catalog_read— to read releasesmedia_read— to get links to the audio
Copy the key when it is shown. It begins sk_, and it is shown once:
//SCHEMA keeps only a hash of it.
Put it in an environment variable so the examples below can use it:
export SCHEMA_API_KEY=sk_...2. Check that the key works#
Ask the API who you are. viewer needs no particular scope, so it is the simplest possible request:
curl https://api.schema.fm/graphql \
-H "Authorization: Bearer $SCHEMA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ viewer { actorType catalogPk scopes } }"}'You should see:
{"data":{"viewer":{"actorType":"api_key","catalogPk":31,"scopes":["CatalogRead","MediaRead"]}}}catalogPk is the catalog this key is bound to. Every request you make with
it acts on that catalog — there is no catalog argument anywhere in the API.
If you see "code": "UNAUTHENTICATED" instead, the key was not sent or was
mistyped. Check the header reads Authorization: Bearer sk_….
3. List your releases#
Everything is one endpoint; only the query changes. Ask for the three most recently updated releases:
query {
releases(limit: 3) {
releasePk
upc
title
state
}
}curl https://api.schema.fm/graphql \
-H "Authorization: Bearer $SCHEMA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'EOF'
{
"query": "query {\n releases(limit: 3) {\n releasePk\n upc\n title\n state\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 {
releases(limit: 3) {
releasePk
upc
title
state
}
}
`,
}),
});
const { data, errors } = await res.json();{
"data": {
"releases": [
{ "releasePk": 48213, "upc": "0196871402293", "title": "Paper Radio", "state": "active" },
{ "releasePk": 48190, "upc": "0196871377720", "title": "Low Orbit", "state": "active" },
{ "releasePk": 47102, "upc": "0196871118736", "title": "Slow Exit", "state": "active" }
]
}
}If the list is empty, your catalog has no published releases yet. Either deliver one, or follow Publish a release and come back.
4. Read one release in depth#
Pick a UPC from the list and ask for its tracks, the main artist, and everyone credited on each track, with their role. You select exactly the fields you want, at every level:
query Release($upc: String!) {
release(upc: $upc) {
title
contributors(role: "MainArtist") {
party { name }
}
resources {
sequence
title
isrc
durationSeconds
contributors {
role
party { name }
}
}
}
}{
"upc": "0196871402293"
}curl https://api.schema.fm/graphql \
-H "Authorization: Bearer $SCHEMA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'EOF'
{
"query": "query Release($upc: String!) {\n release(upc: $upc) {\n title\n contributors(role: \"MainArtist\") {\n party { name }\n }\n resources {\n sequence\n title\n isrc\n durationSeconds\n contributors {\n role\n party { name }\n }\n }\n }\n}",
"variables": {
"upc": "0196871402293"
}
}
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 Release($upc: String!) {
release(upc: $upc) {
title
contributors(role: "MainArtist") {
party { name }
}
resources {
sequence
title
isrc
durationSeconds
contributors {
role
party { name }
}
}
}
}
`,
variables: {
"upc": "0196871402293"
},
}),
});
const { data, errors } = await res.json();{
"data": {
"release": {
"title": "Paper Radio",
"contributors": [{ "party": { "name": "Halfway Ghosts" } }],
"resources": [
{
"sequence": 1,
"title": "Signal Fire",
"isrc": "JPTO09404900",
"durationSeconds": 214,
"contributors": [
{ "role": "Composer", "party": { "name": "Ada Reyes" } },
{ "role": "Composer", "party": { "name": "Tom Vance" } },
{ "role": "Producer", "party": { "name": "Mika Sato" } }
]
}
]
}
}
}Two things to notice:
- Credits live at two levels.
Release.contributorsis who the release is billed to;Resource.contributorsis who worked on each recording. DDEX keeps them apart, and so does the API. - Role names are DDEX's.
MainArtist,Composer,Producer— the values the label delivered, verbatim. To narrow a list to one role, pass it as an argument, as the release does withcontributors(role: "MainArtist"); the match is case-insensitive.
5. Get a playable link#
Add url to a resource, naming the encoding you want. It returns a signed
link to the file that expires after five minutes — this is what media_read
is for:
query {
release(upc: "0196871402293") {
resources(kind: AUDIO) {
title
url(encoding: "aac-256")
}
}
}curl https://api.schema.fm/graphql \
-H "Authorization: Bearer $SCHEMA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'EOF'
{
"query": "query {\n release(upc: \"0196871402293\") {\n resources(kind: AUDIO) {\n title\n url(encoding: \"aac-256\")\n }\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 {
release(upc: "0196871402293") {
resources(kind: AUDIO) {
title
url(encoding: "aac-256")
}
}
}
`,
}),
});
const { data, errors } = await res.json();aac-256 is the stream //SCHEMA makes of every track; encodings lists the
rest. See Stream media.
Try the same query with a key that lacks media_read: the titles still come
back, and each url is null with an error beside it. Authorization in this
API is per field.
What you have learned#
- One endpoint, one
POST, one header. - The catalog comes from the key; scopes decide what the key can read.
- You shape the response by choosing fields, at every level of the tree.
Next#
- Publish a release — build one from scratch through the API.
- Paginate and search — walk a whole catalog.
- The Release object — every field you can ask for.