diff options
| author | fiatjaf <fiatjaf@gmail.com> | 2026-02-20 21:59:54 -0300 |
|---|---|---|
| committer | fiatjaf <fiatjaf@gmail.com> | 2026-02-20 22:00:48 -0300 |
| commit | 685ddacdbf7f3c7684a362c96129130241433723 (patch) | |
| tree | d44bb604f8449d474e7a758dd870eeb97699541d /63.md | |
| parent | 57cf995a474b76f5af2e3358a9dcc1c3dacec85d (diff) | |
rename from paywall/premium to exclusive.paywalls
Diffstat (limited to '63.md')
| -rw-r--r-- | 63.md | 47 |
1 files changed, 24 insertions, 23 deletions
| @@ -1,35 +1,35 @@ | |||
| 1 | NIP-63 | 1 | NIP-63 |
| 2 | ====== | 2 | ====== |
| 3 | 3 | ||
| 4 | Relay-based Paywalls | 4 | Exclusive Content |
| 5 | -------------------- | 5 | ----------------- |
| 6 | 6 | ||
| 7 | `draft` `optional` | 7 | `draft` `optional` |
| 8 | 8 | ||
| 9 | This NIP specifies how relays can support _paywalled content_. Well, "paywall" is a misnomer as this NIP doesn't imply payment necessarily, it's agnostic about that, so better call it **premium content**. | 9 | This NIP specifies how to do paywalled/gated/locked/privileged/protected/paid/subscriber/restricted/premium content on Nostr. |
| 10 | 10 | ||
| 11 | The idea is that a _content-creator_ should be able to manage a list of _premium-reader_ who have access to their premium content, then choose some specific relays to publish their content based on their known support for this NIP. | 11 | The idea is that a _content-creator_ should be able to manage a list of _exclusive-readers_ who have access to their exclusive content, then choose some specific relays to publish their content based on their known support for this NIP. |
| 12 | 12 | ||
| 13 | Relays that support this NIP (as they could indicate in their [NIP-11](11.md) responses) should receive the list of users and use it together with [NIP-42](42.md) authentication in order to decide what content will be readable by each requester. | 13 | Relays that support this NIP (as they could indicate in their [NIP-11](11.md) responses) should receive the list of users and use it together with [NIP-42](42.md) authentication in order to decide what content will be readable by each requester. |
| 14 | 14 | ||
| 15 | ### Premium event | 15 | ### Exclusive event |
| 16 | 16 | ||
| 17 | Any event can be premium, all it needs is a [NIP-70](70.md) `["-"]` tag and another tag `["nip63"]` that clearly indicates its situation. | 17 | Any event can be _exclusive_, all it needs is a [NIP-70](70.md) `["-"]` tag and another tag `["nip63"]` that clearly indicates its status. |
| 18 | 18 | ||
| 19 | Because normal relays won't care about these tags it's enough for the _content-creator_ to release the event to these relays in order to make it "public" to everybody. | 19 | (Because normal relays won't care about these tags it's enough for the _content-creator_ to release the event to these relays in order to make it "public" to everybody.) |
| 20 | 20 | ||
| 21 | ### Membership Event | 21 | ### Membership Event |
| 22 | 22 | ||
| 23 | Membership events must be sent directly to the relays that will implement the paywall. By default relays should not serve these events to anyone, only to the _content-creator_ directly. Because of this, these lists can be kept reasonably private as long as the _content-creator_ is discreet in his publishing, but can also be made public by being published to other relays. | 23 | Membership events must be sent directly to the relays that hold the exclusive content. By default relays should not serve these events to anyone, only to the _content-creator_ directly. Because of this, these lists can be kept reasonably private as long as the _content-creator_ is discreet in his publishing, but can also be made public by being published to other relays. |
| 24 | 24 | ||
| 25 | The lists are constituted of one event for each _premium-reader_, and their removal/update must be done with a [NIP-09](09.md) deletion request. | 25 | The lists are constituted of one event for each _exclusive-reader_, and their removal/update must be done with a [NIP-09](09.md) deletion request. |
| 26 | 26 | ||
| 27 | ```yaml | 27 | ```yaml |
| 28 | { | 28 | { |
| 29 | "kind": 1163, | 29 | "kind": 1163, |
| 30 | "pubkey": "<content-creator>", | 30 | "pubkey": "<content-creator>", |
| 31 | "tags": [ | 31 | "tags": [ |
| 32 | ["p", "<premium-reader>"] | 32 | ["p", "<exclusive-reader>"] |
| 33 | ], | 33 | ], |
| 34 | // ...other fields | 34 | // ...other fields |
| 35 | } | 35 | } |
| @@ -50,9 +50,9 @@ Besides marking individual public keys as readers it's also possible to tag a re | |||
| 50 | 50 | ||
| 51 | This allows for an easy way to, for example, automatically mark all the people the _content-creator_ follows as allowed to read. Or people who are in a specific `kind:30000` follow-set. | 51 | This allows for an easy way to, for example, automatically mark all the people the _content-creator_ follows as allowed to read. Or people who are in a specific `kind:30000` follow-set. |
| 52 | 52 | ||
| 53 | More importantly, it allows the _content-creator_ to delegate inclusion of readers to, for example, a payment provider, such that someone can pay and immediately become a _premium-reader_ without having to wait until the _content-creator_ is online again to update sign a new event. | 53 | More importantly, it allows the _content-creator_ to delegate inclusion of readers to, for example, a payment provider, such that someone can pay and immediately become a _exclusive-reader_ without having to wait until the _content-creator_ is online again to update sign a new event. |
| 54 | 54 | ||
| 55 | It remains a requirement that lists referenced in `"a"` tags here are sent directly to the relays that will implement the paywall, although such relays may try to fetch those in a best-effort basis. | 55 | It remains a requirement that lists referenced in `"a"` tags here are sent directly to the relays that hold the exclusive content, such that these relays don't have to go around trying to find such lists. |
| 56 | 56 | ||
| 57 | ### Relay behavior | 57 | ### Relay behavior |
| 58 | 58 | ||
| @@ -60,43 +60,44 @@ A relay that implements this NIP should: | |||
| 60 | 60 | ||
| 61 | - signal `63` in its `supported_nips` NIP-11 field; | 61 | - signal `63` in its `supported_nips` NIP-11 field; |
| 62 | - accept `kind:1163` events and not serve them to anyone except to their creator; | 62 | - accept `kind:1163` events and not serve them to anyone except to their creator; |
| 63 | - accept events referenced by `"a"` tags in `kind:1163` events it has accepted; | ||
| 63 | - accept deletion requests for such events; | 64 | - accept deletion requests for such events; |
| 64 | - accept premium events containing `["-"]` and `["nip63"]` tags only from their creator; | 65 | - accept exclusive events containing `["-"]` and `["nip63"]` tags only from their creator; |
| 65 | - only serve the premium events to users that have a matching `kind:1163`; | 66 | - only serve the exclusive events to users that have a matching `kind:1163` (directly or indirectly); |
| 66 | - serve an `AUTH` challenge to any client opening a connection immediately. | 67 | - serve an `AUTH` challenge to any client opening a connection immediately. |
| 67 | 68 | ||
| 68 | ### Client behavior | 69 | ### Client behavior |
| 69 | 70 | ||
| 70 | A client doesn't have to do much in order to access premium content: if a client is already very liberal with its authentication policies it will automatically perform NIP-42 AUTH whenever it connects to the relay; otherwise it may want to check if such relay supports `63` before deciding. | 71 | A client doesn't have to do much in order to access exclusive content: if a client is already very liberal with its authentication policies it will automatically perform NIP-42 `AUTH` whenever it connects to the relay; otherwise it may want to check if such relay supports `63` before deciding. |
| 71 | 72 | ||
| 72 | After that, any `REQ`s should include premium content automatically and transparently. This means that while constructiing a normal "following" feed a client will get the premium content automatically and place it in front of the user. | 73 | After that, any `REQ`s should include exclusive content automatically and transparently. This means that while constructiing a normal "following" feed a client will get the exclusive content automatically and place it in front of the user. |
| 73 | 74 | ||
| 74 | A client may decide to display these events differently if they have the `["nip63"]` tag. | 75 | A client may decide to display these events differently if they have the `["nip63"]` tag. |
| 75 | 76 | ||
| 76 | ### Announcement | 77 | ### Announcement |
| 77 | 78 | ||
| 78 | Optionally a _content-creator_ can announce that they have premium content available by publishing an event: | 79 | Optionally a _content-creator_ can announce that they have exclusive content available by publishing an event: |
| 79 | 80 | ||
| 80 | ``` | 81 | ```yaml |
| 81 | { | 82 | { |
| 82 | "kind": 10163, | 83 | "kind": 10163, |
| 83 | "content": "<something about the premium content, the price and other stuff, optionally>", | 84 | "content": "<something about the exclusive content, the price and other stuff, optionally>", |
| 84 | "tags": [ | 85 | "tags": [ |
| 85 | ["url", "<payment-page-url>"] | 86 | ["url", "<payment-page-url>"] |
| 86 | ] | 87 | ] |
| 87 | } | 88 | } |
| 88 | ``` | 89 | ``` |
| 89 | 90 | ||
| 90 | Where `<payment-page-url>` is a normal webpage that may have anything in it. From there on, payments are handled off-protocol. The entity that handled the payment is expected to somehow modify the list of _premium-readers_ or enable the user to modify it later. | 91 | Where `<payment-page-url>` is a normal webpage that may have anything in it. From there on, payments are handled off-protocol. The entity that handled the payment is expected to somehow modify the list of _exclusive-readers_ or enable the user to modify it later. |
| 91 | 92 | ||
| 92 | #### Zap relationship | 93 | #### Zap relationship |
| 93 | 94 | ||
| 94 | This NIP is payment agnostic, but that doesn't mean one shouldn't use zaps or nutzaps for this. Clients or third-party services may offer a feature to read all zaps, compute their sums according to any criteria and use that information to modify the list of _premium-readers_. | 95 | This NIP is payment agnostic, but that doesn't mean one shouldn't use zaps or nutzaps for this. Clients or third-party services may offer a feature to read all zaps, compute their sums according to any criteria and use that information to modify the list of _exclusive-readers_. |
| 95 | 96 | ||
| 96 | ### Future additions | 97 | ### Future additions |
| 97 | 98 | ||
| 98 | - private group announcements: NIP-29 closed groups for subscribers can be announced on the `kind:10163`. | 99 | - private group announcements: NIP-29 closed groups for subscribers can be announced on the `kind:10163`. |
| 99 | - tiered membership: custom tiers for fine-grained content access control can be added by adding a tag like `["tier", "a"]` to the `kind:1163` event and using a `["nip63", "a"]` tag in the events, for example. | 100 | - tiered membership: custom tiers for fine-grained content access control can be added by adding a tag like `["tier", "a"]` to the `kind:1163` event and using a `["nip63", "a"]` tag in the events, for example. |
| 100 | - teaser events: perhaps a `["nip63", "", "-"]` (negative) tag could cause an event to be displayed only to those that do not have access to its premium counterpart, this would also be managed by the relay. | 101 | - teaser events: perhaps a `["nip63", "", "-"]` (negative) tag could cause an event to be displayed only to those that do not have access to its exclusive counterpart, this would also be managed by the relay. |
| 101 | - relays for premium content different from the outbox relays? | 102 | - relays for exclusive content different from the outbox relays? |
| 102 | - individual "pay-per-view" content. | 103 | - individual "pay-per-view" content. |