clone

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

main
nip.guide / site / nips / 09.html
09.html 24.0K
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-09 - Event Deletion Request — Nostr Instruction Manual</title>7<meta name="description" content="NIP-09: the kind-5 deletion request event. How a client asks relays to drop earlier events and asks other clients to hide them, using e, a, and k tags.">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 09 - Content Lifecycle</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="09">09</div>48 <div class="titles">49 <div class="kicker">Nostr Implementation Possibility - Hex № 09</div>50 <h1>Event Deletion Request</h1>51 <p class="sub">A signed event, kind 5, that asks relays to stop serving earlier events and asks clients to hide them. A deletion request is a request. It is never a guarantee.</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>Nostr events are signed and, once published, copies can spread to many relays and many clients. A user cannot reach into every copy and erase it. NIP-09 gives the user a formal way to ask.</p>60 <p>The author of an event publishes a second event, <strong>kind 5</strong>, that lists the events to remove. This is the <strong>deletion request</strong>. Relays that see it and already store the listed events should stop serving those events. Clients that see it should hide the listed events, or mark them as disowned by their author.</p>61 <p>A deletion request only works against events made by the same author. Nobody can delete another user's event this way. Nothing in this NIP forces every relay or every client to comply. Some relays keep no history; some clients ignore deletion requests entirely. Deletion is best-effort, not enforcement.</p>6263 <div class="box hint">64 <span class="tag">Hint!</span>65 <p>This NIP depends on <a href="01.html">NIP-01</a> for the event object, the <code>e</code>/<code>a</code> tag shapes, and the idea of an addressable event. Read that chapter first if the terms below look unfamiliar.</p>66 </div>6768 <figure class="diagram">69 <div class="frame">70 <svg viewBox="0 0 620 320" role="img" aria-label="Sequence: Client A publishes a note, then a kind 5 deletion request for that note; the relay stops serving it; Client B's later request returns nothing for that event">71 <line class="d-wire" x1="90" y1="46" x2="90" y2="300" stroke-dasharray="3 4"/>72 <line class="d-wire" x1="310" y1="46" x2="310" y2="300" stroke-dasharray="3 4"/>73 <line class="d-wire" x1="530" y1="46" x2="530" y2="300" stroke-dasharray="3 4"/>74 <rect class="d-actor" x="35" y="10" width="110" height="30" rx="6"/>75 <text class="d-actor-label" x="90" y="30" text-anchor="middle">Client A</text>76 <rect class="d-actor" x="255" y="10" width="110" height="30" rx="6"/>77 <text class="d-actor-label" x="310" y="30" text-anchor="middle">Relay</text>78 <rect class="d-actor" x="475" y="10" width="110" height="30" rx="6"/>79 <text class="d-actor-label" x="530" y="30" text-anchor="middle">Client B</text>8081 <path class="d-msg" d="M90,66 L305,66"/>82 <text class="d-label" x="200" y="59" text-anchor="middle">EVENT kind:1, id E1</text>83 <path class="d-msg blue" d="M310,90 L95,90"/>84 <text class="d-label" x="200" y="83" text-anchor="middle">OK E1 true</text>8586 <path class="d-msg d-flow" d="M90,128 L305,128"/>87 <text class="d-label" x="200" y="121" text-anchor="middle">EVENT kind:5, tags e:[E1] k:[1]</text>88 <path class="d-msg blue" d="M310,152 L95,152"/>89 <text class="d-label" x="200" y="145" text-anchor="middle">OK D1 true</text>90 <text class="d-note" x="310" y="180" text-anchor="middle">Relay checks: deletion pubkey == E1 pubkey. Match — relay stops serving E1.</text>9192 <path class="d-msg" d="M530,215 L315,215"/>93 <text class="d-label" x="420" y="208" text-anchor="middle">REQ sub, ids:[E1]</text>94 <path class="d-msg blue d-flow" d="M310,245 L525,245"/>95 <text class="d-label" x="420" y="238" text-anchor="middle">EOSE sub — no EVENT sent for E1</text>96 <text class="d-note" x="310" y="278" text-anchor="middle">Client B never receives E1 from this relay. If it already cached E1, it hides it once D1 arrives.</text>9798 <circle r="4" fill="#f26a00">99 <animateMotion dur="2.6s" repeatCount="indefinite" path="M90,128 L305,128"/>100 </circle>101 <circle r="4" fill="#2e5f9e">102 <animateMotion dur="2.6s" begin="1.3s" repeatCount="indefinite" path="M310,245 L525,245"/>103 </circle>104 </svg>105 </div>106 <figcaption>Fig. 9-1 — <b>The deletion-request flow.</b> Client A publishes a note, then a kind:5 deletion request for it. The relay matches the pubkeys, stops serving the note, and future subscribers no longer see it from that relay.</figcaption>107 </figure>108109 <h2 class="bar" id="spec"><span class="num">2</span> The Deletion Request Event</h2>110 <p>Kind 5 marks an event as a deletion request. It must carry one or more <code>e</code> or <code>a</code> tags, each pointing at an event the author wants deleted. Deletion requests should also carry one <code>k</code> tag per referenced event, giving that event's kind.</p>111 <p>The <code>content</code> field may hold a plain-text note that explains the reason for the request. This field is optional. An empty string is valid.</p>112113 <div class="crt">114 <div class="titlebar">Wire format - kind 5, deletion request</div>115<pre>{116 <span class="k">"kind"</span>: 5117 <span class="k">"pubkey"</span>: <span class="c">&lt;32-byte hex pubkey of the event creator&gt;</span>118 <span class="k">"tags"</span>: [119 [<span class="s">"e"</span>, <span class="s">"dcd59…464a2"</span>],120 [<span class="s">"e"</span>, <span class="s">"968c5…ad7a4"</span>],121 [<span class="s">"a"</span>, <span class="s">"&lt;kind&gt;:&lt;pubkey&gt;:&lt;d-identifier&gt;"</span>],122 [<span class="s">"k"</span>, <span class="s">"1"</span>],123 [<span class="s">"k"</span>, <span class="s">"30023"</span>]124 ]125 <span class="k">"content"</span>: <span class="s">"these posts were published by accident"</span>126 <span class="c">// id, created_at, sig: same rules as every event, see NIP-01</span>127}</pre>128 </div>129130 <div class="tscroll"><table class="ref">131 <caption>Kind reference</caption>132 <tr><th>Kind</th><th>Name</th><th>Rule</th></tr>133 <tr><td class="btn">5</td><td>Deletion Request</td><td>Content of a deletion request event. A regular event under the <a href="01.html">NIP-01</a> kind-range convention, so relays are expected to store it, not just the events it targets.</td></tr>134 </table></div>135136 <h2 class="bar" id="tags"><span class="num">3</span> Tags</h2>137 <p>NIP-09 uses three tags. All three follow the general tag shape defined in <a href="01.html">NIP-01</a>.</p>138 <div class="tscroll"><table class="ref">139 <caption>Tags used in a deletion request</caption>140 <tr><th>Tag</th><th>Requirement</th><th>Shape</th><th>Meaning</th></tr>141 <tr><td class="btn">e</td><td>required, unless using <code>a</code></td><td><code>["e", &lt;event id&gt;]</code></td><td>Requests deletion of one regular event, by its exact <code>id</code>.</td></tr>142 <tr><td class="btn">a</td><td>required, unless using <code>e</code></td><td><code>["a", "&lt;kind&gt;:&lt;pubkey&gt;:&lt;d-identifier&gt;"]</code></td><td>Requests deletion of an addressable or replaceable event, by its coordinate.</td></tr>143 <tr><td class="btn">k</td><td>should include, one per referenced event</td><td><code>["k", "&lt;kind&gt;"]</code></td><td>States the kind of the matching <code>e</code> or <code>a</code> tagged event. Lets a relay or client sort deletions without loading each target first.</td></tr>144 </table></div>145 <p>A deletion request lists one or more targets. Use as many <code>e</code>, <code>a</code>, and <code>k</code> tags as needed in a single kind-5 event; there is no rule against combining unrelated deletions in one request.</p>146147 <h2 class="bar" id="relay"><span class="num">4</span> Relay Behavior</h2>148 <ul>149 <li>A relay should delete, or stop publishing, any event referenced by an <code>e</code> tag when that event's <code>pubkey</code> is identical to the deletion request's <code>pubkey</code>.</li>150 <li>A relay should keep publishing and sharing the deletion request event itself, indefinitely. Other clients and relays may not yet have the event it targets, and they need the deletion request to catch up later.</li>151 <li>When an <code>a</code> tag is used, a relay should delete every stored version of that addressable or replaceable event with a <code>created_at</code> at or before the deletion request's own <code>created_at</code>.</li>152 <li>A relay may check that a deletion request only references events sharing its own <code>pubkey</code>, but this check is not required. A relay does not always hold every referenced event, so it cannot always perform the check.</li>153 </ul>154155 <div class="box tech">156 <span class="tag">Tech Note</span>157 <p>The source spec never explicitly restates the pubkey-match rule for <code>a</code> tags the way it does for <code>e</code> tags. In practice the match is implicit: the <code>pubkey</code> segment inside an <code>a</code> tag's coordinate is already part of the address, so a relay comparing it to the deletion request's <code>pubkey</code> is applying the same rule, just read from a different place in the tag. Because the rule is only spelled out for <code>e</code> tags, implementers should not assume every relay applies it consistently to <code>a</code> tags too.</p>158 </div>159160 <figure class="diagram">161 <div class="frame">162 <svg viewBox="0 0 560 170" role="img" aria-label="Timeline: addressable event versions before the deletion request timestamp are deleted; a version published after the deletion request survives">163 <text class="d-actor-label" x="10" y="18">Addressable event, same kind:pubkey:d coordinate</text>164 <line x1="20" y1="80" x2="540" y2="80" stroke="#8fa2b8" stroke-width="1.5"/>165 <circle cx="70" cy="80" r="6" fill="#7d8794"/>166 <text class="d-label" x="70" y="104" text-anchor="middle">v1</text>167 <text class="d-note" x="70" y="120" text-anchor="middle">deleted</text>168 <circle cx="210" cy="80" r="6" fill="#7d8794"/>169 <text class="d-label" x="210" y="104" text-anchor="middle">v2</text>170 <text class="d-note" x="210" y="120" text-anchor="middle">deleted</text>171 <line x1="340" y1="30" x2="340" y2="130" stroke="#f26a00" stroke-width="2.5" stroke-dasharray="5 4"/>172 <text class="d-label" x="340" y="20" text-anchor="middle" fill="#c85700">deletion request created_at</text>173 <circle cx="470" cy="80" r="6" fill="#2c7a3f"/>174 <text class="d-label" x="470" y="104" text-anchor="middle">v3</text>175 <text class="d-note" x="470" y="120" text-anchor="middle">kept — newer than the request</text>176 <text class="d-note" x="280" y="155" text-anchor="middle">Versions at or before the deletion request's created_at are removed. A version published after it survives.</text>177 </svg>178 </div>179 <figcaption>Fig. 9-2 — <b>a-tag range deletion.</b> A deletion request against an addressable event clears every version up to its own timestamp, not just the latest one.</figcaption>180 </figure>181182 <h2 class="bar" id="client"><span class="num">5</span> Client Behavior</h2>183 <p>A client may fully hide any event referenced by a valid deletion request: text notes, direct messages, and any other kind. Alternatively, a client may keep showing the event with an icon or notice that the author has disowned it.</p>184 <p>A client may use the deletion request's <code>content</code> to replace the display of the deleted event's own content. If it does, the interface must make clear that the text shown is the deletion reason, not the original content.</p>185 <p>A client displays the deletion request event itself however it chooses — not at all, or with a prominent notice.</p>186 <p>A client may tell the user that requesting deletion does not guarantee removal. Some relays and clients already hold a copy and may never see, or may ignore, the request.</p>187188 <div class="box warn">189 <span class="tag">Warning!</span>190 <p>A client must check every <code>e</code>-tagged event's <code>pubkey</code> against the deletion request's own <code>pubkey</code> before hiding or deleting it. Relays cannot be trusted to have done this already; a relay may not even hold the referenced event to check.</p>191 </div>192193 <figure class="diagram">194 <div class="frame">195 <svg viewBox="0 0 560 220" role="img" aria-label="Client validation flow: for each e or a tagged event, compare its pubkey to the deletion request pubkey before hiding it">196 <rect class="d-actor" x="180" y="10" width="200" height="46" rx="8"/>197 <text class="d-actor-label" x="280" y="30" text-anchor="middle">Kind:5 event arrives</text>198 <text class="d-note" x="280" y="46" text-anchor="middle">pubkey P, tags e:[E1] e:[E2]</text>199 <path class="d-msg d-flow" d="M280,56 L280,86"/>200 <rect class="d-actor" x="150" y="90" width="260" height="40" rx="8"/>201 <text class="d-actor-label" x="280" y="114" text-anchor="middle">For each e / a tagged event</text>202 <path class="d-msg" d="M230,130 C180,150 120,150 90,168"/>203 <path class="d-msg" d="M330,130 C390,150 450,150 470,168"/>204 <rect class="d-actor" x="10" y="168" width="160" height="42" rx="8"/>205 <text class="d-actor-label" x="90" y="188" text-anchor="middle">pubkey == P</text>206 <text class="d-note" x="90" y="204" text-anchor="middle">hide / mark disowned</text>207 <rect class="d-actor" x="390" y="168" width="160" height="42" rx="8"/>208 <text class="d-actor-label" x="470" y="188" text-anchor="middle">pubkey != P</text>209 <text class="d-note" x="470" y="204" text-anchor="middle">ignore this tag, keep event</text>210 </svg>211 </div>212 <figcaption>Fig. 9-3 — <b>Client-side validation.</b> A client hides an event only after confirming its author matches the deletion request's author, tag by tag.</figcaption>213 </figure>214215 <h2 class="bar" id="repeat"><span class="num">6</span> Deletion Request of a Deletion Request</h2>216 <p>Publishing a deletion request that targets another deletion request has no effect. Clients and relays are not required to support "un-requesting" a deletion.</p>217 <div class="box hint">218 <span class="tag">Hint!</span>219 <p>Once a user sends kind:5, treat that request as final. There is no standard way to withdraw it.</p>220 </div>221222 <h2 class="bar" id="examples"><span class="num">7</span> Worked Example</h2>223 <p>Below, a user publishes a text note, then decides to delete it along with an old long-form article. Orange lines go to the relay. Blue lines come from the relay.</p>224 <div class="crt">225 <div class="titlebar">Session transcript - wss://relay.example.com</div>226<pre><span class="c">-- publish the original note --</span>227<span class="send">→ ["EVENT", {"id":"dcd59a1b…464a2","pubkey":"3bf0c63f…","kind":1,228 "created_at":1749700000,"tags":[],"content":"gm nostr","sig":"7ac1…"}]</span>229<span class="recv">← ["OK", "dcd59a1b…464a2", true, ""]</span>230231<span class="c">-- publish an addressable long-form article, d = "draft-1" --</span>232<span class="send">→ ["EVENT", {"id":"968c5a2e…ad7a4","pubkey":"3bf0c63f…","kind":30023,233 "created_at":1749700500,"tags":[["d","draft-1"]],"content":"# early draft","sig":"91fe…"}]</span>234<span class="recv">← ["OK", "968c5a2e…ad7a4", true, ""]</span>235236<span class="c">-- the author changes their mind and deletes both --</span>237<span class="send">→ ["EVENT", {"id":"a10f77c2…e55b1","pubkey":"3bf0c63f…","kind":5,238 "created_at":1749762600,239 "tags":[240 ["e","dcd59a1b…464a2"],241 ["a","30023:3bf0c63f…:draft-1"],242 ["k","1"],243 ["k","30023"]244 ],245 "content":"these posts were published by accident","sig":"c02a…"}]</span>246<span class="recv">← ["OK", "a10f77c2…e55b1", true, ""]</span>247248<span class="c">-- a second client asks for the deleted note --</span>249<span class="send">→ ["REQ", "check", {"ids":["dcd59a1b…464a2"]}]</span>250<span class="recv">← ["EOSE", "check"]</span>251<span class="c">-- no EVENT was sent: the relay honored the deletion request --</span>252253<span class="c">-- the client also fetches the deletion request itself, to explain the gap --</span>254<span class="send">→ ["REQ", "why", {"kinds":[5], "authors":["3bf0c63f…"]}]</span>255<span class="recv">← ["EVENT", "why", {"kind":5, "content":"these posts were published by accident", …}]</span>256<span class="recv">← ["EOSE", "why"]</span>257258<span class="c">-- attacker tries to delete someone else's note; client must reject it locally --</span>259<span class="recv">← ["EVENT", "feed", {"id":"badreq1…","pubkey":"eeeeeeee…","kind":5,260 "tags":[["e","dcd59a1b…464a2"]], "content":"", …}]</span>261<span class="c">// client compares pubkeys: eeeeeeee… != 3bf0c63f… (the note's real author)</span>262<span class="c">// client ignores this deletion request; the note stays visible</span></pre>263 </div>264265 <h2 class="bar" id="history"><span class="num">8</span> Version History</h2>266 <p>NIP-09 grew from a single-tag "delete this event" note into a multi-tag request covering addressable events. Notable changes, newest first:</p>267 <ul class="patchnotes">268 <li class="minor"><span class="ver">2026</span><span class="when">2026-06</span>Code fence style changed from <code>jsonc</code> to <code>yaml</code> across the manual; no rule change.</li>269 <li><span class="ver">2025</span><span class="when">2025-12</span>Added the <code>relay</code> tag to the spec header, marking this NIP as relevant to relay operators (#2173).</li>270 <li><span class="ver">2024</span><span class="when">2024-08</span>Renamed the event from "deletion" to "retraction" for one day, then settled on "deletion request", the name used today.</li>271 <li><span class="ver">2024</span><span class="when">2024-07</span>Added the optional <code>k</code> tag, so a request can state the kind of each referenced event.</li>272 <li><span class="ver">2024</span><span class="when">2024-06</span>Clarified that an <code>a</code>-tag deletion covers every version of the addressable event up to the request's own timestamp.</li>273 <li class="minor"><span class="ver">2023</span><span class="when">2023-11</span>Removed a stale reference to NIP-33 after its addressable-event rules merged into <a href="01.html">NIP-01</a>.</li>274 <li><span class="ver">2023</span><span class="when">2023-06</span>Added the <code>a</code> tag, extending deletion requests to addressable and replaceable events (#600).</li>275 <li class="minor"><span class="ver">2023</span><span class="when">2023-04</span>General wording fixes and small clarifications to the spec text.</li>276 <li><span class="ver">2022</span><span class="when">2022-11</span>Strengthened the relay-side wording: relays should actively stop serving deleted events, not merely tolerate the request.</li>277 <li><span class="ver">Origin</span><span class="when">2022-05-01</span>fiatjaf migrated the NIP, defining kind 5 with <code>e</code>-tag deletion requests.</li>278 </ul>279280 <div class="credits">281 <h3 class="cardhead">Original Proposal - Credits</h3>282 <table>283 <tr><td>Author</td><td>fiatjaf</td></tr>284 <tr><td>First commit</td><td>2022-05-01 — “migrate nips from main nostr repo” (spec predates the repository)</td></tr>285 <tr><td>Status</td><td>draft - optional — relays and clients may implement it</td></tr>286 <tr><td>Source</td><td><a href="https://github.com/nostr-protocol/nips/blob/master/09.md">09.md on GitHub</a> - <a href="https://github.com/nostr-protocol/nips/commits/master/09.md">full change history</a></td></tr>287 </table>288 </div>289290 <h2 class="bar"><span class="num">9</span> See Also</h2>291 <ul>292 <li><a href="01.html">NIP-01</a> — the event object, <code>e</code>/<code>a</code> tag shapes, and addressable/replaceable events referenced throughout this chapter.</li>293 <li><a href="33.html">NIP-33</a> — the earlier home of addressable events, before that content merged into NIP-01; the <code>a</code> tag here targets what that NIP defined.</li>294 <li><a href="40.html">NIP-40</a> — expiration timestamps, a second way to make an event disappear, set in advance instead of requested afterward.</li>295 <li><a href="62.html">NIP-62</a> — Request to Vanish, a stronger, account-wide relay request to erase everything from a pubkey.</li>296 </ul>297 </div>298299 <aside>300 <div class="cartridge">301 <div class="inner">302 <h3 class="cardhead">Spec Card</h3>303 <div class="lights"><span class="led on"></span><span class="led on"></span><span class="led on"></span></div>304 <dl>305 <dt>Status</dt><dd><span class="chip draft">draft</span><span class="chip">optional</span></dd>306 <dt>Defines</dt><dd>kind 5 (deletion request) - e/a/k tags</dd>307 <dt>Kind(s)</dt><dd>5</dd>308 <dt>Requires</dt><dd><a href="01.html">NIP-01</a> event and tag format</dd>309 <dt>Transport</dt><dd>WebSocket - JSON arrays (inherited from NIP-01)</dd>310 <dt>Crypto</dt><dd>inherited from NIP-01 — the deletion request is itself a signed event</dd>311 <dt>First commit</dt><dd>2022-05-01</dd>312 <dt>Last updated</dt><dd>2026-06-13</dd>313 </dl>314 </div>315 </div>316 </aside>317 </main>318319 <nav class="navbtns">320 <a href="08.html">◀ NIP-08: Handling Mentions</a>321 <a href="10.html">NIP-10: Text Notes and Threads ▶</a>322 </nav>323324 <footer class="pagefoot">325 <a href="../index.html">Nostr Protocol Manual</a>326 <span class="pageno">NIP 09 / F4</span>327 </footer>328</div>329330<script src="../assets/webmcp.js" defer></script>331</body>332</html>