diff --git a/inbox/2026-10-09_nostr-request-response-and-delivery-guarantees.md b/inbox/2026-10-09_nostr-request-response-and-delivery-guarantees.md new file mode 100644 index 0000000..9087220 --- /dev/null +++ b/inbox/2026-10-09_nostr-request-response-and-delivery-guarantees.md @@ -0,0 +1,47 @@ +--- +date: 2026-10-09 +tags: + - question +hubs: + - "[[nostr]]" + - "[[protocols]]" +urls: + - https://github.com/nostr-protocol/nips/blob/master/01.md + - https://github.com/nostr-protocol/nips/blob/master/46.md + - https://github.com/nostr-protocol/nips/blob/master/47.md + - https://github.com/nostr-protocol/nips/blob/master/90.md +--- + +# Nostr request/response and delivery guarantees + +Open question: how does Nostr handle request/response when a machine +*needs* to know its message was received? Nostr is publish/subscribe with +no end-to-end delivery receipt, so every "RPC over Nostr" NIP builds its +own correlation on top. + +What exists today (to verify and expand): + +- **Relay-level ack only.** NIP-01 `["OK", , true|false, ]` + tells the publisher the *relay* stored the event. Says nothing about the + recipient. Publishing to several relays gives several OKs. +- **Correlation by `e` tag.** Every request/response NIP has the responder + publish a new event that tags the request's id; the requester subscribes + with a `#e` filter (and usually `#p` on its own pubkey) and waits with a + timeout. No response within the timeout = treat as not delivered, retry + with the same request id (responders should be idempotent on it). +- **NIP-46 (remote signing, nsecbunkerd):** kind 24133, encrypted JSON-RPC + `{id, method, params}` → `{id, result, error}`. The `id` in the payload + is the correlation key, the event `e`/`p` tags are routing. +- **NIP-47 (Nostr Wallet Connect):** kind 23194 request → 23195 response, + same pattern, plus 23196 notifications. Also `expiration` tag so a stale + request is dropped rather than executed late. +- **NIP-90 (DVMs):** kinds 5xxx request, 6xxx result, 7000 job feedback + with `status` (payment-required, processing, error, success). This is the + closest thing to a progress/ack channel in the protocol. +- **NIP-17 DMs:** no read receipts by design. + +Our own use: lnbits ↔ nsecbunkerd over NIP-46, and anything the bots do +over Nostr. The practical answer is: own correlation id, subscribe before +publishing, bounded timeout, idempotent retry, and treat relay OK as "sent" +not "received". Worth a reference note once the pattern is written down +with code pointers (nsecbunkerd client, nostrclient).