Skip to content

[api] Cashu mint at mint.nostr.watch returns 403 Forbidden, blocking L402 payment flow for /v2/relays #917

Description

@c03rad0r

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:

  1. Confirmed regression: The L402 and P2PK payment flow was working the last time he tested it. Something broke in the last couple of months.
  2. 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.
  3. Patch in progress: The maintainer is working on a fix for the regression.
  4. 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

  1. Fix the L402 payment verification regression — the maintainer has confirmed this and is working on a patch
  2. Remove unreachable mints from the accepted mints list (stablenut.umint.cash, mint.azzamo.net)
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions