sats/token

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.

operator consolesimulated model
input 0 tok · 0 msat
output appears here

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.

model upstreamaperture 402 + meteragent buyer
tokens in
0
tokens out
0
metered
0msat
bundles bought
0
bundle balance no credential≈ $0.00000000 spent
remainingmetered, not yet debitedreservation
GetPrice ChallengeMinted AuthorizeRequest ReportUsage

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.

  1. Sign-up wallAn account before the first token.
  2. Fraud checksInvasive verification for a few cents of usage.
  3. Minimum top-upYou wanted to try a model, not prepay a month.
  4. Unsupported countriesThe rail decides who may buy.
  5. Keys tied to a humanSomeone who can be charged later.
Tweet from Dax (@thdxr), Aug 25, 2026: Stripe has blocked 300M USD worth of fraud for OpenCode in the past few days, with a dashboard showing 323,033,617.04 USD blocked and 8,254,735.82 USD failed.
A public screenshot from OpenCode's CEO: Stripe's dashboard showing blocked fraud over a few days. Figure still being confirmed.

Fallible defenses stand between a payment that can be undone and a product that cannot.

Pick a rail whose properties match the product.

seconds

Final settlement

A payment settles within seconds, and settles finally. A preimage either exists or it does not. There is nothing to charge back.

0 identity

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.

1 msat

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.

scrubber / tokens served on day 0card vs lightning, day 0 to day 120
Cardreversible for 60 to 120 days
Lightningfinal within seconds

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.

transcriptillustrative header shapes, not a wire capture

        
buyer to aperture1 / 6

One 402, two doors. The buyer picks whichever it speaks.
L402Payment HTTP Authentication Scheme (MPP)
SpecL402 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.
CredentialMacaroon plus the preimage of the invoice you paid.A payload carrying the preimage, in an Authorization: Payment header.
Meter keyThe 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.
IntentsPay 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.
ApertureOffered 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.

01GetPriceBefore aperture mints a 402Quotes the bundle price for this request's model.
02ChallengeMintedAs the 402 is mintedBooks a bundle against the credential's key, so a balance exists before the payment arrives.
03AuthorizeRequestOn each authenticated requestAdmits or refuses against the balance, and reserves an estimate (the request's max_tokens when it names one).
04ReportUsageWhen the response finishesDebits the usage the upstream reported, rounded up, and releases the reservation.
born

A bundle is born when the 402 is minted, not when it is paid. An unpaid booking expires after ten minutes.

reserved

The reservation stops ten concurrent requests from each being admitted against the same last thousand tokens.

debited

The debit is weighted by direction when the prompt and completion split is known, so output-heavy work pays the output rate.

exhausted

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.

lightmeter pricing, $/Mtok to msat/tokenregtest demo values
inputoutput
upstream $/Mtok
msat/token, raw
with margin
rounded up (quoted rate)
one bundle, blended rate sats

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.

Wavelength payment path The buyer funds the agent wallet from a phone. The agent pays from its Ark balance through the Wavelength swap server over Lightning. Aperture's seller wallet is credited with inbound liquidity from the swap server. Neither side runs channels or a node. phoneWavelength app agent walletArk, in-process swap serverArk to Lightning apertureseller wallet, no node /fund pay invoice Lightning inbound liquidity from the swap server no channels, no inbound capacity
with a node
  • Open and balance channels
  • Source inbound liquidity
  • Keep a process online
with wavelength
  • Buyer: /fund prints an invoice; pay it from the phone app and the sats land in seconds
  • Buyer: /deposit gives 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.

  1. First call gets a 402. The provider owns the request path.
  2. Budget policy checks the quote against a per-request ceiling and a daily cap, before any wallet action.
  3. The embedded wallet pays the invoice and the credential goes in the cache.
  4. 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.

budget policywhatever you fund is the ceiling
wallet20,000
spent today0
402s paid0

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.

selleraperture + lightmeter (or meterd) + a Wavelength wallet

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.

1 aperture.yaml
# 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: true
2 lightmeter.yaml
listenaddr: "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 spot
3 start the price server
go build ./cmd/lightmeterd
./lightmeterd --config lightmeter.yaml
buyerpi-402 in the Pi coding agent

The buyer holds sats, not a key. Point it at your seller's aperture, fund the wallet, pick a model, prompt.

1 install and point at the seller
pi install npm:@lightninglabs/pi-402
export L402_PROXY_URL=https://your-seller.example/v1   # your seller; include the /v1 prefix
2 inside Pi
/fund 20000                       # invoice; pay it from the Wavelength app
/model l402-baseten/kimi-k3
# then prompt as usual. /balance and /receipts show the ledger
3 optional budget limits
export PI402_MAX_SAT_PER_REQUEST=...   # per-request ceiling
export PI402_DAILY_CAP_SAT=...         # daily ceiling

Wallet backend env vars (sidecar gateway or embedded WASM) and install alternatives are in the pi-402 README.