1 Overview
An ecash mint is a server that issues bearer tokens backed by bitcoin. Two mint families matter here. A Cashu mint is a single server that users reach over HTTPS. A Fedimint federation is a group of servers that users join with an invite code. Before a wallet can hold ecash, it must pick a mint. Picking a mint is a trust decision.
This NIP turns that decision into Nostr events. It defines three kinds. A mint operator publishes kind:38172 (Cashu) or kind:38173 (Fedimint) to announce the mint and its capabilities. A user publishes kind:38000 to recommend a mint. Another user queries those recommendations, filters them by their follow list, and connects to a mint their friends trust.
The design mirrors NIP-89, which does the same for application handlers. Nostr's open, queryable event graph is the discovery index. No app store, no registry, no central list of mints.
All three kinds sit in the 30000–39999 range. They are addressable events under NIP-01: a relay keeps only the latest event per pubkey + kind + d-tag triple. A user can edit a recommendation, and a mint can update its announcement, without creating duplicates.
2 Parties and Flow
Three actors take part in the workflow:
- Mint operator — announces the mint and its capabilities. Publishes
kind:38173orkind:38172with connection details. - User A — recommends an ecash mint. Publishes
kind:38000. - User B — seeks a recommendation. Queries for
kind:38000, then, based on the results, queries forkind:38173/kind:38172.
| Kind | Publisher | Meaning |
|---|---|---|
| 38000 | a user | Recommendation of an ecash mint, with an optional review in content. |
| 38172 | Cashu mint | Announcement: mint URL, supported nuts, network. |
| 38173 | Fedimint | Announcement: invite codes, supported modules, network. |
3 The Recommendation Event
A user recommends a mint with a kind:38000 event. It is a parameterized-replaceable event: the user can edit the recommendation without creating a new event.
{
"kind": 38000,
"pubkey": <recommender-user-pubkey>,
"tags": [
["k", "38173"],
["d", <d-identifier>],
["u", <recommended-fedimint-invite-code>],
["a", "38173:fedimint-pubkey:<d-identifier>", "wss://relay1"]
],
"content": "I trust this mint with my life"
}
| Tag | Rule |
|---|---|
| d | The identifier of the kind:38173/kind:38172 event this event recommends. If no announcement event exists, compute the d value from the mint's pubkey or id anyway. |
| k | The kind number of the recommended announcement: 38173 for Fedimints, 38172 for Cashu mints. |
| u | Optional. A recommended way to connect to the mint: its URL or invite code. Multiple u tags may appear on one event. |
| a | Points to the mint's kind:38173/kind:38172 event. First value is the event address, second value is a relay hint. This disambiguates duplicate events that claim to be the same mint. |
The content holds an optional review in free text.
4 Mint Announcements
Cashu mints — kind 38172
A Cashu mint should publish a kind:38172 event. It announces the mint's capabilities and how to connect. The rules:
- The
utag should be the URL of the Cashu mint. - The event should list the nuts (Cashu protocol features) the mint supports.
- The
dtag should be the mint's pubkey, as returned by the mint's/v1/infoendpoint. Users can then query by pubkey and find the announcement. - An
ntag should state the network:mainnet,testnet,signet, orregtest.
{
"kind": 38172,
"pubkey": <application-pubkey>,
"content": <optional-kind:0-style-metadata>,
"tags": [
["d", <cashu mint pubkey>],
["u", "https://cashu.example.com"],
["nuts", "1,2,3,4,5,6,7"],
["n", "mainnet"]
]
}
Fedimints — kind 38173
A Fedimint should publish a kind:38173 event. The rules:
- List every known Fedimint invite code, one per
utag. - List the modules the federation supports in a
modulestag, for examplelightning,wallet,mint. - The
dtag should be the federation id. Users can then query by federation id and find the announcement. - An
ntag should state the network:mainnet,testnet,signet, orregtest.
{
"kind": 38173,
"pubkey": <application-pubkey>,
"content": <optional-kind:0-style-metadata>,
"tags": [
["d", <federation-id>],
["u", "fed11abc.."],
["u", "fed11xyz.."],
["modules", "lightning,wallet,mint"],
["n", "signet"]
]
}
In both kinds, content is an optional stringified JSON object in the style of the NIP-01 kind-0 metadata. Use it when the pubkey that signs the announcement is not a normal user. If content is empty, clients should display the mint from the pubkey's own kind:0 event: name, picture, web, LUD16, and so on.
d, k, and a, and the mint itself with u.5 Worked Example
User A recommends some mints
User A uses a Cashu mint and a Fedimint. Their client publishes one recommendation that covers both, as in the source spec:
{
"kind": 38000,
"tags": [
["u", "fed11abc..", "fedimint"],
["u", "https://cashu.example.com", "cashu"],
["a", "38173:fedimint-pubkey:<d-identifier>", "wss://relay1", "fedimint"],
["a", "38172:cashu-mint-pubkey:<d-identifier>", "wss://relay2", "cashu"]
],
...
}
This example comes straight from the source spec, and it does not match the spec's own tag rules. It adds a third element ("fedimint" / "cashu") to the u and a tags that the spec text never defines, it drops the required d tag that makes the event addressable, and it omits the k tag that the query below filters on. Treat the tag table in §3 as normative.
User B finds a mint
User B wants an ecash wallet and needs a mint. Their wallet client queries for kind:38000 recommendations, scoped to people User B follows:
-- query recommendations from the user's social graph -- → ["REQ", "mints", {"kinds":[38000], "authors":[<user>, <users-contact-list>], "#k":["38173"]}] ← ["EVENT", "mints", {"kind":38000, "pubkey":"<user A>", "tags":[["k","38173"], ["d","<federation-id>"], …], "content":"I trust this mint with my life", …}] ← ["EOSE", "mints"] -- fetch the announcement the recommendation points at -- → ["REQ", "ann", {"kinds":[38173], "authors":["<fedimint-pubkey>"], "#d":["<federation-id>"]}] ← ["EVENT", "ann", {"kind":38173, "tags":[["d","<federation-id>"], ["u","fed11abc.."], ["modules","lightning,wallet,mint"], ["n","mainnet"]], …}] ← ["EOSE", "ann"] -- User B joins the federation with invite code fed11abc.. --
User B follows User A, sees the kind:38000 event, and connects to the corresponding mint.
Alternative query, bypassing kind 38000
A client may skip recommendations and query announcements directly:
→ ["REQ", "direct", {"kinds":[38173], "authors":[...]}]
Anyone can publish an announcement event. A client that queries kind:38173/kind:38172 directly should apply spam-prevention mechanisms, or query high-quality restricted relays. Otherwise it may direct users to malicious mints.
Both REQ examples in the source spec wrap the filter in an extra JSON array: ["REQ", <id>, [{…}]]. That is invalid NIP-01 syntax; filters follow the subscription id directly. The transcripts above use the correct form.
6 Version History
NIP-87 is young and has a short history. Notable changes, newest first:
- 20262026-06Renamed to "Cashu and Fedimint Discoverability" in fiatjaf's repo-wide title cleanup.
- 20252025-08Typo fixes.
- Origin2025-07benthecarman published the NIP as "Ecash Mint Discoverability" (PR #1110).
Original Proposal - Credits
| Author | benthecarman |
| First commit | 2025-07-16 — “NIP-87: Ecash Mint Discoverability” (PR #1110) |
| Status | draft optional |
| Source | 87.md on GitHub - full change history |