NIP-01 defines the foundational protocol for Nostr, establishing the data structures and communication patterns that all other NIPs build upon.

Events

Events are the only object type in Nostr. Every piece of data, from a profile update to a text post to a reaction, is represented as an event with this structure:

  • id: SHA256 hash of the serialized event (unique identifier)
  • pubkey: The creator’s public key (32-byte hex, secp256k1)
  • created_at: Unix timestamp
  • kind: Integer categorizing the event type
  • tags: Array of arrays for metadata
  • content: The payload (interpretation depends on kind)
  • sig: Schnorr signature proving authenticity

Kinds

Kinds determine how relays store and handle events:

  • Regular events (1, 2, 4-44, 1000-9999): Stored normally, all versions kept
  • Replaceable events (0, 3, 10000-19999): Only the latest per pubkey is kept
  • Ephemeral events (20000-29999): Not stored, just forwarded to subscribers
  • Addressable events (30000-39999): Latest per pubkey + kind + d tag combination

Core kinds include: 0 (user metadata), 1 (text note), 3 (follow list).

Client-Relay Communication

Clients communicate with relays over WebSocket connections using JSON arrays:

Client to relay:

  • ["EVENT", <event>] - Publish an event
  • ["REQ", <sub-id>, <filter>, ...] - Subscribe to events
  • ["CLOSE", <sub-id>] - End a subscription

Relay to client:

  • ["EVENT", <sub-id>, <event>] - Deliver matching event
  • ["EOSE", <sub-id>] - End of stored events (now streaming live)
  • ["OK", <event-id>, <true|false>, <message>] - Accept/reject acknowledgment
  • ["NOTICE", <message>] - Human-readable message

Filters

Filters specify which events to retrieve, with fields including: ids, authors, kinds, #e/#p/#t (tag values), since/until, and limit. Conditions within a filter use AND logic; multiple filters in a REQ combine with OR logic.


Primary sources:

Mentioned in:

See also: