The music layer: tracks, albums, playlists, and play reports. One recording, many encodings. The recording is the identity; the files are editions of it.
Musiquay's core music objects are four event kinds:
| Kind | Object | Replaceability |
|---|---|---|
| 32210 | Track — a specific recording, carrying every published digital encoding | Addressable |
| 32211 | Album — an ordered collection of tracks (the release identity) | Addressable |
| 32212 | Playlist — a named, ordered collection of tracks | Addressable |
| 3221 | Play report — a record of a listener playing a track | Regular (immutable) |
Track, album, and playlist are referenced by address (<kind>:<pubkey>:<d-tag>) - never by event id, because they are replaced on every update. Play reports are regular events, referenced by id: one play, one immutable record.
Paid assets add an access layer on top: signed access filters gate the bytes, private delivery receipts record what was served, and host aggregates publish the totals. That layer is specified in FEATURES_ACCESS.md.
A track event identifies the recording — not any particular file. A single track event carries every digital encoding of that recording published to date, each identified by a standard codec specification, each pointing at a Blossom blob.
This mirrors how the physical world works: the vinyl pressing, the CD replication, and the digital master are all editions of the same recording. On Musiquay, the digital encodings are the editions.
The track event is published by the person who took the master, encoded it, and uploaded the binaries — the publisher. That pubkey is the event author and controls the encoding list. The artist or artists are tagged participants, not necessarily the author: an artist can publish their own recordings, or a label/engineer can publish on their behalf (credit confirmation and scene police validation then apply exactly as in FEATURES_CREDITS.md).
A track event is not "file X uploaded by Y." It is "this recording," stable across:
The track event is addressable (replaceable): when a new encoding is released, the publisher republishes the event containing all previous encodings plus the new one. The latest event replaces the previous one, so readers always see the complete encoding set. The address is the permanent identity of the recording; the event id changes with every update, so references MUST use a tags, never e tags.
The track's metadata tags are modeled on the fields that already exist in the wild: ID3 frames (MP3), Vorbis comments, and the MusicBrainz schema. The mapping is explicit so that import tools can translate existing tagged files into track events and vice versa.
Each encoding is a Blossom blob identified by SHA-256. The track event carries one audio tag per encoding: hash, codec spec, server URL, MIME type, size. Downloading follows the existing Blossom/BUD flow; paid assets are gated by the signed access filter described in FEATURES_ACCESS.md.
{
"kind": 32210,
"pubkey": "<publisher-pubkey>",
"content": "Liner notes, recording story, comments.",
"tags": [
["d", "<recording-identifier>"],
["title", "Song Title"],
["artist", "Band Name"],
["p", "<artist-pubkey>", "wss://relay.musiquay.com", "performer"],
["a", "32211:<publisher-pubkey>:<album-d-tag>", "wss://relay.musiquay.com"],
["album", "Album Name"],
["track", "5/12"],
["disc", "1/2"],
["duration", "247.32"],
["genre", "post-punk"],
["t", "postpunk"],
["release-date", "2026-06-15"],
["isrc", "PT-ABC-26-00001"],
["language", "en"],
["bpm", "138"],
["key", "Am"],
["copyright", "CC BY-NC-SA 4.0"],
["price", "500", "sat"],
["image", "<cover-art-sha256>", "https://blossom.musiquay.com"],
["i", "musicbrainz:recording:8be5c8c0-7b52-4a2d-9d4e-1c2f3a4b5c6d"],
["k", "musicbrainz:recording"],
["audio", "<sha256-flac>", "flac-24bit-96kHz", "https://blossom.musiquay.com", "audio/flac", "48216387"],
["audio", "<sha256-mp3-v0>", "mp3-128kbps-VBR", "https://blossom.musiquay.com", "audio/mpeg", "9110334"],
["audio", "<sha256-opus>", "opus-96kbps", "https://blossom.musiquay.com", "audio/ogg", "3942210"],
["x", "<sha256-flac>"],
["x", "<sha256-mp3-v0>"],
["x", "<sha256-opus>"],
["master", "<sha256-flac>"]
]
}
Design notes:
d tag SHOULD be the ISRC (same value as the isrc tag). ISRCs are globally unique per recording, so they make a stable, meaningful address.p tags; artist and publisher are often the same key but are not required to be.audio tags. Single-letter tags are the only ones relays index, so these are what make "which asset does this blob belong to?" a standard query: {"kinds":[32210],"#x":["<sha256>"]}. Hosts need that answer to gate a download, and receipt issuers need it to name the asset in a deed.One audio tag per published encoding:
["audio", "<sha256>", "<codec-spec>", "<blossom-server-url>", "<media-type>", "<size-bytes>"]
| Field | Required | Notes |
|---|---|---|
| sha256 | yes | Blob hash; the identity of the file on Blossom servers |
| codec-spec | yes | Standard codec specification string, see vocabulary below |
| server-url | recommended | Primary Blossom server hosting the blob. Omitted, clients fall back to the publisher's NIP-B7 kind 10063 server list |
| media-type | recommended | MIME type, lowercase (NIP-94 m convention) |
| size-bytes | optional | Blob size (NIP-94 size convention) |
The codec specification string follows a fixed pattern so encodings are comparable, selectable, and renderable without parsing binaries:
<codec>[-<bitrate>kbps[-<VBR|CBR|ABR>] | -<bit-depth>bit-<sample-rate>kHz | -q<quality>]
Examples from the standard vocabulary:
| Encoding | codec-spec | media-type |
|---|---|---|
| MP3, V0 | mp3-128kbps-VBR | audio/mpeg |
| MP3, 320 | mp3-320kbps-CBR | audio/mpeg |
| AAC | aac-256kbps-VBR | audio/mp4 |
| Ogg Vorbis | ogg-vorbis-q8 | audio/ogg |
| Opus | opus-96kbps | audio/ogg |
| FLAC 16-bit | flac-16bit-44.1kHz | audio/flac |
| FLAC 24-bit | flac-24bit-96kHz | audio/flac |
| WAV | wav-24bit-48kHz | audio/wav |
| ALAC | alac-16bit-44.1kHz | audio/mp4 |
This is a convention, not a closed registry. New codecs and rates emerge simply by using new spec strings. The vocabulary guarantees the important property: a client can always tell, from the tag alone, what kind of file it is about to download.
Mapped against the standard tag annotations so existing libraries can import/export directly:
| Tag | ID3 frame | MusicBrainz field | Notes |
|---|---|---|---|
title | TIT2 | Title | Track title |
artist | TPE1 | Artist credit | Free-text artist name; may repeat for multiple artists |
p | — | Artist | Artist npub, optional relay hint, role (performer, featured) |
album | TALB | Release title | Free-text, for display when the album event is absent |
a | — | Release | Address of the album event (kind 32211), when published |
track | TRCK | Track number | "5" or "5/12" |
disc | TPOS | Disc number | "1" or "1/2" |
duration | TLEN | Length | Seconds, floating point (NIP-71 convention) |
genre | TCON | Genre | Free-text; may repeat |
t | — | — | Hashtag form of genre for relay filtering and discovery |
release-date | TDRC | Date | ISO 8601 |
isrc | TSRC | ISRC | Recording identifier, uppercase |
language | TLAN | Language | ISO 639-1 |
bpm | TBPM | BPM | Integer |
key | TKEY | Key | Free-text |
copyright | TCOP | — | License string or SPDX identifier |
price | — | — | Minimum price for paid access: ["price", "<sats>", "sat"]. Absent means free. See FEATURES_ACCESS.md. |
image | APIC | Cover art | ["image", "<sha256>", "<server-url>"], Blossom blob |
i/k | — | MBID | NIP-73 external IDs (see below) |
content | COMM | — | Liner notes, comments |
Per-track credits (songwriters, session musicians, engineers) are not on the track event — they live on the track credits event (kind 32215), which references this track by address.
The i/k tags use NIP-73's external-content-ID mechanism. The MusicBrainz recording ID uses the convention musicbrainz:recording:<mbid> — same pattern as the barcode IDs on edition events. NIP-73's supported-ID table does not yet list these; until the table is extended upstream, the convention works as-is because i/k values are open-ended.
The album event is the release identity: title, artist, release date, artwork, and the ordered list of tracks. It is the anchor that release credits, editions, merch listings, and calendar release events all reference.
Published by the artist or label. Addressable, so track-list corrections, bonus tracks, and reissues replace the previous version. The track list is an ordered list of track addresses (a tags) — order is the track order, identical to MusicBrainz's release → medium → track position model.
{
"kind": 32211,
"pubkey": "<artist-or-label-pubkey>",
"content": "Release notes, album story.",
"tags": [
["d", "<album-identifier>"],
["title", "Album Name"],
["artist", "Band Name"],
["p", "<artist-pubkey>", "wss://relay.musiquay.com", "performer"],
["p", "<label-pubkey>", "wss://relay.musiquay.com", "label"],
["release-date", "2026-06-15"],
["genre", "post-punk"],
["t", "postpunk"],
["language", "en"],
["copyright", "CC BY-NC-SA 4.0"],
["price", "5000", "sat"],
["image", "<cover-art-sha256>", "https://blossom.musiquay.com"],
["i", "musicbrainz:release-group:5c9e6d6c-2c2e-4a7b-9c3f-3a4b5c6d7e8f"],
["k", "musicbrainz:release-group"],
["a", "32210:<publisher-pubkey>:<track-d-1>", "wss://relay.musiquay.com"],
["a", "32210:<publisher-pubkey>:<track-d-2>", "wss://relay.musiquay.com"],
["a", "32210:<publisher-pubkey>:<track-d-3>", "wss://relay.musiquay.com"]
]
}
Design notes:
a tags IS the tracklist. Clients render it in order; there is no separate position field.disc tag, "1/2"); the album list is flat and ordered.i/k tags in addition).Playlists are named, ordered collections of tracks, following NIP-51 set conventions: addressable event with d, title, image, description tags, and the members as a tags (track addresses) in order. This is the direct analog of NIP-51 video sets (kind 30005), applied to tracks.
{
"kind": 32212,
"pubkey": "<curator-pubkey>",
"content": "",
"tags": [
["d", "my-favourite-deep-cuts"],
["title", "My Favourite Deep Cuts"],
["description", "Tracks that never got the attention they deserved."],
["image", "<cover-sha256>", "https://blossom.musiquay.com"],
["a", "32210:<publisher-1>:<track-d-1>", "wss://relay.musiquay.com"],
["a", "32210:<publisher-2>:<track-d-2>", "wss://relay.musiquay.com"],
["a", "32210:<publisher-3>:<track-d-3>", "wss://relay.musiquay.com"]
]
}
Design notes:
.content per NIP-51's private-list scheme (NIP-44, self-key). Shared-with-selected-pubkeys is a client concern — e.g. gift-wrapped copies via NIP-17.Play reports are the listener-side public signal - the auditable counterpart to the private delivery receipts in FEATURES_ACCESS.md. A play report is a regular (immutable) event: one play, one record, never replaced.
{
"kind": 3221,
"pubkey": "<listener-pubkey>",
"content": "",
"tags": [
["a", "32210:<publisher-pubkey>:<track-d-tag>", "wss://relay.musiquay.com"],
["p", "<artist-pubkey>"],
["x", "<blob-sha256-played>"],
["server", "https://blossom.musiquay.com"],
["codec", "mp3-128kbps-VBR"],
["t0", "1758130000"],
["t1", "1758130247"],
["blind", "<unblinded-signature-C-hex>"],
["host", "<serving-host-pubkey>"],
["statement", "<canonical-statement-hex>"],
["dleq", "<e-hex>", "<s-hex>"]
]
}
Design notes:
musiquay.play:v1|<asset-address>|<blob-sha256>|<start>|<end> — because a host that blind-signs an arbitrary statement is a signing oracle. The host blinds Y = hash_to_curve(statement) without seeing the statement; the listener unblinds to C = k*Y and publishes (statement, C, host, dleq).(e, s) is what lets a third party verify log_G(K) == log_Y(C) without the host's key. A paid play report without dleq is not independently verifiable.| and may not contain |.blind, host, or statement tags. Signal, not proof; useful for artists, easily gamed, treated accordingly.COUNT), so immutability matters. A listener can NIP-09-delete their own report, but cannot edit it.audio codec-spec.audio tag on the track event.d:music, expiring when the track ends. Play reports are the record; NIP-38 statuses are the live feed.Musiquay's addressable kinds live in a contiguous block, 32210-32217. The regular kinds are 3221, 3222, 32218, 32219, and 32220 - they must be stored and counted, so they cannot be addressable, replaceable, or ephemeral. All are listed in ARCHITECTURE.md.
| Kind | Name | Replaceability |
|---|---|---|
| 32210 | Track | Addressable |
| 32211 | Album | Addressable |
| 32212 | Playlist | Addressable |
| 32213 | Setlist | Addressable |
| 32214 | Release credits | Addressable |
| 32215 | Track credits | Addressable |
| 32216 | Edition | Addressable |
| 32217 | Access filter | Addressable |
| 3221 | Play report | Regular |
| 3222 | Purchase order | Regular (private, NIP-59 only) |
| 32218 | Delivery receipt | Regular |
| 32219 | Host aggregate | Regular |
| 32220 | Publisher rollup | Regular |
The block and the regular kinds were re-checked free of collisions in the registry of kinds on 2026-09-28. They should be registered there once implementation begins.
| Concept | NIP Status | Notes |
|---|---|---|
| Track event (32210) | Custom kind | No existing NIP defines a recording; WaveLake 32123 is dead prior art with no spec. |
| Album event (32211) | Custom kind | No existing NIP defines a release. |
| Playlist (32212) | Custom kind, NIP-51 set conventions | Addressable with d/title/image/description; analog of kind 30005 video sets. |
| Play report (3221) | Custom kind | Listener-side signal; BDHKE blind signature certifies paid plays. |
| Access filter (32217) | Custom kind | Signed probabilistic access set; see FEATURES_ACCESS.md. |
| Delivery receipt (32218) | Custom kind, NIP-59 | Private host-signed deed. |
| Host aggregate (32219) | Custom kind | Public host-signed totals. |
| Publisher rollup (32220) | Custom kind | Public publisher-signed consolidation referencing 32219 events. |
| Replaceable semantics | NIP-01 | Parameterized replaceable kinds (30000-39999), d tag |
| Blob identity | NIP-94 conventions | x sha256, m MIME, size; one single-letter x tag per encoding so blob → asset is a #x query |
| Blossom servers | NIP-B7 | Server fallback via publisher's kind 10063 list when server-url omitted |
| Media authorization | BUD-11 | Signed kind 24242 presented as Authorization: Nostr <base64url>; this is how a host identifies a requester |
| Duration | NIP-71 convention | Seconds, floating point |
| External IDs | NIP-73 | i/k for ISRC, MusicBrainz recording/release-group IDs |
| Paid access | Custom filters + NUT-24/BUD-07 + NUT-00 BDHKE | See FEATURES_ACCESS.md |
| Addressing | NIP-19 | naddr codes for sharing |
| Live now-playing | NIP-38 | kind 30315 d:music status, the social companion to play reports |