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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions