NIP-53 ====== Live Activities --------------- `draft` `optional` Service providers want to offer live activities to the Nostr network in such a way that participants can easily log and query by clients. This NIP describes a general framework to advertise the involvement of pubkeys in such live activities. ## Concepts ### Live Event A special event with `kind:30311` "Live Event" is defined as an _addressable event_ of public `p` tags. Each `p` tag SHOULD have a **displayable** marker name for the current role (e.g. `Host`, `Speaker`, `Participant`) of the user in the event and the relay information MAY be empty. This event will be constantly updated as participants join and leave the activity. For example: ```jsonc { "kind": 30311, "tags": [ ["d", ""], ["title", ""], ["summary", ""], ["image", ""], ["t", "hashtag"] ["streaming", ""], ["recording", ""], // used to place the edited video once the activity is over ["starts", ""], ["ends", ""], ["status", ""], ["current_participants", ""], ["total_participants", ""], ["p", "91cf9..4e5ca", "wss://provider1.com/", "Host", ""], ["p", "14aeb..8dad4", "wss://provider2.com/nostr", "Speaker"], ["p", "612ae..e610f", "ws://provider3.com/ws", "Participant"], ["relays", "wss://one.com", "wss://two.com", /*...*/], ["pinned", ""], ], "content": "", // other fields... } ``` A distinct `d` tag should be used for each activity. All other tags are optional. Providers SHOULD keep the participant list small (e.g. under 1000 users) and, when limits are reached, Providers SHOULD select which participants get named in the event. Clients should not expect a comprehensive list. Once the activity ends, the event can be deleted or updated to summarize the activity and provide async content (e.g. recording of the event). Clients are expected to subscribe to `kind:30311` events in general or for given follow lists and statuses. Clients MAY display participants' roles in activities as well as access points to join the activity. Live Activity management clients are expected to constantly update `kind:30311` during the event. Clients MAY choose to consider `status=live` events after 1hr without any update as `ended`. The `starts` and `ends` timestamp SHOULD be updated when the status changes to and from `live` The activity MUST be linked to using the [NIP-19](19.md) `naddr` code along with the `a` tag. ### Proof of Agreement to Participate Event owners can add proof as the 5th term in each `p` tag to clarify the participant's agreement in joining the event. The proof is a signed SHA256 of the complete `a` Tag of the event (`kind:pubkey:dTag`) by each `p`'s private key, encoded in hex. Clients MAY only display participants if the proof is available or MAY display participants as "invited" if the proof is not available. This feature is important to avoid malicious event owners adding large account holders to the event, without their knowledge, to lure their followers into the malicious owner's trap. ### Live Chat Message Event `kind:1311` is live chat's channel message. Clients MUST include the `a` tag of the activity. An `e` tag denotes the direct parent message this post is replying to. ```jsonc { "kind": 1311, "tags": [ ["a", "30311::", "", "root"], ], "content": "Zaps to live streams is beautiful.", // other fields... } ``` `q` tags MAY be used when citing events in the `.content` with [NIP-21](21.md). ```json ["q", " or ", "", ""] ``` Hosts may choose to pin one or more live chat messages by updating the `pinned` tags in the live event kind `30311`. ## Use Cases Common use cases include meeting rooms/workshops, watch-together activities, or event spaces, such as [zap.stream](https://zap.stream). ## Example ### Live Streaming ```json { "id": "57f28dbc264990e2c61e80a883862f7c114019804208b14da0bff81371e484d2", "pubkey": "1597246ac22f7d1375041054f2a4986bd971d8d196d7997e48973263ac9879ec", "created_at": 1687182672, "kind": 30311, "tags": [ ["d", "demo-cf-stream"], ["title", "Adult Swim Metalocalypse"], ["summary", "Live stream from IPTV-ORG collection"], ["streaming", "https://adultswim-vodlive.cdn.turner.com/live/metalocalypse/stream.m3u8"], ["starts", "1687182672"], ["status", "live"], ["t", "animation"], ["t", "iptv"], ["image", "https://i.imgur.com/CaKq6Mt.png"] ], "content": "", "sig": "5bc7a60f5688effa5287244a24768cbe0dcd854436090abc3bef172f7f5db1410af4277508dbafc4f70a754a891c90ce3b966a7bc47e7c1eb71ff57640f3d389" } ``` ### Live Streaming chat message ```json { "id": "97aa81798ee6c5637f7b21a411f89e10244e195aa91cb341bf49f718e36c8188", "pubkey": "3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24", "created_at": 1687286726, "kind": 1311, "tags": [ ["a", "30311:1597246ac22f7d1375041054f2a4986bd971d8d196d7997e48973263ac9879ec:demo-cf-stream", "", "root"] ], "content": "Zaps to live streams is beautiful.", "sig": "997f62ddfc0827c121043074d50cfce7a528e978c575722748629a4137c45b75bdbc84170bedc723ef0a5a4c3daebf1fef2e93f5e2ddb98e5d685d022c30b622" } ``` ## Interactive Rooms and Meetings ----- `draft` `optional` Service providers want to offer Interactive Rooms to the Nostr network in such a way that participants can easily log and query by clients. This NIP describes a general framework to advertise rooms and their associated events. ## Concepts ### Interactive Room (kind:30312) A special event with `kind:30312` "Interactive Room" defines the configuration and properties of a virtual interactive space. Each room has a unique identifier and can host multiple events/meetings. ```jsonc { "kind": 30312, "tags": [ ["d", ""], // Required: Room identifier ["room", ""], // Required: Display name ["summary", ""], // Optional: Room description ["image", ""], // Optional: Room image ["status", ""], // Required: Room accessibility ["service", ""], // Required: URL to access the room ["endpoint", ""], // Optional: API endpoint for status/info ["t", ""], // Optional: Multiple hashtags allowed ["p", "", "", "", ""], // Required: At least one provider ["relays", "", "", /*...*/] // Optional: Preferred relays ], "content": "" // Usually empty, may contain additional metadata } ``` Room properties: * MUST be either open, private or closed. Closed means the room is not in operation. * MAY specify access control policy for private rooms (e.g. invite-only, payment required) * MAY persist when not in use * MUST have at least one provider with "Host" role * MAY have multiple providers with different roles Provider roles (p tags): * Host: Full room management capabilities * Moderator: Room moderation capabilities * Speaker: Allowed to present/speak * Optional proof field for role verification ### Room Meeting (kind:30313) A special event with kind:30313 represents a scheduled or ongoing meeting within a room. It MUST reference its parent room using the d tag. ```jsonc { "kind": 30313, "tags": [ ["d", ""], // Required: Event identifier ["a", "30312::", "wss://nostr.example.com"], // Required: Reference to parent room, 'd' from 30312 ["title", ""], // Required: Meeting title ["summary", ""], // Optional: Meeting description ["image", ""], // Optional: Meeting image ["starts", ""], // Required: Start time ["ends", ""], // Optional: End time ["status", ""], // Required: Meeting status ["total_participants", ""], // Optional: Total registered ["current_participants", ""], // Optional: Currently active ["p", "", "", ""], // Optional: Participant with role ], "content": "" // Usually empty, may contain additional metadata } ``` Event properties: * MUST reference parent room via d tag * MUST have a status (planned/live/ended) * MUST have a start time * MAY track participant counts * MAY include participant roles specific to the event Event management: * Clients SHOULD update event status regularly when live * Events without updates for 1 hour MAY be considered ended * starts and ends timestamps SHOULD be updated when status changes Examples Interactive Room (kind:30312) ```jsonc { "kind": 30312, "tags": [ ["d", "main-conference-room"], ["room", "Main Conference Hall"], ["summary", "Our primary conference space"], ["image", "https://example.com/room.jpg"], ["status", "open"], ["service", "https://meet.example.com/room"], ["endpoint", "https://api.example.com/room"], ["t", "conference"], ["p", "f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca", "wss://nostr.example.com/", "Owner"], ["p", "14aeb..8dad4", "wss://provider2.com/", "Moderator"], ["relays", "wss://relay1.com", "wss://relay2.com"] ], "content": "" } ``` Conference Event (kind:30313) ```jsonc { "kind": 30313, "tags": [ ["d", "annual-meeting-2025"], ["a", "30312:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:main-conference-room", "wss://nostr.example.com"] ["title", "Annual Company Meeting 2025"], ["summary", "Yearly company-wide meeting"], ["image", "https://example.com/meeting.jpg"], ["starts", "1676262123"], ["ends", "1676269323"], ["status", "live"], ["total_participants", "180"], ["current_participants", "175"], ["p", "91cf9..4e5ca", "wss://provider1.com/", "Speaker"], ], "content": "" } ``` ## Room Presence New `kind: 10312` provides an event which signals presence of a listener. The presence event SHOULD be updated at regular intervals and clients SHOULD filter presence events older than a given time window. **This kind `10312` is a regular replaceable event, as such presence can only be indicated in one room at a time.** ```json { "kind": 10312, "tags": [ ["a" , "", "", "root"], ["hand", "1"] // hand raised flag ] } ```