Playing and accessing tracks
Choose how access is granted, then — when a server creates a play session — how audio is played. Upload is a separate decision; see Uploading tracks.
Play sessions vs signed delivery
A play session is a short-lived, per-listener authorization created via the API
(track or collection scope — playlist scope is reserved and returns 400).
Signed delivery without a play session signs a URL on your server with a URL Signing key;
possession of the temporary link is sufficient access. You can mix both (for example signed previews and gated full tracks).
Playing and accessing tracks
Choose how access is granted, then — if needed — how audio is played. You can mix methods (for example public signed previews and gated play sessions for full tracks).
AudioDN Player web component with a Client-Side Player key
Fastest setup. Drop in the AudioDN Player web component; it creates and renews play sessions. Suitable when per-listener server approval is not required.
Create a Client-Side Player key
In the dashboard create a Client-Side Player key. Optionally scope it to a collection, track, and/or variants. This key can only create play sessions — not manage tracks or collections.
Install the Player web component
npm install @audiodn/components import '@audiodn/components/player' Or from a CDN:
<script type="module" src="https://unpkg.com/@audiodn/components@latest/dist/player.js"></script> Render the Player web component
<audiodn-player
api-key="CLIENT-SIDE-PLAYER-KEY"
scope="collection"
id="COLLECTION-ID"
variant="hq"
size="large"
></audiodn-player> Either api-key or play-session-id is required — never both.
See the Player component reference.
Custom player with a Client-Side Player key
Your app creates a play session with a scoped Client-Side Player key and plays signed variant URLs in your own interface.
Create a Client-Side Player key
Scope it to the tracks, collections, and variants the app may access. Never use an API Access key in client code.
Create a play session
const response = await fetch('https://api.audiodelivery.net/v1/play_session/collection', {
method: 'POST',
headers: {
'Authorization': 'Bearer CLIENT-SIDE-PLAYER-KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
collection_id: 'COLLECTION-ID',
variants: ['hq', 'lq'],
is_downloadable: false,
expires_in: 3600
})
});
const { play_session_id, tracks } = await response.json(); Scope path is /v1/play_session/track or /v1/play_session/collection.
variants is required. Download only when the key allows it and the request sets is_downloadable: true.
Fetch playback resources and play
const response = await fetch(
`https://api.audiodelivery.net/v1/play/${play_session_id}/${track_id}`
);
const { variants } = await response.json();
const url = variants.find((v) => v.variant.index === 'hq' || v.variant.id === 'hq').url; Server-created play session with the AudioDN Player web component
Your server checks entitlement, creates a play session, and passes the session ID to the AudioDN Player web component.
Keep an API Access key on your server
Create an API Access key. Never expose it to the client.
Authorize the listener, then create a play session
// After checking the listener's entitlement on your server:
const response = await fetch('https://api.audiodelivery.net/v1/play_session/collection', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_ACCESS_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
collection_id: 'COLLECTION-ID',
variants: ['hq', 'lq'],
is_downloadable: false,
expires_in: 3600
})
});
const { play_session_id, tracks, first_track } = await response.json(); Return only play_session_id to the client. Full parameter list:
Play Sessions API.
Pass the session to the Player web component
npm install @audiodn/components import '@audiodn/components/player' <audiodn-player
play-session-id="PLAY-SESSION-ID"
></audiodn-player> Server-created play session with a custom player
Your server creates the play session; your custom web or native player uses the returned playback resources.
Keep an API Access key on your server
Server only.
Authorize, then create a play session
// After checking the listener's entitlement on your server:
const response = await fetch('https://api.audiodelivery.net/v1/play_session/collection', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_ACCESS_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
collection_id: 'COLLECTION-ID',
variants: ['hq', 'lq'],
is_downloadable: false,
expires_in: 3600
})
});
const { play_session_id, tracks, first_track } = await response.json(); Fetch variant URLs and play
const track_id = tracks[0].id;
// No auth needed — the play session ID authorizes the request
const response = await fetch(
`https://api.audiodelivery.net/v1/play/${play_session_id}/${track_id}`
);
const { variants } = await response.json();
const hq = variants.find((v) => v.variant.index === 'hq' || v.variant.id === 'hq');
// Use hq.url in your custom player Native examples:
const response = await fetch(
`https://api.audiodelivery.net/v1/play/${play_session_id}/${track_id}`
);
const { variants } = await response.json();
const url = variants.find((v) => v.variant.index === 'hq' || v.variant.id === 'hq').url; Signed delivery without a play session
Your server signs a delivery URL with a URL Signing key. No play session, no API round trip at play time. Possession of the temporary URL grants access until it expires.
Not per-listener entitlement enforcement
Anyone with a valid signed URL can stream until the signature expires. Sign on your server, choose a sensible lifetime, and never expose the signing secret. Signed delivery is a playback option — not an upload method, and not for the AudioDN Player web component.
Create a URL Signing key
In the dashboard create a URL Signing key. The secret is shown once — store it on your server.
Optional: set signature ttl and restrict variants. See
Signing Keys.
Find your delivery domain
Every organization has a delivery host like {organization_id}.audiodelivery.net.
Copy it from Settings → Organization → Delivery Domain.
Sign the URL on your server
function base64url(bytes) {
let binary = '';
const b = new Uint8Array(bytes);
for (let i = 0; i < b.byteLength; i++) binary += String.fromCharCode(b[i]);
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
async function hmacSha256(key, data) {
const cryptoKey = await crypto.subtle.importKey(
'raw', new TextEncoder().encode(key),
{ name: 'HMAC', hash: 'SHA-256' }, false, ['sign']
);
return new Uint8Array(await crypto.subtle.sign('HMAC', cryptoKey, new TextEncoder().encode(data)));
}
// secret = URL Signing key secret (server-side only)
// domain = your org delivery host, e.g. "1bb2....audiodelivery.net"
// path = the file path, e.g. "folder-id/track-index_lq.mp3"
async function signUrl(secret, domain, path) {
const u = new URL('https://' + domain + '/' + path);
u.searchParams.delete('verify');
const message = u.pathname + (u.search || '');
const issued = Math.floor(Date.now() / 1000).toString();
const mac = await hmacSha256(secret, message + issued);
u.searchParams.append('verify', issued + '-' + base64url(mac)); // verify MUST be last
return u.toString();
} // Express example: hand a freshly signed URL to your frontend.
app.get('/api/track-url', async (req, res) => {
const url = await signUrl(
process.env.ADN_SIGNING_SECRET, // never expose to the client
process.env.ADN_DELIVERY_DOMAIN, // e.g. 1bb2....audiodelivery.net
req.query.path
);
res.json({ url });
}); Play in your media interface
<!-- Signed URL works anywhere a normal audio URL does. Not for <audiodn-player>. -->
<audio controls src="https://{org}.audiodelivery.net/{file_path}?verify={issued}-{mac}">
</audio> The AudioDN Player web component uses a Client-Side Player key or play-session-id — not a pre-signed URL.
Plays from signed URLs still count toward usage and billing.