inference, metered
Sats/token
Sell inference by the token, paid in sats (Bitcoin). The payment is final in seconds, so there are no accounts, no buyer-side API keys, and no cards.
No model runs in this page. Token counts are an estimate (about 4 characters each); a real seller bills the usage the upstream reports. Demo bundle is 1,000 tokens (a real bundle is 1,000,000). Press Ctrl+Enter to run.
01 / the problem
A token is irreversible. A card payment is not.
Generating a token draws joules from the grid and turns them into heat and part of a response. No message from a card network can reach back and recover that energy. So if you sell inference on cards, you are a lender, not a merchant.
You allocate scarce GPU time now, for an amount you do not know in advance, and learn somewhere between 60 and 120 days later whether you were paid. Each familiar barrier is an attempt to underwrite that loan, and the fraud you fail to catch is the default rate.
- Sign-up wallAn account before the first token.
- Fraud checksInvasive verification for a few cents of usage.
- Minimum top-upYou wanted to try a model, not prepay a month.
- Unsupported countriesThe rail decides who may buy.
- Keys tied to a humanSomeone who can be charged later.
Pick a rail whose properties match the product.
Final settlement
A payment settles within seconds, and settles finally. A preimage either exists or it does not. There is nothing to charge back.
No identity attached
Card fraud works because a payment is a claim on a person, which can be borrowed or stolen. A Lightning payment is not a claim on anyone.
Tiny amounts
The unit is the millisatoshi, 1/1000 of a sat (about $0.00000079 at the time of writing). You can price a single token.
Card
Lightning
02 / how it works
The payment is the credential.
The server answers an unpaid request with HTTP 402: a macaroon that commits to an invoice's payment hash, plus the invoice. Paying reveals the preimage, and macaroon plus preimage is the credential. A valid credential cannot exist without settlement. No sign-up, no key issuance, no account.
| L402 | Payment HTTP Authentication Scheme (MPP) | |
|---|---|---|
| Spec | L402 on HTTP 402, docs. A macaroon bound to the invoice's payment hash. | draft-httpauth-payment-00, an IETF draft co-authored by Stripe and Tempo. Nearly the same shape. |
| Credential | Macaroon plus the preimage of the invoice you paid. | A payload carrying the preimage, in an Authorization: Payment header. |
| Meter key | The random token ID inside the macaroon. | The payment hash, derived from the preimage itself. Each 402 books one bundle per door; only the paid one is drawn down. |
| Intents | Pay once, present the same credential until the bundle refuses. | charge: pay per challenge. session: a deposit, bearer requests against a running balance, a metered refund on close. |
| Aperture | Offered on every 402. | Offered alongside L402 with --authenticator.enablempp; sessions with --authenticator.enablesessions. |
pi-402 takes a Payment offer when the seller makes one and falls back to L402. It accepts the charge intent by default; session needs a return-invoice minter that the swap-backed wallet cannot supply yet.
03 / metering
Charge for the thing that varies.
One request costs the seller a few dozen tokens, the next a few thousand, and the seller only learns which once the response is served. So the payment happens once, up front, for a bundle, and the accounting happens per request, from the usage the upstream actually reported. At 1 msat per input token and 2 msat per output token, that is roughly $0.79 / $1.57 per million tokens at the time of writing.
The four calls below are the same chips that light up in the meter at the top of the page. Run a completion there and watch them fire.
max_tokens when it names one).A bundle is born when the 402 is minted, not when it is paid. An unpaid booking expires after ten minutes.
The reservation stops ten concurrent requests from each being admitted against the same last thousand tokens.
The debit is weighted by direction when the prompt and completion split is known, so output-heavy work pays the output rate.
A request that would overdraw gets a fresh 402 naming the next bundle. Exhaustion, not the credential, ends a bundle.
Aperture ships meterd. A real seller wants lightmeter.
meterd is the minimal price server: a JSON file of per-model rates. Lightmeter is the reference daemon for a real seller. It knows what each model costs, reads the upstream provider's catalog, tracks the BTC/USD rate, converts dollars per million tokens to msat per token, adds an optional margin, and keeps a SQLite database with an append-only accounting ledger for reconciliation. Try the conversion with the values from the regtest demo config.
| input | output | |
|---|---|---|
| upstream $/Mtok | ||
| msat/token, raw | ||
| with margin | ||
| rounded up (quoted rate) |
04 / wavelength
No node. No channels. Nothing to keep online.
Running a Lightning node means channels, inbound liquidity, and a process that has to stay online. Too much to ask of a seller who wants to sell tokens, and far more than you would ask of a wallet living inside a coding agent. Wavelength is an Ark wallet that pays a BOLT11 invoice through a swap server, so both sides skip it.
- Open and balance channels
- Source inbound liquidity
- Keep a process online
- Buyer:
/fundprints an invoice; pay it from the phone app and the sats land in seconds - Buyer:
/depositgives an on-chain address for the patient path - Seller: aperture mints challenge invoices from a Wavelength wallet instead of lnd
05 / agents
Agents pay for their own inference.
Plenty of agents can pay a Lightning invoice for an API. Here the metered thing is the model call itself, priced by the token and settled by the preimage. pi-402 is one example: an extension for the Pi coding agent that registers a paid model provider. Pi is unmodified.
- First call gets a 402. The provider owns the request path.
- Budget policy checks the quote against a per-request ceiling and a daily cap, before any wallet action.
- The embedded wallet pays the invoice and the credential goes in the cache.
- The request retries and streams back. The agent loop never learns it bought anything.
No API key ever reaches the buyer. The proxy holds the model credential and injects it server-side, so the buyer holds sats and the seller holds the key.
Illustrative. Each call hits a fresh 402 for the bundle quote shown. The real policy asserts on the quoted total outflow, not the invoice face value, so swap fees count against the ceiling.
06 / run it yourself
Bring your own seller.
There is no hosted endpoint at launch. You run aperture and a price server in front of any OpenAI-compatible upstream, then point a buyer at it. Config below is trimmed from the regtest demo profile; the READMEs have the full steps.
The model key lives in aperture's environment, never in the buyer's. Challenge invoices come from a Wavelength wallet, so there is no node to run.
# challenge invoices come from a Wavelength wallet, not lnd
listenaddr: "127.0.0.1:8404"
authenticator:
network: "regtest"
wavelengthgateway: "https://your-wavelength-gateway.example" # your gateway; the regtest demo runs one locally
services:
- name: "inference"
hostregexp: ".*"
pathregexp: "^/v1/.*"
address: "inference.baseten.co" # any OpenAI-compatible upstream
protocol: "https"
auth: "on"
headers:
Authorization: "Bearer ${BASETEN_GLM_5_2}"
dynamicprice:
enabled: true
grpcaddress: "127.0.0.1:10025"
insecure: true
metered: truelistenaddr: "127.0.0.1:10025"
dbpath: "lightmeter.regtest.db"
defaultmodel: "moonshotai/Kimi-K3"
bundletokens: 1000000
models:
"moonshotai/Kimi-K3":
inputusdpermtok: 3.00
outputusdpermtok: 15.00
pricing:
marginpercent: 25
btcusd:
staticrate: 100000 # pinned for regtest; 0 polls spotgo build ./cmd/lightmeterd
./lightmeterd --config lightmeter.yamlThe buyer holds sats, not a key. Point it at your seller's aperture, fund the wallet, pick a model, prompt.
pi install npm:@lightninglabs/pi-402
export L402_PROXY_URL=https://your-seller.example/v1 # your seller; include the /v1 prefix/fund 20000 # invoice; pay it from the Wavelength app
/model l402-baseten/kimi-k3
# then prompt as usual. /balance and /receipts show the ledgerexport PI402_MAX_SAT_PER_REQUEST=... # per-request ceiling
export PI402_DAILY_CAP_SAT=... # daily ceilingWallet backend env vars (sidecar gateway or embedded WASM) and install alternatives are in the pi-402 README.
