Distributor hub
API reference
Every endpoint of the distributor API, with examples.
The API is plain HTTPS and JSON. Every request carries your key; errors come back with a status code and an error field that says in plain words what to change.
| Base address | https://www.listnmusic.ai/api/feed/v1 |
|---|---|
| Key | Authorization: Bearer lbxf_... on every request |
| Limits | 240 requests a minute; 60 a minute for /validate |
| Errors | 401 wrong or missing key, 403 deliveries paused for your account, 404 not found, 409 wrong state, 422 something to fix, 503 deliveries closed for now |
GET /ping
Checks your key. Returns your account, your SFTP login when it is on, and the formats we take.
curl -H "Authorization: Bearer $KEY" https://www.listnmusic.ai/api/feed/v1/ping
{"ok": true, "store": "LISTN AI", "distributor": {"name": "Sample Distributor", "id": "sample"},
"sftp": {"host": "...", "port": 2022, "username": "sample"},
"formats": {"audio": ["wav", "flac", "aiff", "mp3"], "ern": ["3.8.x", "4.1", "4.2", "4.3"]}}
POST /validate
The sandbox. Send one ERN message and see what a delivery of it would do. Nothing is changed. Send the XML as the body with Content-Type: application/xml, or JSON {"xml": "..."}. See Sandbox and testing.
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/xml" \
--data-binary @0123456789012.xml https://www.listnmusic.ai/api/feed/v1/validate
POST /deliveries
Starts a delivery. List every file with its path (relative, as the message refers to it) and size in bytes; md5 is optional. Up to 1,000 files. At least one must be an ERN message.
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" https://www.listnmusic.ai/api/feed/v1/deliveries -d '{
"files": [
{"path": "0123456789012/0123456789012.xml", "size": 5120},
{"path": "0123456789012/resources/QZXXX2600001.flac", "size": 31457280, "md5": "0123456789abcdef0123456789abcdef"},
{"path": "0123456789012/resources/cover.jpg", "size": 812345}
]}'
201 {"id": 42, "status": "receiving", ..., "uploads": [
{"path": "0123456789012/0123456789012.xml", "method": "PUT", "url": "https://..."}, ...]}
Then upload each file: curl -X PUT --upload-file 0123456789012.xml "<url>". No other headers are needed.
POST /deliveries/{id}/links
New upload links for a delivery that is still receiving (the first ones last 12 hours).
POST /deliveries/{id}/complete
Call it when every file is uploaded. We check that each one arrived at the size you gave. If any did not, you get 422 with missing and wrong_size lists: upload those again and call complete again. Otherwise the delivery is read within five minutes.
GET /deliveries and /deliveries/{id}
Your deliveries, newest first, 25 a page (?page=2). One delivery adds each message with its status (waiting, done, failed), its kind (new, update, takedown), the error when it failed, the notes we made, and the release it made or changed.
{"id": 42, "status": "done", "status_text": "Read", "messages": [
{"file": "0123456789012/0123456789012.xml", "status": "done", "kind": "new", "upc": "0123456789012",
"title": "First Light", "error": null, "notes": [],
"release": {"upc": "0123456789012", "status": "in_review", "on_sale": false, "url": null}}]}
GET /releases/{upc}
Where a release stands: processing, in_review, scheduled (with goes_live), live (with its url), rejected (with a note) or taken_down, and each track with its ISRC and whether it is live.
GET /sales?month=2026-09
Your streams and what they earned in a month: one line per track, Premium and free streams apart, and total_net_due. Add &format=csv for a spreadsheet.
