NIPs by PolleramaCommunity NIPs, surfaced by trustConnect
npub19jghhl87fum...

NIP-XX: Recurring Subscriptions & Treasury Events

Published Jul 9, 2026

NIP-XX: Recurring Subscriptions & Treasury Events

draft optional

This NIP defines event kinds for managing recurring subscriptions over Lightning and automated infrastructure payments within the Nostr ecosystem.

Motivation

Creators and app operators need a protocol-native way to:

  1. Offer recurring subscriptions paid via Lightning (NWC/NIP-47)
  2. Verify subscription status from relay data without proprietary APIs
  3. Manage infrastructure payments (relays, media hosts, compute) under auditable rules

Design Goals

  • Non-custodial: No event kind implies custody of funds. Only wallet connections (NWC URIs) and rules are stored.
  • Composable: Builds on NIP-47 (Wallet Connect), NIP-57 (Zaps), NIP-17 (Private DMs), NIP-44 (Encrypted Payloads).
  • Minimal: Five event kinds cover the full lifecycle.
  • Verifiable: Any client can verify an active subscription by checking receipts signed by the plan publisher.

Event Kinds

kind 31039 — Subscription Plan (Addressable)

Published by the provider (creator/app). Defines a subscription tier.

Tags:

  • d — unique plan identifier (e.g. "supporter")
  • title — human-readable plan name
  • description — plan description
  • amount — price in millisatoshis per period
  • period — ISO-8601 duration (P7D, P1M, P1Y)
  • grace — grace period as ISO-8601 duration (e.g. P8D)
  • perk — (repeatable) one perk per tag
  • alt — human-readable description for NIP-31 compatibility
  • currency — (optional) fiat reference currency code
{
  "kind": 31039,
  "pubkey": "<provider-pubkey>",
  "tags": [
    ["d", "supporter"],
    ["title", "Supporter Tier"],
    ["description", "Full access plus exclusive content"],
    ["amount", "21000000"],
    ["period", "P1M"],
    ["grace", "P8D"],
    ["perk", "All articles"],
    ["perk", "Monthly Q&A"],
    ["alt", "Subscription plan: Supporter Tier — 21,000 sats/month"]
  ],
  "content": ""
}

kind 1359 — Subscription Agreement

Published by the subscriber, referencing the plan. This is the signed, timestamped "contract".

Tags:

  • a — plan coordinate (31039:<provider-pubkey>:<plan-d-tag>)
  • p — provider pubkey
  • alt — human-readable description

Content: May contain a NIP-44 encrypted payload with subscriber contact preferences (email hash, notification channel).

{
  "kind": 1359,
  "pubkey": "<subscriber-pubkey>",
  "tags": [
    ["a", "31039:<provider-pubkey>:supporter"],
    ["p", "<provider-pubkey>"],
    ["alt", "Subscription agreement for Supporter Tier"]
  ],
  "content": "<optional NIP-44 encrypted contact preferences>"
}

kind 6301 — Payment Receipt

Published by the provider (or its delegated billing key) after each successful payment cycle. Receipts are the public, verifiable proof of active subscription.

Tags:

  • a — plan coordinate
  • p — subscriber pubkey
  • period_start — unix timestamp of period start
  • period_end — unix timestamp of period end
  • amount — amount paid in millisatoshis
  • bolt11 — (optional) the BOLT11 invoice reference
  • preimage — (optional) payment preimage as proof
  • alt — human-readable description
{
  "kind": 6301,
  "pubkey": "<provider-pubkey>",
  "tags": [
    ["a", "31039:<provider-pubkey>:supporter"],
    ["p", "<subscriber-pubkey>"],
    ["period_start", "1719792000"],
    ["period_end", "1722470400"],
    ["amount", "21000000"],
    ["alt", "Subscription receipt: Supporter Tier — Jul 2026"]
  ],
  "content": ""
}

kind 4739 — Cancellation / Lapse Notice

Published by either party to record termination or lapse.

