Multi-tenant isolation, API key auth, dual APIs, DDEX parsing, and secure file storage — everything a DSP needs to receive and serve catalog data.
Every organization operates in a fully isolated environment. Attribute-based multi-tenancy ensures every query is automatically scoped to the current tenant — no data leaks between stores, ever.
# API key is scoped to an organization
# The X-Organization-Id header selects the tenant
curl -H "Authorization: Bearer dds_abc123..." \
-H "X-Organization-Id: org_spotify" \
https://your-instance.fly.dev/api/json/releases
Create scoped API keys for each organization. Keys support granular permissions so you can grant exactly the access level needed.
Authorization: Bearer dds_...
# Create a key via the dashboard, then use it:
curl -X GET \
-H "Authorization: Bearer dds_live_a1b2c3d4e5f6..." \
-H "Content-Type: application/vnd.api+json" \
https://your-instance.fly.dev/api/json/releases
Access your catalog through whichever protocol fits your stack. Both APIs are generated from the same Ash resource definitions, so they stay perfectly in sync.
/api/json/swaggerui
/gql/playground
# JSON:API — list releases with artist included
curl -H "Authorization: Bearer dds_..." \
"/api/json/releases?include=artists&filter[title]=Abbey+Road"
# GraphQL — query releases with tracks
curl -X POST /gql \
-H "Authorization: Bearer dds_..." \
-H "Content-Type: application/json" \
-d '{"query": "{ releases { title tracks { title isrc } } }"}'
Upload any ERN XML and we handle the rest. Automatic version detection means you don't need to know whether a label sends 3.8.2 or 4.3 — both work seamlessly.
<!-- ERN 4.3 — auto-detected from namespace -->
<ern:NewReleaseMessage
xmlns:ern="http://ddex.net/xml/ern/43">
<ReleaseList>
<Release>
<ReleaseId>
<ICPN>00602445073658</ICPN>
</ReleaseId>
<ReferenceTitle>Abbey Road</ReferenceTitle>
...
</Release>
</ReleaseList>
</ern:NewReleaseMessage>
Audio files, artwork, and XML are stored on S3-compatible storage (Tigris) with presigned URLs. Every file path is scoped to the owning tenant.
tenants/org/deliveries/id/...
# Files are stored under tenant-isolated paths:
tenants/org_spotify/deliveries/abc123/
├── message.xml
├── audio/
│ ├── track_01.flac
│ └── track_02.flac
└── artwork/
└── cover.jpg
# Presigned URLs provide time-limited access
# without exposing storage credentials
Deliveries are processed asynchronously with Oban workers. PubSub broadcasts status updates in real time, and every step is recorded for a full audit trail.
# Delivery lifecycle:
#
# 1. Upload → Files received, delivery created
# 2. Parsing → XML validated, version detected
# 3. Ingesting → Releases, tracks, artists extracted
# 4. Complete → Data available via API
#
# Each step broadcasts via PubSub:
# "delivery:<id>" → %{status: :parsing}
# "delivery:<id>" → %{status: :complete}
Upload a DDEX XML file and see how it becomes a queryable API in seconds.