open402

HTTP finally gets paid.

HTTP has reserved the 402 Payment Required status since 1991. open402 makes it real — a simple, open protocol and TypeScript SDK that lets any server charge per-request and any client pay transparently. No subscriptions. No API keys. No intermediaries.

How it works
  1. Request — client requests a paywalled resource
  2. 402 — server responds with payment headers: amount, currency, methods, endpoint
  3. Invoice — client posts to /.well-known/402/pay to create an invoice
  4. Pay — client pays via their wallet (Lightning, Stripe, USDC…)
  5. Poll — client polls GET /.well-known/402/pay/:id until receipt is ready
  6. Receipt — server issues a self-verifying JWT signed with ES256
  7. 200 — client retries with Payment-Receipt: <jwt>, server responds
Wire format

Server → Client (402)

HTTP/1.1 402 Payment Required
Payment-Amount: 1000
Payment-Currency: BTC
Payment-Methods: lightning
Payment-Description: Premium market data
Payment-Expiry: 1742003600
Payment-Endpoint: https://api.example.com/.well-known/402/pay

Client → Server (retry)

GET /api/data HTTP/1.1
Payment-Receipt: eyJhbGciOiJFUzI1NiJ9…
Server
Express · TypeScript
import express from 'express'
import { Open402Server, createWellKnownRouter, paywall } from '@open402/server'

const app = express()
app.use(express.json())

const pay402 = new Open402Server()
await pay402.init()

pay402.registerAdapter(myLightningAdapter)
app.use('/.well-known/402', createWellKnownRouter(pay402))

app.get(
  '/api/data',
  paywall(pay402, { path: '/api/data', amount: 1000, currency: 'BTC' }),
  (req, res) => res.json({ secret: 'the data' }),
)
Client
TypeScript · Browser or Node
import { Open402Client } from '@open402/client'
import { WebLNWallet } from '@open402/lightning'

const client = new Open402Client({ wallet: new WebLNWallet() })

// automatically handles 402, pays, and retries
const res = await client.fetch('https://api.example.com/api/data')
const data = await res.json()
Packages
Design principles

Currency-agnostic

The protocol defines headers and a receipt format. Payment adapters are plug-in. Lightning ships first; any payment rail can implement the interface.

Self-verifying receipts

Receipts are ES256 JWTs signed by the server's own keypair, published at GET /.well-known/402. No central authority. No third-party verification service.

Interoperable

The protocol spec is language-agnostic. Any HTTP server can issue 402s. Any HTTP client can pay them.