Important Clarification
Updated 2025-06-05: The original issue below incorrectly identified the mint 403 as the root cause. Credit to @Franchovy for correctly identifying that the real issue is a persistent 402 — the API never accepts payment, regardless of which mint the Cashu tokens come from. The maintainer has confirmed this is a regression (see "Update" section below).
Summary
The L402 payment verification flow on GET /v2/relays is broken due to a regression. The API returns HTTP 402 with valid payment headers, but even when sending valid Cashu tokens from accepted mints, the response remains 402.
Context
The /v2/relays API endpoint requires a 2-sat (2000 msat) Cashu payment via the L402 protocol. The server correctly returns HTTP 402 with the expected WWW-Authenticate and X-Cashu headers, but the L402 payment verification is non-functional — the server always returns 402 regardless of valid payment.
Steps to Reproduce
1. Request the relays endpoint
curl -s -D /tmp/headers https://api.nostr.watch/v2/relays?sortBy=url&sortOrder=asc
# Response: {"error":"Payment Required"}
# HTTP Status: 402
2. Inspect the 402 response headers
The server returns proper L402 headers:
WWW-Authenticate: L402 contains:
- Macaroon (base64-decoded):
{
"routeKey": "/relays",
"priceMsat": 2000,
"paymentHash": "f94dc6fe5c45b899d3b477b31c570ea19d00d9413b6b0173237563bf5b7ad4d2",
"exp": 1780669458
}
- Lightning invoice:
lnbc20n1p4z9nszpp5... (20 sat invoice)
X-Cashu header (decoded):
{
"mint": "https://mint.nostr.watch",
"amountMsat": 2000,
"p2pkPubkey": "9bbabc5e36297b6f7d15dd21b90ef85b2f1cb80e15c37fcc0c7f6c05acfd0019",
"mints": [
"https://mint.nostr.watch",
"https://mint.minibits.cash/Bitcoin",
"https://mint.coinos.io",
"https://mint.macadamia.cash",
"https://21mint.me",
"https://stablenut.umint.cash",
"https://mint.agorist.space",
"https://mint.azzamo.net",
"https://mint.nodenebula.com",
"https://mint.lnw.cash",
"https://cashu.boats"
]
}
3. Primary mint is intentionally not public
curl -s "https://mint.nostr.watch/v1/info"
# Response: Forbidden (HTTP 403)
Note: This 403 is by design. The mint exists only to facilitate P2PK for the API payment flow — it is not meant to be a public mint.
4. Verified alternate mints are accessible
Fallback mints listed in X-Cashu respond with HTTP 200 (except stablenut.umint.cash and mint.azzamo.net which are unreachable):
| Mint |
Status |
https://mint.nostr.watch |
403 (by design — not a public mint) |
https://mint.minibits.cash/Bitcoin |
200 OK |
https://mint.coinos.io |
200 OK |
https://mint.macadamia.cash |
200 OK |
https://21mint.me |
200 OK |
https://stablenut.umint.cash |
Unreachable |
https://mint.agorist.space |
200 OK |
https://mint.azzamo.net |
Unreachable |
https://mint.nodenebula.com |
200 OK |
https://mint.lnw.cash |
200 OK |
https://cashu.boats |
200 OK |
5. Persistent 402 even with valid payment
Even when providing valid Cashu tokens from an accepted external mint (e.g., mint.minibits.cash), P2PK-locked to the pubkey specified in the X-Cashu header, and constructing a proper Authorization: L402 macaroon=<macaroon>, cashu=<token> header, the server continues to return 402.
Expected Behavior
- The L402 payment flow should be completable: pay Lightning invoice or send Cashu tokens → server verifies payment → returns relay data
- The payment verification should accept tokens from any of the listed mints in the
X-Cashu header
Impact
- The L402 payment verification flow is non-functional due to a regression
- The web UI pagination at nostr.watch also does not work, leaving no way to retrieve a full relay list
- Users cannot use the API programmatically
Update — What We Learned from the Maintainer
@Franchovy — here is what the maintainer shared on this issue:
- Confirmed regression: The L402 and P2PK payment flow was working the last time he tested it. Something broke in the last couple of months.
- Mint is intentionally private:
mint.nostr.watch is not meant to be a public mint. It exists only to facilitate P2PK for the API payment flow and has no use outside of melting tokens.
- Patch in progress: The maintainer is working on a fix for the regression.
- Planned improvements (also mentioned):
- Move from flat-rate to per-result pricing (1 sat minimum)
- Add a credit/balance system so users can overpay and carry a balance
- Add response size guards integrated with CEP-8 payment calculation, to prevent paying for oversized responses with no refund path
- These changes are especially important for CEP-8 context where responses can vary significantly in size
Suggested Fixes
- Fix the L402 payment verification regression — the maintainer has confirmed this and is working on a patch
- Remove unreachable mints from the accepted mints list (
stablenut.umint.cash, mint.azzamo.net)
- Consider implementing per-result pricing and credit system as planned by the maintainer
Environment
cashu CLI version: 0.20.0
- API endpoint:
https://api.nostr.watch/v2/relays
- Date tested: 2025-06-05
Important Clarification
Summary
The L402 payment verification flow on
GET /v2/relaysis broken due to a regression. The API returns HTTP 402 with valid payment headers, but even when sending valid Cashu tokens from accepted mints, the response remains 402.Context
The
/v2/relaysAPI endpoint requires a 2-sat (2000 msat) Cashu payment via the L402 protocol. The server correctly returns HTTP 402 with the expectedWWW-AuthenticateandX-Cashuheaders, but the L402 payment verification is non-functional — the server always returns 402 regardless of valid payment.Steps to Reproduce
1. Request the relays endpoint
2. Inspect the 402 response headers
The server returns proper L402 headers:
WWW-Authenticate: L402contains:{ "routeKey": "/relays", "priceMsat": 2000, "paymentHash": "f94dc6fe5c45b899d3b477b31c570ea19d00d9413b6b0173237563bf5b7ad4d2", "exp": 1780669458 }lnbc20n1p4z9nszpp5...(20 sat invoice)X-Cashuheader (decoded):{ "mint": "https://mint.nostr.watch", "amountMsat": 2000, "p2pkPubkey": "9bbabc5e36297b6f7d15dd21b90ef85b2f1cb80e15c37fcc0c7f6c05acfd0019", "mints": [ "https://mint.nostr.watch", "https://mint.minibits.cash/Bitcoin", "https://mint.coinos.io", "https://mint.macadamia.cash", "https://21mint.me", "https://stablenut.umint.cash", "https://mint.agorist.space", "https://mint.azzamo.net", "https://mint.nodenebula.com", "https://mint.lnw.cash", "https://cashu.boats" ] }3. Primary mint is intentionally not public
Note: This 403 is by design. The mint exists only to facilitate P2PK for the API payment flow — it is not meant to be a public mint.
4. Verified alternate mints are accessible
Fallback mints listed in
X-Cashurespond with HTTP 200 (exceptstablenut.umint.cashandmint.azzamo.netwhich are unreachable):https://mint.nostr.watchhttps://mint.minibits.cash/Bitcoinhttps://mint.coinos.iohttps://mint.macadamia.cashhttps://21mint.mehttps://stablenut.umint.cashhttps://mint.agorist.spacehttps://mint.azzamo.nethttps://mint.nodenebula.comhttps://mint.lnw.cashhttps://cashu.boats5. Persistent 402 even with valid payment
Even when providing valid Cashu tokens from an accepted external mint (e.g.,
mint.minibits.cash), P2PK-locked to the pubkey specified in theX-Cashuheader, and constructing a properAuthorization: L402 macaroon=<macaroon>, cashu=<token>header, the server continues to return 402.Expected Behavior
X-CashuheaderImpact
Update — What We Learned from the Maintainer
@Franchovy — here is what the maintainer shared on this issue:
mint.nostr.watchis not meant to be a public mint. It exists only to facilitate P2PK for the API payment flow and has no use outside of melting tokens.Suggested Fixes
stablenut.umint.cash,mint.azzamo.net)Environment
cashuCLI version: 0.20.0https://api.nostr.watch/v2/relays