# 402-announce

> Announce HTTP 402 services on Nostr for decentralised discovery

## What it does

402-announce publishes kind 31402 parameterised replaceable Nostr events that describe paid HTTP APIs. AI agents and Nostr clients discover these announcements to find services they can pay for and consume — no central registry needed.

## Kind 31402 — disambiguation

This library uses kind 31402 for **L402/x402 service announcements** (paid API discovery). This is distinct from any SARA (revenue share) proposals that may also reference kind 31402. The 402-announce definition: a parameterised replaceable event (NIP-33) where pubkey + d-tag uniquely identifies one service listing.

## Key concepts

- **Kind 31402**: Nostr event kind for L402/x402 service announcements. Parameterised replaceable — same pubkey + identifier updates the existing listing.
- **Payment methods**: Services declare accepted payment methods via multi-element `pmi` tags. Each `paymentMethods` entry is `[rail, ...params]` (e.g. `['l402', 'lightning']`, `['cashu']`, `['lnurlcash', 'mint.example']`, `['x402', 'base', 'usdc', '<addr>']`, `['payment', 'lightning']`).
- **Pricing**: Per-capability pricing via `price` tags (capability name, amount, currency).
- **Decentralised discovery**: Events are published to standard Nostr relays. Any client can subscribe and filter.
- **Multi-transport**: A single event can carry multiple `url` tags (1–10). Use this when the same service is reachable via clearnet, Tor (.onion), or Handshake domains.

## API surface

Paid-API exports:

- `announceService(config)`: build, sign, and publish to relays. Returns `{ eventId, pubkey, close() }`. Invalid config rejects the promise. Relay failures never reject: if every relay fails it still resolves with the `eventId` of the signed event (no relay accepted it) and logs a warning; the handle does not report how many relays accepted.
- `buildAnnounceEvent(secretKey, config)` — build and sign without publishing. Returns a `VerifiedEvent`.
- `isPrivateHost(hostname)`: utility that returns true if hostname is a private/loopback/link-local/reserved address (SSRF guard). String check only, no DNS resolution.

Exported constant: `L402_ANNOUNCE_KIND = 31402`. Exported types: `AnnounceConfig`, `Announcement`, `PricingDef` (`capability`, `price`, `currency`), `CapabilityDef` (`name`, `description`, optional `endpoint`, `schema`, `outputSchema`). `currency` is a free-form string (non-blank, up to 32 characters), not an enumeration.

URL rules for `urls` (1-10 unique entries): each must parse with `new URL()`, be at most 2048 characters, and not use `data:`, `file:`, `javascript:`, `blob:` or `vbscript:`. `announceService` also needs at least one public URL (http/https host not matched by `isPrivateHost`, a `.onion` host, or a non-http scheme); `buildAnnounceEvent` allows private hosts.

Module format: ESM-only, no `require` export condition. Use `import` (or `await import()` from CommonJS).

Experimental storage extension, exported from `402-announce/storage` (and the package root): `buildStorageAnnouncement`,
`acceptSignedStorageAnnouncement`, `parseStorageAnnouncement`,
`selectStorageAnnouncements`, `validateStorageDescription` and
`validateStorageEndpointBinding`. These are pure, key-free functions for paid,
free-mirror and combined storage descriptions. They do not publish, contact a
node or purchase storage. Flow: build (unsigned) -> external signer -> accept -> select -> bind to endpoint; the `402-announce/storage` subpath carries only the six functions, while `STORAGE_*` constants and storage types are root-only. Contract: docs/storage-service-v1.md; machine schema:
schemas/storage-service-v1.schema.json; signed fixture manifest:
fixtures/storage-v1/manifest.json. Native publisher and consumer UI remain separate.

## Ecosystem position

```
toll-booth (paywall)         → protects your API with L402
toll-booth-announce (bridge) → maps toll-booth config to 402-announce automatically
402-announce (this)          → tells the world your API exists via kind 31402
402-mcp (discovery)          → AI agents find, pay, and consume your API
402.pub (dashboard)          → live view of all announcing services
```

## Details

For full API reference, event format, integration patterns, and examples see:
- llms-full.txt (comprehensive reference)
- README.md (human-oriented documentation with diagrams)
- Source: https://github.com/forgesworn/402-announce
