clone

every nostr nip as a chapter of an illustrated, early-2000s printed game manual

main
nip.guide / site / nips / a4.html
a4.html 20.9K
1<!DOCTYPE html>2<html lang="en">3<head>4<meta charset="utf-8">5<meta name="viewport" content="width=device-width, initial-scale=1">6<title>NIP-A4 - Public Messages — Nostr Instruction Manual</title>7<meta name="description" content="NIP-A4: kind 24 public messages. Plaintext notes addressed to one or more users, delivered to their inbox relays, with no threads and no privacy. Complete manual page.">8<link rel="preload" href="../assets/fonts/michroma-400-latin.woff2" as="font" type="font/woff2" crossorigin>9<link rel="preload" href="../assets/fonts/exo2-var-latin.woff2" as="font" type="font/woff2" crossorigin>10<link rel="preload" href="../assets/fonts/sairacondensed-600-latin.woff2" as="font" type="font/woff2" crossorigin>11<link rel="preload" href="../assets/fonts/sairacondensed-700-latin.woff2" as="font" type="font/woff2" crossorigin>12<link rel="preload" href="../assets/fonts/sairacondensed-500-latin.woff2" as="font" type="font/woff2" crossorigin>13<link rel="preload" href="../assets/fonts/sharetechmono-400-latin.woff2" as="font" type="font/woff2" crossorigin>14<link rel="preload" href="../assets/fonts/exo2-400i-latin.woff2" as="font" type="font/woff2" crossorigin>15<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">16<link rel="stylesheet" href="../assets/manual.css">17</head>18<body>1920<svg width="0" height="0" style="position:absolute">21 <defs>22 <marker id="arr" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">23 <path d="M1,1 L8,4.5 L1,8 Z" fill="#f26a00"/>24 </marker>25 <marker id="arrb" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">26 <path d="M1,1 L8,4.5 L1,8 Z" fill="#2e5f9e"/>27 </marker>28 </defs>29</svg>3031<div class="page">32 <span class="staple s1"></span><span class="staple s2"></span>3334 <header class="band">35 <a class="logo" href="../index.html">NOSTR<b>▸</b>PROTOCOL MANUAL</a>36 <span class="booklet-note">Chapter A4 - Messaging</span>37 </header>38 <nav class="tabs">39 <a href="../index.html">Contents</a>40 <a href="#overview" class="on">Overview</a>41 <a href="#spec">Spec</a>42 <a href="#examples">Examples</a>43 <a href="#history">History</a>44 </nav>4546 <div class="chapter">47 <div class="nipno" data-n="A4">A4</div>48 <div class="titles">49 <div class="kicker">Nostr Implementation Possibility - Hex № A4</div>50 <h1>Public Messages</h1>51 <p class="sub">A signed plaintext message to one or more users - delivered to their inbox relays, shown on notification screens, with no threads and no privacy.</p>52 </div>53 </div>5455 <main class="spread">56 <div class="main">5758 <h2 class="bar" id="overview"><span class="num">1</span> Overview</h2>59 <p>Sometimes you want to say something <em>to</em> someone, not <em>about</em> something. A reply needs a root note. A <a href="17.html">NIP-17</a> direct message needs encryption and gift wraps. This NIP defines a third option: the <strong>public message</strong>, event kind <code>24</code>.</p>60 <p>A public message is a plain <a href="01.html">NIP-01</a> event. The <code>content</code> holds the message text. One or more <code>p</code> tags name the receivers. That is the whole format.</p>61 <p>The design target is the <strong>notification screen</strong>. A client shows the message as a notification. The user replies from the same screen. The client does not fetch chat history, because there is none. There are no message chains, no threads, no thread roots, and no chatrooms. Messages start and continue without any syntactic connection to each other.</p>6263 <div class="box hint">64 <span class="tag">Hint!</span>65 <p>Think of kind <code>24</code> as a postcard. It is addressed to someone, anyone who handles it can read it, and it does not come bound in an album. If you need an envelope, use <a href="17.html">NIP-17</a> instead.</p>66 </div>6768 <h2 class="bar" id="spec"><span class="num">2</span> The Kind 24 Event</h2>69 <p>Kind <code>24</code> is a regular event under the <a href="01.html">NIP-01</a> storage classes. Relays store all of them. The wire format is:</p>7071 <div class="crt">72 <div class="titlebar">Wire format - kind 24 public message</div>73<pre>{74 <span class="k">"pubkey"</span>: <span class="c">&lt;sender pubkey&gt;</span>,75 <span class="k">"kind"</span>: 24,76 <span class="k">"tags"</span>: [77 [<span class="s">"p"</span>, <span class="c">&lt;receiver pubkey&gt;</span>, <span class="c">&lt;relay URL&gt;</span>]78 <span class="c">... one "p" tag per receiver ...</span>79 ],80 <span class="k">"content"</span>: <span class="c">&lt;message in plain text&gt;</span>81 <span class="c">... plus the usual id, created_at, sig ...</span>82}</pre>83 </div>8485 <div class="tscroll"><table class="ref">86 <caption>Field and tag reference</caption>87 <tr><th>Item</th><th>Rule</th></tr>88 <tr><td class="btn">kind</td><td>Always <code>24</code>.</td></tr>89 <tr><td class="btn">content</td><td>The message, in plain text.</td></tr>90 <tr><td class="btn">p</td><td>One tag per receiver: <code>["p", &lt;receiver&gt;, &lt;relay-url&gt;]</code>. One or more receivers.</td></tr>91 <tr><td class="btn">e</td><td><strong>Must not be used.</strong> There are no threads to point at.</td></tr>92 </table></div>9394 <div class="box warn">95 <span class="tag">Warning!</span>96 <p>Do not add <code>e</code> tags to a kind <code>24</code> event. A public message never references a parent. A reply to a public message is just another public message with a <code>p</code> tag for the other user.</p>97 </div>9899 <div class="box tech">100 <span class="tag">Tech Note</span>101 <p>The source spec fences its event template as YAML (it was <code>jsonc</code> until 2026-06) and the template contains a trailing comma. It is not valid JSON as written. Build the event as a normal <a href="01.html">NIP-01</a> JSON object with <code>id</code>, <code>created_at</code>, and <code>sig</code> included.</p>102 </div>103104 <h2 class="bar" id="delivery"><span class="num">3</span> Delivery and Display</h2>105 <p>Routing follows the <a href="65.html">NIP-65</a> outbox model, but in the inbox direction. Clients <strong>must</strong> send the event to the <a href="65.html">NIP-65</a> inbox relays of each receiver. Clients must also send it to the outbox relay of the sender.</p>106107 <figure class="diagram">108 <div class="frame">109 <svg viewBox="0 0 560 200" role="img" aria-label="Sender publishes a kind 24 event to each receiver's inbox relays and to the sender's own outbox relay">110 <rect class="d-actor" x="10" y="75" width="110" height="50" rx="8"/>111 <text class="d-actor-label" x="65" y="97" text-anchor="middle">Sender</text>112 <text class="d-note" x="65" y="114" text-anchor="middle">client</text>113 <rect class="d-actor" x="240" y="14" width="130" height="44" rx="8"/>114 <text class="d-actor-label" x="305" y="36" text-anchor="middle">Inbox relay</text>115 <text class="d-note" x="305" y="51" text-anchor="middle">receiver A</text>116 <rect class="d-actor" x="240" y="78" width="130" height="44" rx="8"/>117 <text class="d-actor-label" x="305" y="100" text-anchor="middle">Inbox relay</text>118 <text class="d-note" x="305" y="115" text-anchor="middle">receiver B</text>119 <rect class="d-actor" x="240" y="142" width="130" height="44" rx="8"/>120 <text class="d-actor-label" x="305" y="164" text-anchor="middle">Outbox relay</text>121 <text class="d-note" x="305" y="179" text-anchor="middle">sender</text>122 <rect class="d-actor" x="440" y="14" width="110" height="44" rx="8"/>123 <text class="d-actor-label" x="495" y="36" text-anchor="middle">Client A</text>124 <text class="d-note" x="495" y="51" text-anchor="middle">notification</text>125 <rect class="d-actor" x="440" y="78" width="110" height="44" rx="8"/>126 <text class="d-actor-label" x="495" y="100" text-anchor="middle">Client B</text>127 <text class="d-note" x="495" y="115" text-anchor="middle">notification</text>128 <path class="d-msg d-flow" d="M122,88 C170,70 190,48 237,38"/>129 <path class="d-msg d-flow" d="M122,100 L237,100"/>130 <path class="d-msg d-flow" d="M122,112 C170,130 190,152 237,162"/>131 <path class="d-msg blue d-flow" d="M372,36 L437,36"/>132 <path class="d-msg blue d-flow" d="M372,100 L437,100"/>133 <text class="d-label" x="178" y="52" text-anchor="middle">EVENT k24</text>134 <text class="d-label" x="404" y="24" text-anchor="middle">REQ #p</text>135 <circle r="4" fill="#f26a00">136 <animateMotion dur="2.6s" repeatCount="indefinite" path="M122,88 C170,70 190,48 237,38"/>137 </circle>138 <circle r="4" fill="#2e5f9e">139 <animateMotion dur="2.6s" begin="1.3s" repeatCount="indefinite" path="M372,36 L437,36"/>140 </circle>141 </svg>142 </div>143 <figcaption>Fig. A4-1 — <b>Delivery routing.</b> The sender writes to every receiver's inbox relays plus the sender's own outbox relay. Receivers watch their inboxes for <code>p</code> tags.</figcaption>144 </figure>145146 <p>Display rules are just as strict as routing rules:</p>147 <ul>148 <li>Kind <code>24</code> is designed to be shown on notification screens. Users reply from there.</li>149 <li>The goal is that clients support this feature without chat history. No thread, no thread root, no chatroom exists in this system.</li>150 <li>Kind <code>24</code> is not designed to be displayed on feeds.</li>151 <li>Anyone can see and reply to a message, even a message that is not for them.</li>152 </ul>153154 <figure class="diagram">155 <div class="frame">156 <svg viewBox="0 0 560 150" role="img" aria-label="A threaded conversation chains events with e tags; public messages are standalone events with only p tags">157 <text class="d-actor-label" x="10" y="20">Thread (kind 1)</text>158 <rect class="d-actor" x="10" y="34" width="76" height="30" rx="6"/>159 <text class="d-label" x="48" y="53" text-anchor="middle">root</text>160 <rect class="d-actor" x="126" y="34" width="76" height="30" rx="6"/>161 <text class="d-label" x="164" y="53" text-anchor="middle">reply</text>162 <rect class="d-actor" x="242" y="34" width="76" height="30" rx="6"/>163 <text class="d-label" x="280" y="53" text-anchor="middle">reply</text>164 <path class="d-msg" d="M124,49 L90,49"/>165 <path class="d-msg" d="M240,49 L206,49"/>166 <text class="d-note" x="400" y="53">"e" tags chain each reply to a parent</text>167 <text class="d-actor-label" x="10" y="98">Public messages (kind 24)</text>168 <rect class="d-actor" x="10" y="110" width="76" height="30" rx="6"/>169 <text class="d-label" x="48" y="129" text-anchor="middle">msg</text>170 <rect class="d-actor" x="126" y="110" width="76" height="30" rx="6"/>171 <text class="d-label" x="164" y="129" text-anchor="middle">msg</text>172 <rect class="d-actor" x="242" y="110" width="76" height="30" rx="6"/>173 <text class="d-label" x="280" y="129" text-anchor="middle">msg</text>174 <text class="d-note" x="400" y="129">no links - only "p" tags name receivers</text>175 </svg>176 </div>177 <figcaption>Fig. A4-2 — <b>No chains.</b> Threads link events together. Public messages never do. Each message stands alone.</figcaption>178 </figure>179180 <h2 class="bar" id="advanced"><span class="num">4</span> Advanced Support</h2>181 <p>Kind <code>24</code> composes with several other NIPs. The rules below come straight from the spec:</p>182183 <div class="tscroll"><table class="ref">184 <caption>Interop rules</caption>185 <tr><th>Feature</th><th>Level</th><th>Rule</th></tr>186 <tr><td class="btn">expiration</td><td><span class="kbd">RECOMMENDED</span></td><td>Add a <a href="40.html">NIP-40</a> <code>expiration</code> tag. Without a chatroom, old messages stop making sense as time goes on.</td></tr>187 <tr><td class="btn">q</td><td><span class="kbd">MAY</span></td><td>Use a <a href="18.html">NIP-18</a> quote-repost <code>q</code> tag when the <code>content</code> cites an event with a <a href="21.html">NIP-21</a> URI.</td></tr>188 <tr><td class="btn">k (reactions)</td><td><span class="kbd">MUST</span></td><td>A <a href="25.html">NIP-25</a> reaction to a public message must carry a <code>k</code> tag with value <code>24</code>.</td></tr>189 <tr><td class="btn">k (zaps)</td><td><span class="kbd">MUST</span></td><td>A <a href="57.html">NIP-57</a> zap on a public message must include the <code>k</code> tag with value <code>24</code>.</td></tr>190 <tr><td class="btn">nevent links</td><td><span class="kbd">MUST</span></td><td>A <a href="21.html">NIP-21</a> link that uses a <a href="19.html">NIP-19</a> <code>nevent1</code> must include a <code>kind</code> of <code>24</code>. Clients are not expected to render non-<code>kind:24</code> links natively.</td></tr>191 <tr><td class="btn">imeta</td><td><span class="kbd">SHOULD</span></td><td>Add <a href="92.html">NIP-92</a> <code>imeta</code> tags for image and video links in the <code>content</code>.</td></tr>192 </table></div>193194 <p>The <code>q</code> tag has the standard <a href="18.html">NIP-18</a> shape:</p>195 <div class="crt">196 <div class="titlebar">Quote tag format</div>197<pre>[<span class="s">"q"</span>, <span class="c">&lt;event-id&gt; or &lt;event-address&gt;</span>, <span class="c">&lt;relay-url&gt;</span>, <span class="c">&lt;pubkey-if-a-regular-event&gt;</span>]</pre>198 </div>199200 <div class="box tech">201 <span class="tag">Tech Note</span>202 <p>The reaction and zap rules place a MUST on <em>other</em> kinds (<a href="25.html">NIP-25</a> kind <code>7</code> and <a href="57.html">NIP-57</a> zap requests), not on kind <code>24</code> itself. A kind <code>24</code> publisher cannot enforce them. Clients that react to or zap public messages carry the obligation.</p>203 </div>204205 <h2 class="bar" id="warnings"><span class="num">5</span> Warnings</h2>206 <div class="box danger">207 <span class="tag">Warning!</span>208 <p>There must be <strong>no expectation of privacy</strong> in kind <code>24</code>. A public message is just a public reply without a root note. Every relay and every user can read it.</p>209 </div>210 <p>Do not confuse this kind with kind <code>14</code> rumors in <a href="17.html">NIP-17</a> direct messages. A kind <code>14</code> rumor is unsigned and travels sealed and gift-wrapped. A kind <code>24</code> event is signed and designed for public consumption. Never route private text through kind <code>24</code>.</p>211212 <h2 class="bar" id="examples"><span class="num">6</span> Worked Example</h2>213 <p>Alice thanks Bob for a talk. Her client signs a kind <code>24</code> event and publishes it to Bob's inbox relay and to her own outbox relay. Bob's client watches his inbox for <code>#p</code> matches and raises a notification.</p>214215 <div class="crt">216 <div class="titlebar">Event - full kind 24 message</div>217<pre>{218 <span class="k">"id"</span>: <span class="s">"7ac66f21d3…"</span>,219 <span class="k">"pubkey"</span>: <span class="s">"a11ce4f2b9…"</span>, <span class="c">// Alice</span>220 <span class="k">"created_at"</span>: 1765990800,221 <span class="k">"kind"</span>: 24,222 <span class="k">"tags"</span>: [223 [<span class="s">"p"</span>, <span class="s">"b0bd7e881c…"</span>, <span class="s">"wss://inbox.bob.example"</span>],224 [<span class="s">"expiration"</span>, <span class="s">"1766595600"</span>]225 ],226 <span class="k">"content"</span>: <span class="s">"Great talk today. The relay section clicked for me."</span>,227 <span class="k">"sig"</span>: <span class="s">"90c1f2ab44…"</span>228}</pre>229 </div>230231 <div class="crt">232 <div class="titlebar">Session transcript - delivery and reply</div>233<pre><span class="c">-- Alice's client, on wss://inbox.bob.example and her outbox relay --</span>234<span class="send">→ ["EVENT", {"id":"7ac66f21d3…","kind":24,"tags":[["p","b0bd7e881c…",235 "wss://inbox.bob.example"],["expiration","1766595600"]],236 "content":"Great talk today. The relay section clicked for me.", …}]</span>237<span class="recv">← ["OK", "7ac66f21d3…", true, ""]</span>238239<span class="c">-- Bob's client, watching his inbox relay --</span>240<span class="send">→ ["REQ", "notif", {"kinds":[24], "#p":["b0bd7e881c…"]}]</span>241<span class="recv">← ["EVENT", "notif", {"id":"7ac66f21d3…", "kind":24, …}]</span>242<span class="recv">← ["EOSE", "notif"]</span>243244<span class="c">-- Bob replies from the notification: a new standalone kind 24 --</span>245<span class="send">→ ["EVENT", {"id":"c3d901aa72…","kind":24,"tags":[["p","a11ce4f2b9…",246 "wss://inbox.alice.example"]],"content":"Thanks! Come back next month.", …}]</span>247<span class="recv">← ["OK", "c3d901aa72…", true, ""]</span></pre>248 </div>249 <p>Note the reply. It has no <code>e</code> tag and no reference to Alice's event. It is a fresh message with a <code>p</code> tag for Alice, sent to <em>her</em> inbox relays.</p>250251 <h2 class="bar" id="history"><span class="num">7</span> Version History</h2>252 <p>NIP-A4 is young and has barely changed since it landed. Notable changes, newest first:</p>253 <ul class="patchnotes">254 <li class="minor"><span class="ver">2026</span><span class="when">2026-06</span>Repository-wide cleanup switched the event template's code fence from <code>jsonc</code> to <code>yaml</code>. No rule changed.</li>255 <li><span class="ver">Origin</span><span class="when">2025-12</span>Vitor Pamplona proposed kind <code>24</code> public messages in PR <a href="https://github.com/nostr-protocol/nips/pull/1988">#1988</a>, complete with routing, notification-screen intent, and interop rules.</li>256 </ul>257258 <div class="credits">259 <h3 class="cardhead">Original Proposal - Credits</h3>260 <table>261 <tr><td>Author</td><td>Vitor Pamplona</td></tr>262 <tr><td>First commit</td><td>2025-12-18 — “Public Messages (#1988)”</td></tr>263 <tr><td>Pull request</td><td><a href="https://github.com/nostr-protocol/nips/pull/1988">nostr-protocol/nips #1988</a></td></tr>264 <tr><td>Status</td><td>draft - optional</td></tr>265 <tr><td>Source</td><td><a href="https://github.com/nostr-protocol/nips/blob/master/A4.md">A4.md on GitHub</a> - <a href="https://github.com/nostr-protocol/nips/commits/master/A4.md">full change history</a></td></tr>266 </table>267 </div>268269 <h2 class="bar"><span class="num">8</span> See Also</h2>270 <ul>271 <li><a href="01.html">NIP-01</a> — the base event format and relay messages used here.</li>272 <li><a href="65.html">NIP-65</a> — the inbox and outbox relay lists that route public messages.</li>273 <li><a href="17.html">NIP-17</a> — private direct messages; use these when privacy matters.</li>274 <li><a href="40.html">NIP-40</a> — the <code>expiration</code> tag recommended for every public message.</li>275 <li><a href="18.html">NIP-18</a> — the <code>q</code> quote tag for citing events in the content.</li>276 <li><a href="21.html">NIP-21</a> and <a href="19.html">NIP-19</a> — <code>nostr:</code> URIs and <code>nevent1</code> entities for citations.</li>277 <li><a href="25.html">NIP-25</a> and <a href="57.html">NIP-57</a> — reactions and zaps, which must tag <code>k</code> = <code>24</code>.</li>278 <li><a href="92.html">NIP-92</a> — <code>imeta</code> tags for image and video links.</li>279 </ul>280 </div>281282 <aside>283 <div class="cartridge">284 <div class="inner">285 <h3 class="cardhead">Spec Card</h3>286 <div class="lights"><span class="led on"></span><span class="led on"></span><span class="led on"></span></div>287 <dl>288 <dt>Status</dt><dd><span class="chip draft">draft</span><span class="chip">optional</span></dd>289 <dt>Defines</dt><dd>kind 24 - public message</dd>290 <dt>Kind</dt><dd>24 (regular)</dd>291 <dt>Requires</dt><dd><a href="01.html">NIP-01</a> - <a href="65.html">NIP-65</a> relay lists</dd>292 <dt>Plays with</dt><dd><a href="40.html">NIP-40</a> - <a href="18.html">NIP-18</a> - <a href="25.html">NIP-25</a> - <a href="57.html">NIP-57</a> - <a href="92.html">NIP-92</a></dd>293 <dt>Privacy</dt><dd>none - fully public</dd>294 <dt>First commit</dt><dd>2025-12-18</dd>295 <dt>Last updated</dt><dd>2026-06-13</dd>296 </dl>297 </div>298 </div>299 </aside>300 </main>301302 <nav class="navbtns">303 <a href="a3.html">◀ NIP-A3: payto: Payment Targets</a>304 <a href="b0.html">NIP-B0: Web Bookmarking ▶</a>305 </nav>306307 <footer class="pagefoot">308 <a href="../index.html">Nostr Protocol Manual</a>309 <span class="pageno">NIP A4 / F4</span>310 </footer>311</div>312313<script src="../assets/webmcp.js" defer></script>314</body>315</html>