Releases
Once your assets are uploaded, you can save a draft and submit a release for distribution. All endpoints require authentication.
Read the rules first
Before building payloads, read GET /v1/metadata-rules (artist-name policy,
title casing, writers, UPC, AI disclosure, cover songs) and
GET /v1/release-schema (authoritative required fields and an example
payload). Use GET /v1/distribution-stores to fetch supported DSP IDs before
setting release.distribution_store_ids. The platform enforces these rules at
submission, so reading them first saves you rejected requests.
curl https://once.app/v1/metadata-rules
curl -H "Authorization: Bearer $ONCE_ACCESS_TOKEN" https://once.app/v1/release-schema
curl https://once.app/v1/distribution-storesDrafts
curl -X POST https://once.app/v1/drafts \
-H "Authorization: Bearer $ONCE_ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "release": { ... }, "tracks": [ ... ], "mode": "delta" }'POST /v1/drafts upserts a work-in-progress release snapshot. Body:
{ "release"?, "tracks"?, "track_patches"?, "upload_requests"?, "status"?, "mode"?: "delta" | "replace", "release_id"?, "conversation_id"? }. Use
mode: "delta" to patch an existing draft or mode: "replace" to overwrite
it.
Submit a release
curl -X POST https://once.app/v1/releases \
-H "Authorization: Bearer $ONCE_ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "release": { ... }, "tracks": [ ... ] }'POST /v1/releases submits the release for distribution and returns 201.
Build the body from GET /v1/release-schema, attaching the fileUrls returned
by your uploads and cover-art calls. Submission debits credits from your
account (1 credit per human song, 2 per AI-detected song). Releases are
distributed to all supported stores unless release.distribution_store_ids
selects specific DSPs.
New clients should provide DSP selection, record label, C/P copyright credits, track type, and Producer/Engineer role credits explicitly. Existing v1 clients that omit those expanded fields continue to work with ONCE’s server defaults.
{
"release": {
"title": "My Release",
"primary_artist_name": "Artist Name",
"genre": "Pop",
"sub_genre": "Dance Pop",
"release_date": "2026-02-01",
"label": "Artist Name Records",
"audio_language": "en",
"metadata_language": "en",
"distribution_store_ids": [1, 9, 13, 319],
"pline_year": "2026",
"pline_owner": "Artist Name Records",
"cline_year": "2026",
"cline_owner": "Artist Name Records",
"cover_art_file_url": "/api/files/cover-art/USER_ID/cover.jpg",
"contributors": [
{ "name": "First Producer", "role": "Producer" },
{ "name": "First Engineer", "role": "Engineer" }
]
},
"tracks": [
{
"title": "My Release",
"primary_artist_name": "Artist Name",
"audio_file_url": "/api/files/audio/USER_ID/track.wav",
"explicit_flag": false,
"track_type": "original",
"language": "en",
"pline_year": "2026",
"pline_owner": "Artist Name Records",
"cline_year": "2026",
"cline_owner": "Artist Name Records",
"writers": [{ "name": "First Last" }],
"contributors": [
{ "name": "First Producer", "role": "Producer" },
{ "name": "First Engineer", "role": "Engineer" }
]
}
]
}For DSP selection, pass a non-empty distribution_store_ids array using store
IDs from GET /v1/distribution-stores, or pass null to explicitly choose all
supported stores. Do not send an empty array.
For remixes, do not send remix as track_type. Use title_version: "Remix"
and include a Remixer contributor when applicable.
Partners can attach the X-Once-Provenance header (e.g. AIMD) so the release
is attributed to their surface.
After submission, poll release status to follow delivery.
List releases
curl -H "Authorization: Bearer $ONCE_ACCESS_TOKEN" \
'https://once.app/v1/releases?limit=100'GET /v1/releases returns recent releases for the authenticated user
(limit-only paging). GET /v1/releases/:id returns the merged metadata for a
single release (its draft snapshot or latest merged data).