This NIP defines the complete protocol that MUST be implemented by everybody. New NIPs may add new optional (or mandatory) fields, messages, and features to the structures and flows described here.
| Replaceable | `10000 <= kind < 20000` OR `0, 3` | The newest event for each `pubkey` and `kind` |
| Ephemeral | `20000 <= kind < 30000` | Nothing |
| Parameterized | `30000 <= kind < 40000` | The newest event for each `pubkey`, `kind` and `d`-tag |
In case of replaceable events with the same timestamp, the event with the lowest `.id` (first in lexical order) SHOULD be retained. Older versions MAY be kept but SHOULD not be returned on queries.
This NIP defines two kinds:
-`kind:0`: **User Metadata**: the `content` is set to a stringified JSON object `{name: <username>, about: <string>, picture: <url, string>}` describing the user who created the event. A relay may delete older events once it gets a new one for the same pubkey.
-`kind:1`: **Text Note**: the `content` is set to the **plaintext** content of a note (anything the user wants to say). Content that must be parsed, such as Markdown and HTML, should not be used. Clients should also not parse content as those.
Each tag is an array of strings of arbitrary size. Their meaning is determined by the event `.kind` and defined in NIPs in this repository. Tags with the same name might have entirely different meanings in different kinds.
The first element of the tag array is referred to as the tag _name_ or _key_ and the second as the tag _value_. All elements after the second do not have a conventional name.
This NIP defines the format of 3 standard tags: `e`, `p`, and `a`. `e`, `p` can be used to reference events and pubkeys, and `a` references the latest version of a replaceable event, parameterized or not.
Nostr has two main components: Clients & Relays. Users run a client to fetch/subscribe to events from one or more Relays via WebSockets. Relays are not expected to communicate with one another. It's the Client's responsibility to discover which relay has the event set their user wants to see. Both sides SHOULD verify the hash and the signature of each event upon receipt.
Clients SHOULD open a single WebSocket connection to each relay and use it for all their subscriptions. Relays MAY limit the number of connections from specific IP/client/etc. All messages are defined as JSON arrays.
Clients send a **subscription** message with one or more filters. The Relay MUST query its database, return all events that match the filter, and keep applying the filter to all connections, returning new events as they arrive. Subscriptions stay indefinitely open until either side closes the subscription or the connection.
`<subscription_id>` is a non-empty string with a maximum length of 64 chars. Relays MUST manage `<subscription_id>`s independently for each WebSocket connection. `<subscription_id>`s are not globally unique. A `REQ` message on an existing subscription overrides the previous subscription.
Array properties (i.e., `ids`, `authors`, `kinds`, and tag filters) represent a logical OR statement. At least one of the arrays' values must match the respective field in the event to be considered a match. In the case of tag attributes such as `#e`, for which an event may have multiple values, the event and filter condition values must have at least one item in common.
The `since` and `until` properties are used to specify the time range of events returned in the subscription. An event matches the filter if `since <= created_at <= until` holds.
All messages MUST be sent with the subscription_id initiated by the client (using the `REQ` message above).
`CLOSED` messages MUST be sent in response to a `REQ` when the relay refuses to fulfill it. It can also be sent when a relay decides to kill a subscription on its side before a client has disconnected or sent a `CLOSE`. The message MUST be a string formed by a machine-readable single-word prefix followed by a `:` and then a human-readable message.
`OK` messages MUST be sent in response to `EVENT` messages received from clients, they must have the 3rd parameter set to `true` when an event has been accepted by the relay, `false` otherwise. The 4th parameter MUST always be present, but MAY be an empty string when the 3rd is `true`.
If present, the message MUST be a string formed by a machine-readable single-word prefix followed by a `:` and then a human-readable message.
The standardized machine-readable prefixes for `OK` and `CLOSED` are: `duplicate`, `pow`, `blocked`, `rate-limited`, `invalid`, and `error` for when none of that fits.