Tags:

  • a — plan coordinate
  • p — the other party's pubkey
  • reason"canceled", "lapsed", or "expired"
  • alt — human-readable description
{
  "kind": 4739,
  "pubkey": "<subscriber-or-provider-pubkey>",
  "tags": [
    ["a", "31039:<provider-pubkey>:supporter"],
    ["p", "<other-party-pubkey>"],
    ["reason", "canceled"],
    ["alt", "Subscription canceled: Supporter Tier"]
  ],
  "content": ""
}

kind 39729 — Treasury Rule (Addressable, Private)

Published by the creator to define automated payment rules for infrastructure. Content SHOULD be NIP-44 encrypted so configuration is portable but private.

Tags:

  • d — unique rule identifier
  • alt — human-readable description

Encrypted content (JSON):

{
  "payee": "<lightning-address-or-npub>",
  "maxAmount": 15000,
  "interval": "P1M",
  "autoPay": true,
  "category": "relay"
}

Verification Rules

A reader validates an active subscription for subscriber S on plan P as:

  1. Find the latest kind 6301 event where pubkey = plan provider AND #p contains S AND #a contains P's coordinate.
  2. Parse period_end tag.
  3. If period_end > now, the subscription is active.
  4. Additionally check no kind 4739 event exists from either party more recent than the receipt.

Privacy Considerations

  • Email addresses MUST NOT appear in plaintext on relays. Use NIP-44 encryption in kind 1359 content or SHA-256 hashes.
  • Treasury rules (kind 39729) SHOULD encrypt their content with NIP-44.
  • NWC connection strings are NEVER published as events. They are stored locally and encrypted at rest.

Interaction with NIP-47

NWC connections used for subscription pull payments SHOULD:

  • Have explicit budget caps matching amount × 1 per period
  • Include expiry dates
  • Be revocable by the subscriber at any time

The billing engine MUST be idempotent: for a given (agreement, period) pair, at most one pull payment attempt succeeds. Retries use the same period identifier to prevent double-charging.

kind 7012 — Multi-Rail Payment Receipt (Module E Extension)

Published by the provider after a payment settles via any rail (Stripe, NWC, Zaprite). Extends kind 6301 with rail identification and split allocation transparency.

Tags:

  • a — plan coordinate (if applicable)
  • p — subscriber pubkey (if known)
  • amount — gross amount in claim currency
  • currency — ISO 4217 currency code (CHF, EUR, USD, or SAT for native Lightning)
  • rail — settlement rail identifier: stripe, nwc, or zaprite
  • settled_at — unix timestamp of confirmed settlement
  • external_ref — external system reference (Stripe invoice ID, BOLT11, Zaprite order ID)
  • purposesubscription, share, ticket, crowdfund, auction-clear, one-time
  • period — (optional) billing period identifier for recurring payments
  • split — (repeatable) allocation tag: ["split", "<label>", "<amount>", "<percentage>", "<pubkey?>"]
  • fee — estimated processing fee amount
  • alt — human-readable description
{
  "kind": 7012,
  "pubkey": "<provider-pubkey>",
  "tags": [
    ["a", "31039:<provider-pubkey>:supporter"],
    ["p", "<subscriber-pubkey>"],
    ["amount", "19.00"],
    ["currency", "CHF"],
    ["rail", "stripe"],
    ["settled_at", "1720454400"],
    ["external_ref", "in_live_abc123"],
    ["purpose", "subscription"],
    ["period", "1720454400-1723132800"],
    ["split", "Autorin", "14.44", "80"],
    ["split", "Gemeinsame Kasse", "2.71", "15"],
    ["split", "Abwicklung", "0.90", "5"],
    ["fee", "0.95"],
    ["alt", "Payment receipt: 19.00 CHF via stripe for subscription"]
  ],
  "content": ""
}

