Last week I shipped AtlasData, a pay-per-call crypto data API where the buyer is usually not a human — it is an agent that holds a wallet. Getting paid per request without accounts, API keys, or invoices meant implementing both of the protocols that actually work today: x402 (USDC on Base) and L402 (Lightning sats). Here is what I learned running both on the same FastAPI app.

The shape of both protocols

Both live on HTTP 402 Payment Required:

curl -i https://atlasdata.shares.zrok.io/api/price/BTC # HTTP/2 402 # {"payment": {"maxAmountRequired":"1000", "asset":"USDC", "network":"eip155:8453", ...}} curl -i https://atlasdata.shares.zrok.io/l402/btc/fees # HTTP/2 402 # www-authenticate: L402 macaroon="...", invoice="lnbc100n1..." 

The difference is the proof. x402 returns an EIP-3009 transferWithAuthorization the client signs; a facilitator settles it onchain, then your server serves the response. L402 pairs a macaroon with a BOLT11 invoice — after paying, the client retries with Authorization: L402 <token>:<preimage> and you verify sha256(preimage) == payment_hash with zero stored state.

Why run both

  • x402 buyers are mostly EVM-native agents (CDP wallets, Coinbase's Bazaar discovery). Settlement is a stablecoin transfer — clean accounting, but every call is a chain transaction.
  • L402 buyers are Lightning-native (the sats crowd, Nostr agents). No facilitator, instant finality, and the credential can be reused until caveats expire — closer to a bearer capability than a payment.

Per-request stablecoin settlement vs. prepaid capability — different trust models, same 402 status.

The boring parts that mattered

  1. Discovery docs are the product. Agents do not browse — they read /.well-known/x402, /openapi.json with x-payment-info hints, and /llms.txt. Half my paid traffic comes from crawlers, not humans.
  2. Return a real challenge, not a marketing page. Any error string that is not a parseable 402 payload breaks machine clients. I verify with curl -i from a clean shell — browsers see the tunnel's interstitial, agents see the 402.
  3. One fee model, two prices. Each route has one USD price expressed twice: $0.001 for x402 or ~10 sats for L402. Keep them equivalent; arbitrage hunters notice.
  4. Reject bad params before the paywall. A 404 must come before a 402 — agents will retry a paid request forever if you let them pay into a 404.

The catalog today: spot prices, 24h tickers, mempool fees, Base gas/blocks, ERC-20 metadata, wallet balances, Dexscreener pairs, Fear & Greed, plus a few paid research reports ($0.50 / 200 sats). Everything is discoverable from /llms.txt and /openapi.json.

If you are building paid APIs for agents, run both rails — the audiences barely overlap, and the marginal cost of the second middleware is tiny.