Skip to content

Bitcoin accepted at checkout  |  Ships from Montreal, QC, Canada  |  Expert support since 2016

Nostr Relay Protocol Reference: The 8 NIP-01 Wire Messages

Nostr’s whole client-to-relay protocol fits on one page: eight JSON-array messages and one filter object. That minimalism is the point — it is why anyone can run a relay and why the network resists capture. This reference lays out every NIP-01 wire message with its exact syntax, the REQ filter fields and how they match, and the standardized rejection prefixes a relay speaks back. It completes our Nostr canon beside the NIPs index, the event-kinds reference and the standardized-tags reference.

Quick answer

The Nostr protocol is remarkably small: a client and a relay exchange just 8 message types, all JSON arrays. The client sends EVENT (publish), REQ (subscribe with filters) and CLOSE (unsubscribe); the relay replies EVENT (a matching event), OK (accepted/rejected), EOSE (end of stored events, real-time begins), CLOSED (subscription refused) and NOTICE (human-readable message). This reference lays out each message with its syntax and purpose, the REQ filter-object fields (ids/authors/kinds/#tag/since/until/limit) and their matching rules, and the 8 standardized machine-readable OK/CLOSED prefixes. Sourced from the canonical NIP-01.

The filter rule to remember: within one filter, all conditions must match (AND); across multiple filters in one REQ, an event passes if it matches ANY (OR). EOSE is the key signal — it tells the client "backfill done, the rest is live". AUTH is NOT here (that is NIP-42). Free CSV/JSON under CC BY 4.0; as of 2026-07-26.

Download CSV Download JSON REST API →

Client → relay messages 3

MessageSyntaxPurpose
EVENT["EVENT", <event JSON>]Publishes an event to the relay. The event is the full signed object (id, pubkey, created_at, kind, tags, content, sig).
REQ["REQ", <subscription_id>, <filters1>, <filters2>, ...]Requests stored events and subscribes to new ones. subscription_id is an arbitrary non-empty string up to 64 chars, scoped per connection; a new REQ with the same id replaces the old subscription.
CLOSE["CLOSE", <subscription_id>]Stops a previously opened subscription identified by subscription_id.

Relay → client messages 5

MessageSyntaxPurpose
EVENT["EVENT", <subscription_id>, <event JSON>]Sends an event matching a subscription. MUST carry a subscription_id from a REQ the client previously opened.
OK["OK", <event_id>, <true|false>, <message>]Reports acceptance (true) or rejection (false) of a client EVENT. The 4th parameter MUST be present; it MAY be empty when true, otherwise MUST be a machine-readable prefix + ':' + human message.
EOSE["EOSE", <subscription_id>]End Of Stored Events: marks the boundary between stored events and real-time events newly streamed for that subscription.
CLOSED["CLOSED", <subscription_id>, <message>]Sent when the relay refuses or terminates a subscription from its side. Uses the same prefix:message convention as OK.
NOTICE["NOTICE", <message>]Sends a human-readable message (usually an error) to the client. NIP-01 defines no rules for how NOTICEs are sent or handled.

REQ filter-object fields

FieldTypeMeaning
idsarray of stringsEvent ids to match. MUST contain exact 64-char lowercase hex (exact match; no prefix matching in current NIP-01).
authorsarray of stringsThe event pubkey must be one of these. MUST contain exact 64-char lowercase hex.
kindsarray of integersThe event kind must be in the list.
#<single-letter>array of stringsTag filter (e.g. #e = event ids, #p = pubkeys). Relays index single-letter tags; only the FIRST value of a tag is indexed. #e/#p MUST use exact 64-char lowercase hex. Event and filter must share at least one value.
sinceinteger (unix seconds)Event created_at must be >= since.
untilinteger (unix seconds)Event created_at must be <= until. In short: since <= created_at <= until.
limitintegerMax events the relay SHOULD return for the initial query only (ignored afterwards). Returns the newest n by created_at (ties broken by lowest id).

Standardized OK / CLOSED prefixes

duplicate: The event was already received / stored.
pow: The event does not meet a required proof-of-work difficulty.
blocked: The pubkey or event is blocked by relay policy.
rate-limited: The client is sending too fast.
invalid: The event or request is malformed / fails validation.
restricted: The action requires an authorization the client does not have.
mute: The event was accepted-but-ignored (e.g. nobody was listening).
error: Catch-all for when none of the other prefixes fit.

Source: the canonical NIP-01 from nostr-protocol/nips (fetched 2026-07-26). Completes the on-site Nostr canon alongside the NIPs, event kinds and standardized tags references — the fourth leg of the protocol canon.