Design Notes:

  • kind 7012 complements kind 6301 (which remains the Lightning-native receipt). Applications SHOULD query both kinds for complete payment history.
  • The rail tag enables clients to filter/display receipts by payment method without inspecting rail-specific metadata.
  • split tags make the payout breakdown verifiable by any third party — this transparency is a feature, not a leak (Bajour logic for community-funded media).
  • The fee tag shows the displayed estimate. The platform may absorb higher actual fees (for small card payments) to give authors a predictable rate.

Prior Art

This NIP was designed with awareness of earlier NIP-88 (recurring subscription) proposals. Key divergences:

  • Uses generated, conflict-free kind numbers rather than assumed ranges
  • Separates agreement (subscriber-signed) from receipt (provider-signed) for bilateral auditability
  • Adds treasury management events for infrastructure spend
  • Specifies verification rules for third-party status checks (enabling Module C embeddable primitives)

NIP-XX — Stablezaps: Asset-Denominated Zaps & Recurring Subscriptions

draft optional

Status: Draft v0.1 (skeleton for review) · Author: Pareto / Athanor Studio · License: Public domain Depends on: NIP-01, NIP-57 (Lightning Zaps), NIP-47 (Nostr Wallet Connect) · Relates to: BOLT11, BOLT12, Taproot Assets (Lightning Labs), RGB Kind numbers are provisional pending the NIP review process.


Abstract

This NIP extends NIP-57 zaps with asset denomination (e.g., USDT) and defines a minimal, ledger-derived subscription scheme on top of them. It allows a payment request to be denominated in a stable unit, settled over Lightning either natively (Taproot Assets / RGB asset invoices) or in BTC at a disclosed rate, and it allows recurring creator revenue ("$5/month") whose entire state — active, lapsed, cancelled — is derivable from public zap receipts alone. No custodian, no subscription database, no platform.

Motivation

Zaps made value transfer a native gesture of the social web, but they are denominated in a volatile unit. Tips work in sats; income does not: the proven revenue model of independent publishing is the fixed-price monthly subscription, and it cannot be priced in an asset that moves 10% in a week. Since USDT became transactable over Lightning via Taproot Assets (March 2026), stable-denominated settlement on open rails is possible — what is missing is the Nostr convention that lets any client display, request, verify, and renew such payments interoperably. This NIP is that convention.

Design goals, in order: (1) auditability — every claim about who paid whom, how much, in what unit, must be verifiable from public events and the embedded invoice, never from a self-declared tag alone; (2) backwards compatibility — a NIP-57-only client must degrade gracefully; (3) settlement neutrality — BTC remains the universal settlement asset; asset-denominated requests MUST remain payable in BTC; (4) issuer honesty — clients implementing this NIP MUST NOT present issuer-backed assets as trustless (see Security Considerations).

Terminology

  • Stablezap — a zap whose requested amount is denominated in a non-BTC unit.
  • Asset invoice — a BOLT11/BOLT12 invoice carrying a Taproot Assets or RGB asset transfer.
  • Minor units — integer amounts in the smallest customary unit of the denomination (cents for USD-pegged assets).
  • Offer — a creator-published subscription product.
  • Cycle — one billing period of an offer.

1. Asset-denominated zap requests (extends kind 9734)

A stablezap request is a standard NIP-57 zap request with the following additional tags:

{
  "kind": 9734,
  "tags": [
    ["relays", "..."],
    ["p", "<recipient-pubkey>"],
    ["e", "<zapped-event-id>"],
    ["amount", "<msats-equivalent>"],
    ["unit", "USDT"],
    ["uamount", "500", "2"],
    ["asset", "<asset-id>", "taproot"],
    ["settle", "asset", "btc"]
  ],
  "content": ""
}

Rules:

  • unit + uamount together define the denominated amount. uamount MUST be an integer string; the second element is the decimal count. Clients MUST NOT use floats anywhere.
  • asset identifies the concrete on-Lightning asset when native settlement is desired. If absent, the request is denomination-only and settlement is expected in BTC at a disclosed rate.
  • settle lists acceptable settlement paths. ["settle", "btc"] alone makes this a display-denominated zap ("$5, paid in sats"). ["settle", "asset"] alone demands native asset settlement; wallets that cannot comply MUST fail rather than silently settle in BTC.
  • If amount (msats) is present alongside uamount, it is a courtesy fallback for NIP-57-only wallets; the denominated amount is authoritative for stablezap-aware clients.

