# Nostr Implementation Possibilities (NIPs) - Complete Overview This document provides detailed descriptions of all standard NIPs from the nostr-protocol/nips repository. ## Core Protocol NIPs ### NIP-01: Basic Protocol Flow Description **Status**: Mandatory for all implementations The foundational NIP that defines the entire Nostr protocol. #### Events Events are the only object type in Nostr. Structure: ```json { "id": "<32-bytes lowercase hex>", "pubkey": "<32-bytes lowercase hex>", "created_at": "", "kind": "", "tags": [["", "", ...]], "content": "", "sig": "<64-bytes hex>" } ``` **Event ID Calculation**: 1. Serialize to JSON array: `[0, pubkey, created_at, kind, tags, content]` 2. UTF-8 encode 3. Calculate SHA256 hash 4. Result is the event ID **Signature**: - Schnorr signature of the event ID - Uses secp256k1 curve - 64-byte hex-encoded #### Communication Protocol All communication happens over WebSocket. **Client Messages**: 1. `["EVENT", ]` - Publish event 2. `["REQ", , , ...]` - Subscribe 3. `["CLOSE", ]` - Unsubscribe **Relay Messages**: 1. `["EVENT", , ]` - Send event 2. `["OK", , , ]` - Command result 3. `["EOSE", ]` - End of stored events 4. `["CLOSED", , ]` - Forced close 5. `["NOTICE", ]` - Human-readable notice #### Filters Filter object fields (all optional): - `ids`: List of event IDs (prefix match) - `authors`: List of pubkeys (prefix match) - `kinds`: List of event kinds - `#`: Tag queries - `since`: Unix timestamp (events after) - `until`: Unix timestamp (events before) - `limit`: Maximum events to return A filter matches if ALL conditions are met. Within arrays, conditions are ORed. #### Basic Event Kinds - `0`: Metadata (user profile) - `1`: Text note - `2`: Recommend relay (deprecated) ### NIP-02: Contact List and Petnames **Status**: Widely implemented Defines event kind `3` for user contact lists (following lists). **Format**: ```json { "kind": 3, "tags": [ ["p", "", "", ""] ], "content": "" } ``` **Characteristics**: - Replaceable event (latest version is authoritative) - Each `p` tag is a followed user - Relay URL (optional): where to find this user - Petname (optional): user's chosen name for contact - Content may contain JSON relay list (deprecated, use NIP-65) **Usage**: - Clients fetch kind 3 to build following list - Always replace old version with new - Use for social graph discovery ### NIP-03: OpenTimestamps Attestations **Status**: Optional Allows embedding OpenTimestamps proofs in events. **Format**: ```json { "tags": [ ["ots", ""] ] } ``` Used to prove an event existed at a specific time via Bitcoin blockchain timestamps. ### NIP-04: Encrypted Direct Messages **Status**: Deprecated (use NIP-44) Event kind `4` for encrypted private messages. **Encryption**: - ECDH shared secret between sender/receiver - AES-256-CBC encryption - Base64 encoded result **Format**: ```json { "kind": 4, "tags": [ ["p", ""] ], "content": "" } ``` **Security Issues**: - Vulnerable to certain attacks - No forward secrecy - Use NIP-44 instead ### NIP-05: Mapping Nostr Keys to DNS-based Internet Identifiers **Status**: Widely implemented Allows verification of identity via domain names (like email addresses). **Format**: `name@domain.com` **Implementation**: 1. User adds `"nip05": "alice@example.com"` to metadata (kind 0) 2. Domain serves `/.well-known/nostr.json`: ```json { "names": { "alice": "" }, "relays": { "": ["wss://relay1.com", "wss://relay2.com"] } } ``` 3. Clients verify by fetching and checking pubkey match **Benefits**: - Human-readable identifiers - Domain-based verification - Optional relay hints - Spam prevention (verified users) ### NIP-06: Basic Key Derivation from Mnemonic Seed Phrase **Status**: Optional Derives Nostr keys from BIP39 mnemonic phrases. **Derivation Path**: `m/44'/1237'/0'/0/0` - 1237 is the coin type for Nostr - Allows HD wallet-style key management **Benefits**: - Backup with 12/24 words - Multiple accounts from one seed - Compatible with BIP39 tools ### NIP-07: window.nostr Capability for Web Browsers **Status**: Browser extension standard Defines browser API for Nostr key management. **API Methods**: ```javascript window.nostr.getPublicKey(): Promise window.nostr.signEvent(event): Promise window.nostr.getRelays(): Promise<{[url]: {read: boolean, write: boolean}}> window.nostr.nip04.encrypt(pubkey, plaintext): Promise window.nostr.nip04.decrypt(pubkey, ciphertext): Promise ``` **Usage**: - Web apps request signatures from extension - Private keys never leave extension - User approves each action - Popular extensions: nos2x, Alby, Flamingo ### NIP-08: Handling Mentions **Status**: Core convention Defines how to mention users and events in notes. **Format**: - Add `p` or `e` tags for mentions - Reference in content with `#[index]` ```json { "kind": 1, "tags": [ ["p", "<pubkey>", "<relay>"], ["e", "<event-id>", "<relay>"] ], "content": "Hello #[0], check out #[1]" } ``` Clients replace `#[0]`, `#[1]` with user-friendly displays. ### NIP-09: Event Deletion **Status**: Widely implemented Event kind `5` requests deletion of events. **Format**: ```json { "kind": 5, "tags": [ ["e", "<event-id-to-delete>"], ["e", "<another-event-id>"] ], "content": "Reason for deletion (optional)" } ``` **Behavior**: - Only author can delete their events - Relays SHOULD delete referenced events - Not guaranteed (relays may ignore) - Some clients show deletion notice ### NIP-10: Text Note References (Reply, Threads) **Status**: Core threading standard Conventions for `e` and `p` tags in threaded conversations. **Markers**: - `root`: The root event of the thread - `reply`: Direct parent being replied to - `mention`: Mentioned but not replied to **Format**: ```json { "kind": 1, "tags": [ ["e", "<root-event-id>", "<relay>", "root"], ["e", "<parent-event-id>", "<relay>", "reply"], ["e", "<mentioned-event-id>", "<relay>", "mention"], ["p", "<author1-pubkey>"], ["p", "<author2-pubkey>"] ] } ``` **Best Practices**: - Always include root marker for thread context - Include reply marker for direct parent - Add p tags for all mentioned users - Maintains thread integrity ### NIP-11: Relay Information Document **Status**: Standard HTTP endpoint for relay metadata. **Implementation**: - HTTP GET to relay URL (not WebSocket) - Accept header: `application/nostr+json` **Response Example**: ```json { "name": "Example Relay", "description": "A Nostr relay", "pubkey": "<admin-pubkey>", "contact": "admin@example.com", "supported_nips": [1, 2, 9, 11, 12, 15, 16, 20, 22], "software": "git+https://github.com/...", "version": "1.0.0", "limitation": { "max_message_length": 16384, "max_subscriptions": 20, "max_filters": 100, "max_limit": 5000, "max_subid_length": 100, "min_prefix": 4, "max_event_tags": 100, "max_content_length": 8196, "min_pow_difficulty": 30, "auth_required": false, "payment_required": false }, "relay_countries": ["US", "CA"], "language_tags": ["en", "es"], "tags": ["adult-content", "no-spam"], "posting_policy": "https://example.com/policy", "payments_url": "https://example.com/pay", "fees": { "admission": [{"amount": 5000000, "unit": "msats"}], "subscription": [{"amount": 1000000, "unit": "msats", "period": 2592000}], "publication": [] }, "icon": "https://example.com/icon.png" } ``` **Usage**: - Clients discover relay capabilities - Check NIP support before using features - Display relay info to users - Respect limitations ### NIP-12: Generic Tag Queries **Status**: Core functionality Extends filtering to support any single-letter tag. **Syntax**: `#<letter>: [<value>, ...]` **Examples**: ```json { "#t": ["bitcoin", "nostr"], "#p": ["pubkey1", "pubkey2"], "#e": ["eventid1"] } ``` Matches events with specified tag values. ### NIP-13: Proof of Work **Status**: Spam prevention Requires computational work for event publication. **Implementation**: - Add `nonce` tag: `["nonce", "<number>", "<target-difficulty>"]` - Hash event ID until leading zero bits >= difficulty - Increment nonce until condition met **Example**: ```json { "tags": [ ["nonce", "12345", "20"] ], "id": "00000abcd..." // 20+ leading zero bits } ``` **Difficulty Levels**: - 0-10: Very easy - 20: Moderate - 30+: Difficult - 40+: Very difficult Relays can require minimum PoW for acceptance. ### NIP-14: Subject Tag **Status**: Convenience Adds `subject` tag for event titles/subjects. **Format**: ```json { "tags": [ ["subject", "My Post Title"] ] } ``` Used for long-form content, discussions, emails-style messages. ### NIP-15: End of Stored Events (EOSE) **Status**: Core protocol Relay sends `EOSE` after sending all stored events matching a subscription. **Format**: `["EOSE", <subscription_id>]` **Usage**: - Clients know when historical events are complete - Can show "loading" state until EOSE - New events after EOSE are real-time ### NIP-16: Event Treatment **Status**: Event lifecycle Defines three event categories: 1. **Regular Events** (1000-9999): - Immutable - All versions kept - Examples: notes, reactions 2. **Replaceable Events** (10000-19999): - Only latest kept - Same author + kind → replace - Examples: metadata, contacts 3. **Ephemeral Events** (20000-29999): - Not stored - Forwarded once - Examples: typing indicators, presence 4. **Parameterized Replaceable Events** (30000-39999): - Replaced based on `d` tag - Same author + kind + d-tag → replace - Examples: long-form posts, product listings ### NIP-18: Reposts **Status**: Social feature Event kind `6` for reposting/sharing events. **Format**: ```json { "kind": 6, "tags": [ ["e", "<reposted-event-id>", "<relay>"], ["p", "<original-author-pubkey>"] ], "content": "" // or reposted event JSON } ``` **Generic Repost** (kind 16): - Can repost any event kind - Preserves original context ### NIP-19: bech32-encoded Entities **Status**: Widely implemented Human-readable encodings for Nostr entities. **Formats**: 1. **npub**: Public key - `npub1xyz...` - Safer to share than hex 2. **nsec**: Private key (SENSITIVE!) - `nsec1xyz...` - Never share publicly 3. **note**: Event ID - `note1xyz...` - Links to specific events 4. **nprofile**: Profile with hints - Includes pubkey + relay URLs - Better discovery 5. **nevent**: Event with hints - Includes event ID + relay URLs + author - Reliable event fetching 6. **naddr**: Replaceable event coordinate - Includes kind + pubkey + d-tag + relays - For parameterized replaceable events **Usage**: - Use for sharing/displaying identifiers - Clients should support all formats - Always use npub/nsec instead of hex when possible ### NIP-20: Command Results **Status**: Core protocol Defines `OK` message format from relays. **Format**: `["OK", <event_id>, <accepted>, <message>]` **Examples**: ```json ["OK", "abc123...", true, ""] ["OK", "def456...", false, "invalid: signature verification failed"] ["OK", "ghi789...", false, "pow: difficulty too low"] ["OK", "jkl012...", false, "rate-limited: slow down"] ``` **Common Rejection Prefixes**: - `duplicate:` - Event already received - `pow:` - Insufficient proof of work - `blocked:` - Pubkey or content blocked - `rate-limited:` - Too many requests - `invalid:` - Event validation failed - `error:` - Server error ### NIP-21: nostr: URI Scheme **Status**: Standard linking Defines `nostr:` URI scheme for deep linking. **Format**: - `nostr:npub1...` - `nostr:note1...` - `nostr:nevent1...` - `nostr:nprofile1...` - `nostr:naddr1...` **Usage**: - Clickable links in web/mobile - Cross-app navigation - QR codes ### NIP-22: Event created_at Limits **Status**: Relay policy Relays may reject events with timestamps too far in past/future. **Recommendations**: - Reject events created_at > 15 minutes in future - Reject very old events (relay-specific) - Prevents timestamp manipulation ### NIP-23: Long-form Content **Status**: Blog/article support Event kind `30023` for long-form content (articles, blogs). **Format**: ```json { "kind": 30023, "tags": [ ["d", "<unique-identifier>"], ["title", "Article Title"], ["summary", "Brief description"], ["published_at", "<unix-timestamp>"], ["t", "tag1"], ["t", "tag2"], ["image", "https://..."] ], "content": "Markdown content..." } ``` **Characteristics**: - Parameterized replaceable (by `d` tag) - Content in Markdown - Rich metadata - Can be edited (updates replace) ### NIP-25: Reactions **Status**: Widely implemented Event kind `7` for reactions to events (likes, emoji reactions). **Format**: ```json { "kind": 7, "tags": [ ["e", "<reacted-event-id>"], ["p", "<event-author-pubkey>"], ["k", "<reacted-event-kind>"] ], "content": "+" // or emoji } ``` **Content Values**: - `+`: Like/upvote - `-`: Dislike (discouraged) - Emoji: 👍, ❤️, 😂, etc. - Custom reactions **Client Display**: - Count reactions per event - Group by emoji - Show who reacted ### NIP-26: Delegated Event Signing **Status**: Advanced delegation Allows delegating event signing to another key. **Use Cases**: - Bot accounts posting for user - Temporary keys for devices - Service providers posting on behalf **Implementation**: - Delegation token in tags - Limits by kind, time range - Original author still verifiable ### NIP-27: Text Note References **Status**: Convenience Shortcuts for mentioning entities inline. **Format**: - `nostr:npub1...` → user mention - `nostr:note1...` → event reference - `nostr:nevent1...` → event with context Clients render as clickable links. ### NIP-28: Public Chat (Channels) **Status**: Channel support Event kinds for public chat channels. **Event Kinds**: - `40`: Create channel - `41`: Set channel metadata - `42`: Create message - `43`: Hide message - `44`: Mute user **Channel Creation (kind 40)**: ```json { "kind": 40, "content": "{\"name\": \"Bitcoin\", \"about\": \"Discussion\", \"picture\": \"url\"}" } ``` **Channel Message (kind 42)**: ```json { "kind": 42, "tags": [ ["e", "<channel-id>", "<relay>", "root"] ], "content": "Hello channel!" } ``` ### NIP-33: Parameterized Replaceable Events **Status**: Core feature Event kinds 30000-39999 are replaceable by `d` tag. **Format**: ```json { "kind": 30000, "tags": [ ["d", "<identifier>"] ] } ``` **Replacement Rule**: - Same author + kind + d-tag → replace old event - Different d-tag → separate events - No d-tag → treated as `d` = "" **Coordinate Reference**: `<kind>:<pubkey>:<d-value>` **Use Cases**: - Product catalogs (each product = d-tag) - Article revisions (article slug = d-tag) - Configuration settings (setting name = d-tag) ### NIP-36: Sensitive Content Warning **Status**: Content moderation Tags for marking sensitive/NSFW content. **Format**: ```json { "tags": [ ["content-warning", "nudity"], ["content-warning", "violence"] ] } ``` Clients can hide/blur until user confirms. ### NIP-39: External Identities **Status**: Identity verification Links Nostr identity to external platforms. **Format (in kind 0 metadata)**: ```json { "kind": 0, "content": "{\"identities\": [{\"platform\": \"github\", \"username\": \"alice\", \"proof\": \"url\"}]}" } ``` **Supported Platforms**: - GitHub - Twitter - Mastodon - Matrix - Telegram ### NIP-40: Expiration Timestamp **Status**: Ephemeral content Tag for auto-expiring events. **Format**: ```json { "tags": [ ["expiration", "<unix-timestamp>"] ] } ``` Relays should delete event after expiration time. ### NIP-42: Authentication of Clients to Relays **Status**: Access control Relays can require client authentication. **Flow**: 1. Relay sends: `["AUTH", "<challenge>"]` 2. Client creates kind `22242` event: ```json { "kind": 22242, "tags": [ ["relay", "<relay-url>"], ["challenge", "<challenge-string>"] ], "created_at": <now> } ``` 3. Client sends: `["AUTH", <signed-event>]` 4. Relay verifies signature and challenge **Benefits**: - Spam prevention - Access control - Rate limiting per user - Paid relays ### NIP-44: Encrypted Payloads (Versioned) **Status**: Modern encryption Improved encryption replacing NIP-04. **Algorithm**: - ECDH shared secret - ChaCha20-Poly1305 AEAD - Version byte for upgradability - Salt for key derivation **Security Improvements**: - Authenticated encryption - Better key derivation - Version support - Resistance to padding oracle attacks **Format**: ``` <version-byte><encrypted-payload> ``` Base64 encode for `content` field. ### NIP-45: Event Counts **Status**: Statistics Request for event counts matching filters. **Client Request**: ```json ["COUNT", <subscription_id>, <filters>] ``` **Relay Response**: ```json ["COUNT", <subscription_id>, {"count": 123, "approximate": false}] ``` **Usage**: - Display follower counts - Show engagement metrics - Statistics dashboards ### NIP-46: Nostr Connect (Remote Signing) **Status**: Remote signer protocol Protocol for remote key management and signing. **Architecture**: - Signer: Holds private key - Client: Requests signatures - Communication via Nostr events **Use Cases**: - Mobile app delegates to desktop signer - Browser extension as signer - Hardware wallet integration - Multi-device key sharing ### NIP-47: Wallet Connect **Status**: Lightning integration Protocol for connecting Lightning wallets to Nostr apps. **Commands**: - `pay_invoice` - `get_balance` - `get_info` - `make_invoice` - `lookup_invoice` Enables in-app Lightning payments. ### NIP-50: Search Capability **Status**: Optional Full-text search in filter queries. **Format**: ```json { "search": "bitcoin nostr" } ``` **Implementation**: - Relay-specific behavior - May search content, tags, etc. - Not standardized ranking ### NIP-51: Lists **Status**: Curation Event kinds for various list types. **List Kinds**: - `30000`: Categorized people list - `30001`: Categorized bookmarks - `10000`: Mute list - `10001`: Pin list **Format**: ```json { "kind": 30000, "tags": [ ["d", "my-list"], ["p", "<pubkey>", "<relay>", "<petname>"], ["t", "<category>"] ] } ``` ### NIP-56: Reporting **Status**: Moderation Event kind `1984` for reporting content. **Format**: ```json { "kind": 1984, "tags": [ ["e", "<event-id>", "<relay>"], ["p", "<pubkey>"], ["report", "spam"] // or "nudity", "profanity", "illegal", "impersonation" ], "content": "Additional details" } ``` Used by relays and clients for moderation. ### NIP-57: Lightning Zaps **Status**: Widely implemented Protocol for Lightning tips with proof. **Flow**: 1. Get user's Lightning address (from metadata) 2. Fetch LNURL data 3. Create zap request (kind `9734`) 4. Pay invoice 5. Relay publishes zap receipt (kind `9735`) **Zap Request (kind 9734)**: ```json { "kind": 9734, "tags": [ ["p", "<recipient-pubkey>"], ["amount", "<millisats>"], ["relays", "relay1", "relay2"], ["e", "<event-id>"] // if zapping event ] } ``` **Zap Receipt (kind 9735)**: Published by LNURL provider, proves payment. ### NIP-58: Badges **Status**: Reputation system Award and display badges (achievements, credentials). **Event Kinds**: - `30008`: Badge definition - `30009`: Profile badges - `8`: Badge award **Badge Definition**: ```json { "kind": 30008, "tags": [ ["d", "badge-id"], ["name", "Badge Name"], ["description", "What this means"], ["image", "url"], ["thumb", "thumbnail-url"] ] } ``` ### NIP-65: Relay List Metadata **Status**: Critical for routing Event kind `10002` for user's relay preferences. **Format**: ```json { "kind": 10002, "tags": [ ["r", "wss://relay1.com"], ["r", "wss://relay2.com", "write"], ["r", "wss://relay3.com", "read"] ] } ``` **Usage**: - Clients discover where to fetch user's events (read) - Clients know where to send events for user (write) - Optimizes relay connections - Reduces bandwidth **Best Practice**: - Always check NIP-65 before querying - Fall back to NIP-05 relays if no NIP-65 - Cache relay lists ### NIP-78: App-Specific Data **Status**: Application storage Event kind `30078` for arbitrary app data. **Format**: ```json { "kind": 30078, "tags": [ ["d", "<app-name>:<data-key>"] ], "content": "<encrypted-or-public-data>" } ``` **Use Cases**: - App settings - Client-specific cache - User preferences - Draft posts ### NIP-84: Highlights **Status**: Annotation Event kind `9802` for highlighting content. **Format**: ```json { "kind": 9802, "tags": [ ["e", "<event-id>"], ["context", "surrounding text..."], ["a", "<article-coordinate>"] ], "content": "highlighted portion" } ``` Like a highlighter pen for web content. ### NIP-89: Application Handlers **Status**: App discovery Advertise and discover apps that handle specific event kinds. **Format (kind 31989)**: ```json { "kind": 31989, "tags": [ ["k", "1"], // handles kind 1 ["web", "https://app.com/<bech32>"], ["ios", "app-scheme://<bech32>"], ["android", "app-package://<bech32>"] ] } ``` **Kind 31990**: User's preferred handlers ### NIP-94: File Metadata **Status**: File sharing Event kind `1063` for file metadata. **Format**: ```json { "kind": 1063, "tags": [ ["url", "https://..."], ["m", "image/jpeg"], // MIME type ["x", "<sha256-hash>"], ["size", "123456"], ["dim", "1920x1080"], ["magnet", "magnet:..."], ["blurhash", "..."] ], "content": "Description" } ``` **Use Cases**: - Images, videos, audio - Documents - Torrents - IPFS files ### NIP-96: HTTP File Storage Integration **Status**: File hosting HTTP API for file uploads/downloads. **Endpoints**: - `GET /.well-known/nostr/nip96.json` - Server info - `POST /upload` - Upload file - `DELETE /delete` - Delete file **Upload Response**: Returns kind `1063` event data for the file. ### NIP-98: HTTP Auth **Status**: API authentication Use Nostr events for HTTP API auth. **Flow**: 1. Create kind `27235` event with: - `u` tag: API URL - `method` tag: HTTP method 2. Add `Authorization: Nostr <base64-event>` header 3. Server verifies signature **Benefits**: - No passwords - Cryptographic authentication - Works with Nostr keys ## Summary of Key NIPs by Category ### Essential (All implementations) - NIP-01, NIP-02, NIP-10, NIP-19 ### Social Features - NIP-25 (reactions), NIP-18 (reposts), NIP-23 (long-form), NIP-28 (channels) ### Identity & Discovery - NIP-05 (verification), NIP-39 (external identities), NIP-65 (relay lists) ### Security & Privacy - NIP-04 (deprecated encryption), NIP-44 (modern encryption), NIP-42 (auth), NIP-13 (PoW) ### Lightning Integration - NIP-47 (wallet connect), NIP-57 (zaps) ### Content & Moderation - NIP-56 (reporting), NIP-36 (content warnings), NIP-09 (deletion) ### Advanced Features - NIP-33 (parameterized replaceable), NIP-46 (remote signing), NIP-50 (search)