1.1 LNURL / lud16 extension

The recipient's LNURL-pay endpoint advertises stablezap capability by adding to its response:

{
  "allowsNostr": true,
  "nostrPubkey": "...",
  "stablezaps": {
    "units": ["USDT"],
    "assets": [{"id": "<asset-id>", "proto": "taproot", "unit": "USDT"}],
    "settlement": ["asset", "btc"]
  }
}

When the payer requests an invoice for a stablezap, the endpoint MUST return either (a) an asset invoice matching asset/uamount exactly, or (b) a BTC invoice whose msat amount reflects the denominated amount at the endpoint's current rate, in which case the endpoint MUST also return "rate": "<msats-per-minor-unit>" so the payer can verify the conversion before paying. Payers SHOULD reject rates deviating more than a client-configured tolerance from an independent reference.

2. Stablezap receipts (extends kind 9735)

The zap receipt mirrors NIP-57 and adds:

{
  "kind": 9735,
  "tags": [
    ["p", "..."], ["e", "..."],
    ["bolt11", "<invoice>"],
    ["description", "<zap-request-json>"],
    ["preimage", "..."],
    ["unit", "USDT"],
    ["uamount", "500", "2"],
    ["asset", "<asset-id>", "taproot"],
    ["rate", "<msats-per-minor-unit>"]
  ]
}

2.1 Verification rules (normative)

A receipt claims a stable amount only if it survives all of the following; clients computing totals, leaderboards, or subscription state MUST apply them:

  1. The embedded zap request (in description) parses, is validly signed, and its p/e/a targets match the receipt's tags.
  2. Native settlement: the decoded invoice is an asset invoice whose asset id equals the asset tag and whose asset amount equals uamount. The self-declared tags are display hints; the invoice is the truth.
  3. BTC settlement: the decoded invoice's msat amount equals uamount × rate within rounding of one minor unit. Clients SHOULD flag receipts whose rate deviates grossly from historical reference rates for the receipt's timestamp.
  4. The receipt is published by the recipient's LNURL provider pubkey as declared in their profile metadata, where verifiable (as in NIP-57).
  5. Deduplication by receipt id; one receipt counts once.

Receipts failing 1–4 MUST be treated as unverified and MUST NOT contribute to any displayed stable-denominated total.

3. Subscription offers (addressable kind 37555, provisional)

A creator publishes an offer:

{
  "kind": 37555,
  "tags": [
    ["d", "<offer-id>"],
    ["title", "Freischwebende Intelligenz — Supporter"],
    ["unit", "USDT"],
    ["uamount", "500", "2"],
    ["period", "2592000"],
    ["grace", "259200"],
    ["asset", "<asset-id>", "taproot"],
    ["settle", "asset", "btc"],
    ["benefit", "Full archive access"],
    ["visibility", "public"]
  ],
  "content": "<markdown description>"
}

4. Subscription state — derived from the ledger, not declared

There is deliberately no "subscription status" event signed by anyone. State is computed:

  • A cycle payment is a verified stablezap receipt (per §2.1) whose embedded request contains an a tag referencing the offer (37555:<pubkey>:<offer-id>) and a cycle tag: ["cycle", "<unix-start-of-cycle>"].
  • A subscriber is active for cycle N iff a verified cycle payment exists for N, or for N−1 within the offer's grace window.
  • A subscriber lapses by simply not paying. Cancellation requires no permission and no event — though a client MAY publish kind 7556 (["a", <offer-address>], empty content) as a courtesy signal to stop renewal reminders.
  • Creators verify entitlement by querying receipts against their own offer address — one relay query, no database. Any third party can audit a creator's subscriber revenue the same way. The engagement report and the payment ledger are the same document.

4.1 Renewal execution

Non-custodial auto-renewal is delegated to NIP-47 budgets: the subscriber grants their NWC-connected wallet a standing permission scoped to (offer-address, uamount, unit, period); the client (or the wallet itself) executes the cycle payment when due. Where no NWC budget exists, clients fall back to reminder-based renewal (a local or DM notification with a one-tap pay action). Implementations MUST NOT build custodial pull-payment schemes to work around this; the inconvenience is the cost of self-custody and is accepted by design.

5. Privacy modes

  • visibility: public (default): receipts are ordinary public events. Maximal auditability; the subscriber list is effectively public. Appropriate for patronage.
  • visibility: private: cycle payments are wrapped per NIP-59 (gift wrap) to the creator; the creator's entitlement checks work as in §4 over unwrapped receipts, but third-party auditability is lost and totals become claims, not proofs. Clients MUST label privately-settled totals as unaudited.

The trade-off is stated rather than hidden: this NIP considers public-by-default the honest configuration for creator revenue and private mode the concession to subscriber privacy.

6. Backwards compatibility

  • NIP-57-only clients see stablezap receipts as ordinary zaps (and, where the amount fallback was set, display a sats value). Nothing breaks.
  • NIP-57-only wallets can pay denomination-only requests via the BTC fallback path (§1.1 b).
  • Offers (37555) are invisible to legacy clients; entitlement checks are the publisher's concern, so degradation is graceful.

7. Security & trust considerations

  1. Issuer risk is not abstracted away. USDT and comparable assets are centrally issued and freezable. Clients implementing this NIP MUST NOT describe asset-settled balances or streams as censorship-resistant, and SHOULD display an issuer-risk notice at the point where a user first opts into asset settlement. Sats remain the base layer; this NIP standardizes the pragmatic layer above it — the distinction is part of the spec, not marketing.
  2. Rate honesty. BTC-settled denominated zaps are the main manipulation surface (inflated rate → inflated displayed dollar totals). Hence §2.1(3): the invoice arithmetic, not the tag, is authoritative, and gross rate outliers are flagged.
  3. Fake-asset invoices. Wallets MUST verify asset ids against the offer/request before paying; a matching ticker string is not a matching asset.
  4. Replay/duplication. Receipt-id dedupe plus cycle-tag uniqueness (one counted payment per subscriber per cycle; extras are tips).
  5. Regulatory surface. A subscription is a payment for published content; this NIP defines no custody, no pooling, no exchange function. Implementers adding fiat on/off-ramps or custodial wallets import their own regulatory obligations, outside this spec's scope.

8. Reference flows (informative)

A. One-off stablezap, native settlement: client builds 9734 with unit/uamount/asset → LNURL endpoint returns taproot asset invoice → wallet (asset-capable) pays → provider publishes 9735 with asset tag → verifiers apply §2.1(2).

B. One-off stablezap, BTC settlement: as above, endpoint returns BTC invoice + rate → any NIP-57 wallet pays → 9735 carries rate → verifiers apply §2.1(3).

C. Subscription lifecycle: creator publishes 37555 → subscriber's first cycle payment (receipt with a + cycle) → NWC budget authorized → wallet auto-pays each cycle → subscriber stops payment or publishes 7556 → state lapses after grace. No party ever asked permission of a platform.

9. Open questions for review

  1. Kind numbers (37555, 7556) — collision review against deployed kinds required before merge.
  2. BOLT12 offers as the renewal primitive (recurrence field) once wallet support matures — could replace NWC budgets as the preferred path.
  3. Multi-asset offers (same price, several acceptable assets) — repeatable asset tags vs. separate offers.
  4. Proration and price changes mid-subscription — current position: a price change is a new offer; old offers are honored until lapse.
  5. Whether rate should additionally cite a signed oracle attestation rather than relying on outlier detection alone.

Skeleton v0.1 — circulated for comment. Reference implementation planned in Conciergstr (billing engine) and the shared zap-validation module used across Pareto/Athanor clients.