Lightning Labs announced Aperture v0.6.0 on November 12, 2026, alongside pi402, a tool that lets coding agents pay for AI inference in bitcoin, according to Lightning News coverage of the launch. Aperture is the seller-side piece. It sits in front of your API, answers unpaid requests with HTTP 402 and a Lightning invoice, and lets paid requests through. Put one in front of a plain Python API on a private regtest network, charge 25 sats per token, and pay it from a second node.

Regtest keeps the stakes at zero. You mine blocks on demand, open channels in seconds, and break the paywall as often as you like before a real satoshi moves. If you have never run a node, setting up your own LND node first will make the lab feel familiar, though the scripts below build everything from scratch.

The finished lab has two LND nodes (a seller called alice and a buyer called bob), a Bitcoin Core 32.1 backend, a Python API on port 8000, Aperture on port 8081, and a client script that pays invoices on its own, caps what it will spend, and reuses tokens. Expect about 90 minutes if the downloads cooperate. Every step lists the output you should see, so you can stop at the first mismatch instead of debugging five layers at once.

Don't miss new tech stories on Google

Add Shattered once in the Google app and our stories show up in your news suggestions.

How an L402 Paywall Works on the Lightning Network

L402 turns a Lightning payment into an API key. A client asks for a resource with no credentials, the server replies with HTTP 402 Payment Required, and the reply carries two things in a WWW-Authenticate header: a token and a Lightning invoice. The token commits to the invoice through its payment hash. The client pays, receives the payment preimage as proof, and retries the request with the token and the preimage together. Only that pair is valid, which means nobody can forge access without paying.

The official L402 documentation describes the token format as a macaroon, a bearer credential that can carry permissions and can be attenuated and delegated by whoever holds it. Verification needs only a root key and basic cryptography, so the server does not look up a payment record to authorize a call. Lightning Labs formalized the protocol as bLIP-0026 and said on March 11, 2026 that L402 was production-ready. The company also said Lightning Loop has used L402 through Aperture since its first release, roughly five years earlier.

Aperture is the piece that does the work. Lightning Labs describes it in its builder documentation as “a reverse proxy that acts as a payment and authentication gateway for Lightning Network powered APIs.” Your backend never touches Lightning. Aperture mints the macaroons, asks LND for invoices, checks credentials, and forwards good requests to your service. A write-up of the pi402 launch summarizes the same loop: an unpaid request gets a 402, an incomplete credential, and an invoice, and paying reveals the preimage that completes the credential.

Compare that with a classic API key. There is no signup form, no billing portal, no card on file, and no chargeback. A script with a funded wallet can buy access to a service it has never seen, which is why Lightning Labs keeps pairing L402 with agent tooling. The same property makes the paywall useful for plain human developers who want to sell a data feed by the request without building an account system.

One naming wrinkle trips people up. Older posts and some Aperture log lines use LSAT, the protocol’s earlier name. Treat LSAT and L402 as the same thing in historical material, and write L402 in anything you build today. Header parsing in Step 8 accepts the current name only, which matches what Aperture v0.6.0 documents.

Prerequisites and Version Check

Pin versions before you type a command, because Lightning guides age fast. LND is still labeled beta, and its repository’s releases page listed v0.21.8-beta as the latest release as of November 14, 2026. Anything that tells you to run v0.21.6-beta or earlier predates the newer releases. For Bitcoin Core, check the version against its own release page instead of trusting a guide.

You need a shell and free local ports for the backend, both Lightning nodes, and Aperture. If a port is taken, change it in the script and in the YAML in the same edit. Two ports collide most often: Aperture documents 8081 as its default, and many dev boxes already run something on 8080.

Install Bitcoin Core 32.1 from the official release page, and verify the checksum and signatures as the release notes describe. Do the same for the LND v0.21.8-beta tarball for your platform, then copy lnd and lncli onto your PATH. Check both with their version flags before moving on. If you want a longer walkthrough of a production-style node, the guide to setting up a Lightning Network node covers Docker, backups, and monitoring in depth.

Expected output looks like the lines below. Your commit hashes and build tags will differ slightly, and that is fine as long as the version numbers match.

Lab only: the scripts start LND with the no-seed-backup flag so nobody has to write down a mnemonic for coins that have no value. That flag stores the wallet unencrypted. Never copy it to a mainnet node. Step 12 lists what changes when real money is involved.

Build the Regtest Lab: Steps 1 to 4

The lab needs a chain, two funded nodes, and a channel between them with liquidity on the right side. The buyer opens the channel, which gives the seller inbound capacity. That detail matters later, because a seller with zero inbound liquidity can mint invoices all day and never get paid.

Step 1: Create the Lab Folder and Shell Helpers

Put every path and helper function in one file so each later command stays short. Shell functions work in scripts, which aliases do not, so the helpers below are functions.

The last command should print alice is a function followed by its body. If your shell reports not found, the file did not load, so source it again from the lab directory.

Step 2: Start Bitcoin Core 32.1 in Regtest and Mine Coins

LND talks to Bitcoin Core over RPC for blocks and over ZeroMQ for fast notifications, so both ZMQ endpoints must be set when bitcoind starts. The transaction index is optional for LND but harmless here. Creating a wallet named miner and mining 101 blocks matures the first coinbase reward, because regtest coinbase outputs need 100 confirmations before they can be spent.

Step 3: Start Two LND Nodes Named Alice and Bob

Alice sells, Bob buys. Each node gets its own directory, peer port, gRPC port, and REST port. Keep 8081 free for Aperture, since that is its documented default, and give each node’s REST port a different value. For a deeper look at the flags a long-running node needs, the Bitcoin Lightning node setup guide explains each one.

If getinfo complains that the macaroon file does not exist, LND is still creating the wallet. Wait ten seconds and run it again. If synced_to_chain stays false for more than a minute, read the log at $LAB/alice.log and check the ZMQ ports first.

Step 4: Fund Bob and Open a Channel to Alice

Send one regtest bitcoin to Bob’s on-chain wallet, confirm it, connect the peers, and open a channel of 1,000,000 sats. All of Bob’s balance starts on his side of the channel. Once the channel is active, Bob can pay Alice up to the channel’s capacity minus reserves, and Alice has the same amount as inbound liquidity. Channel liquidity is the main operating cost on mainnet too, and techniques such as channel splicing let you resize a channel without closing it.

Your local_balance will differ by a few thousand sats because the channel reserves part of the capacity for commitment fees. What matters is active: true. If it prints false, mine six more blocks and ask again. The lab now has everything a real Lightning seller and buyer would have, minus the real money.

Install and Configure Aperture: Steps 5 to 7

With the Lightning side running, the seller needs a gateway and something worth selling. Aperture builds from source with the Go toolchain, reads one YAML file, and talks to Alice’s LND over gRPC to create invoices.

Step 5: Build Aperture v0.6.0 From Source

The official install instructions are three commands: clone the repository, enter it, and run make install. Check out the v0.6.0 tag first so you build the release and not whatever sits on the main branch today. The docs list Go 1.19 or later as the floor, but read go.mod in the tag you check out and use a Go release at least that new.

The commit hash in your output will not match the sample. If which aperture prints nothing, $(go env GOPATH)/bin is not on your PATH. The env file from Step 1 adds it, so source that file again in the same shell.

Step 6: Write aperture.yaml

Aperture looks for its configuration at ~/.aperture/aperture.yaml. The structure below follows the sample in the official step-by-step guide: a listen address, an authenticator block that points at Alice’s LND, a database backend, and a list of services. Use absolute paths everywhere. YAML does not expand a tilde or $HOME, and a path that looks right but does not resolve is the most common reason Aperture fails on its first start. Replace YOU with your username.

Each key earns its place. The authenticator block tells Aperture which LND node mints the invoices, so Alice’s TLS certificate and macaroon directory must be real. The hostregexp matches the Host header, which is why the test URLs in this lab say localhost and not 127.0.0.1. The pathregexp decides which paths belong to this service. The address is your backend. The price is in sats, and the official docs note that a valid token for a service unlocks unlimited resources on that service. The authwhitelistpaths list carves out a free tier.

Step 7: Start the Backend and Aperture, Then See the 402

Create a tiny backend with one paid file and one free file, bind it to localhost only, and start Aperture in a second terminal. Binding the backend to 127.0.0.1 matters more than it looks. If the backend listens on all interfaces, anyone who finds port 8000 walks around the paywall.

Aperture generates a self-signed TLS key and certificate on first run, per its install guide, so use https and tell curl to accept the certificate with -k. Production deployments need a valid certificate for your domain. Now send an unauthenticated request in a third terminal.

That reply is the whole product. The invoice prefix lnbcrt250n means regtest and 250 nanobitcoin, which equals 25 sats, exactly the price in the YAML. If you request /service/free/status.json instead, you should get a plain 200 with the free JSON body, because the whitelist pattern matches it.

Pay the Invoice and Fetch the Data: Steps 8 and 9

A payment by hand teaches the protocol faster than any diagram. Do it once manually, then let a script do it every time after.

Step 8: Pay by Hand and Replay With the L402 Header

Pull the macaroon and invoice out of the header, pay the invoice from Bob, read the preimage from his payment history, and retry with Authorization: L402 macaroon:preimage. Two details deserve care. HTTP/2 lowercases header names, so match case-insensitively. Aperture v0.6.0 can advertise both L402 and MPP, which means the response may carry more than one WWW-Authenticate line, so filter for the one that starts with L402.

Repeat only the last curl and you get the data again with no second payment. The token already proves the preimage. Change a single character of the preimage and the request goes back to a 402, which confirms the gateway verifies the pair and not just the presence of a header.

Step 9: Write a Python Client That Pays Within a Budget

A script that pays any invoice a server sends is a wallet-draining bug waiting to happen. The client below decodes the invoice first, refuses anything above a spending cap, pays through Bob, checks that the SHA-256 of the preimage equals the invoice’s payment hash, and caches the token for later calls. It shells out to lncli so it needs no extra dependencies.

Save it as l402_client.py in the lab folder. Run it twice against the paid path. The first run pays 25 sats and prints the JSON. The second run finds the cached token and prints the JSON with no payment line.

Now test the spending cap. Delete tokens.json and rerun the client with MAX_SATS=10 in front of it. The script prints refusing to pay 25 sats, cap is 10 and exits with a non-zero code before any payment leaves Bob’s node, which is the behavior you want from an unattended agent. The token cache is keyed by host and first path segment, so one payment covers every file under /service, matching the way Aperture treats a valid token as access to the whole service.

Pricing, Free Routes, and a Test Script: Steps 10 and 11

Step 10: Choose a Pricing Model

A fixed price per service is the simplest model and the one the lab uses. Aperture offers more. The pricing guide documents a dynamicprice block that points at a gRPC price server, and Aperture v0.6.0 added opt-in metered pricing, where one payment buys a usage bundle that real traffic then draws down. A static price of 0 does not make an endpoint free. The v0.6.0 notes say it falls back to a default of 1 sat, and a genuinely free endpoint uses auth: "off" or a whitelist path.

To try a second price tier, add another entry under services with its own name, pathregexp, and price. Aperture matches a request to a service by host and path, so give each pattern a distinct prefix such as /premium. Restart Aperture after every YAML edit, because it reads the file once at startup.

Step 11: Automate the Check With a Test Script

A paywall that silently stops charging is worse than one that is down. The script below asserts four behaviors: unpaid requests get a 402, the free path stays open, the first paid call costs exactly one payment, and the second call costs none. Run it after every config change.

Harden the Seller for Mainnet: Step 12

Step 12: Replace Every Lab Shortcut

The lab made four shortcuts on purpose. Each one needs a real replacement before a customer pays you a satoshi. First, drop --noseedbackup, create the wallet with a seed and a password, and write the mnemonic down offline. Second, replace the self-signed certificate with a valid one for your domain and serve Aperture on 443. Third, move the macaroon directory out of reach. Aperture needs only enough authority to create and look up invoices, so point it at a baked macaroon with those permissions instead of the admin file. Fourth, firewall the backend so only Aperture can reach it.

Patch discipline matters more on a node that holds channel funds. LND’s v0.21.6-beta release on October 30, 2026 disabled MPTCP listeners by default after an exploit path linked to CVE-2026-98432 was demonstrated. The release notes call that a mitigation and not a substitute for a Linux kernel carrying the upstream fix, so patch the kernel too. Earlier in the year, a Lightning Labs advisory dated August 11, 2026 described an HTLC sweep failure tied to a wallet budget constraint, fixed in v0.19.0-beta. Run the newest release, v0.21.8-beta at the time of writing, and treat any older number in a guide as a warning sign.

A repository change requiring TLS 1.2 as Aperture’s minimum version was visible on GitHub in early November 2026, though it had not been confirmed as part of a release by November 15. Put Aperture behind a reverse proxy or load balancer that enforces modern TLS regardless. For a repeatable routine that checks your node against current advisories, the Lightning Network upgrade audit turns patch checks into a script.

  • Create the mainnet wallet with a seed and password, and back up the channel state file after every channel change.
  • Use an Aperture-specific macaroon with invoice permissions only, never admin.macaroon.
  • Serve Aperture on 443 with a certificate for your domain, and keep the backend on a private interface.
  • Open a channel from your side only after you understand inbound liquidity, since buyers pay you through inbound capacity.
  • Set a price that clears routing fees. A 1-sat price can lose money on a long route.
  • Log every 402 and every paid request so you can reconcile invoices against traffic.

Advanced Tips: Metering, MPP, and Wavelength-Backed Sellers

Aperture v0.6.0 changes what a seller can do. Lightning Labs said it adds MPP support alongside L402, so a service can advertise both and let the buyer pick the protocol it speaks. It also adds real-time per-request accounting and an embedded meterd price server that quotes bundles and deducts token usage. A client buys credit once, each response debits it, and a new 402 arrives when the balance runs out. Fixed-price paywalls charge for access. Metered ones charge for consumption.

The biggest structural change is that a seller no longer needs LND. Per the release description, Aperture v0.6.0 can connect directly to a Wavelength wallet, so a seller can issue invoices without running a node, managing channels, or sourcing inbound liquidity. An EL7 report on the launch repeats that point. The setting is called wavelengthgateway, and you should read the v0.6.0 release notes for its exact syntax before using it, since this lab does not exercise it.

Those Wavelength limits and fees come from the October 23, 2026 mainnet announcement, and a CoinMarketCap Academy piece restates the 0.25% figure. Price your service with that fee in mind. A tiny per-request price on a small account can shrink faster than the headline percentage suggests once routing fees land on top.

On the buyer side, Lightning Labs’ Lightning Agent Tools, released February 11, 2026, include lnget, an L402-aware command-line client for paying gated APIs. For coding agents, pi402 ships as the @lightninglabs/pi-402 package installed through the Pi harness. Your Python client in Step 9 is the same idea as a short script, and it works against any L402 server.

What a Request Costs: Sats, Millisats, and Token Math

Prices in Aperture’s YAML are whole sats, but inference-style metering works in millisatoshis, and mixing the two causes the most expensive mistakes. One sat equals 1,000 msat. The pi402 announcement gave an example rate of 1 msat per input token and 2 msat per output token. Lightning Labs framed it as an illustration and not a published price, and it estimated roughly $0.80 per million input tokens and $1.61 per million output tokens at the exchange rate it cited.

The table applies the announcement’s example rates, so treat it as arithmetic and not a quote from any live service. It shows why metering matters. A flat 25-sat price would overcharge the small prompt by more than ten times and undercharge the long summary. Metered bundles let one payment cover many calls, which also cuts the number of Lightning payments you route. Fewer payments mean fewer chances to hit a failed route.

Fees and liquidity set the floor on what you can sell. Every payment needs a path with enough capacity, and a seller who only receives needs inbound liquidity from peers. Plan for it the way a shop plans for a card terminal. For the broader map of Bitcoin tools that sit around Lightning, from cold storage to mining, the cryptocurrency section collects the related guides.

Common Pitfalls When Selling an API Over Lightning

Most failures in a first L402 build come from a short list of mistakes. Each one below has burned someone who thought the setup was finished.

  • Binding the backend to all interfaces. If the Python server listens on 0.0.0.0, a visitor who finds port 8000 skips Aperture and reads your paid data for free. Bind to 127.0.0.1 or firewall the port.
  • Using tilde or $HOME in the YAML. Aperture reads paths literally. A tlspath of ~/l402-lab/alice/tls.cert fails at startup with a file-not-found error that looks like an LND problem.
  • Forgetting inbound liquidity. A seller node with channels where all the balance sits on its own side can create invoices that nobody can pay. In the lab, Bob opens the channel to Alice for exactly this reason.
  • Setting price to 0 and expecting free access. The v0.6.0 notes say a static price of 0 defaults to 1 sat. Use auth: "off" or a whitelist path for free routes.
  • Parsing only the first WWW-Authenticate header. With L402 and MPP both advertised, the first line may not be the one your client understands. Select the line that starts with L402.
  • Paying without a cap. A client that pays any invoice a server returns will drain its wallet on a hostile or buggy endpoint. Decode first, compare to a limit, and verify the preimage hash.
  • Confusing sats and msat. Aperture prices are in sats. Inference metering examples use millisatoshis. A factor of 1,000 hides in that gap.
  • Copying version numbers from old guides. A tutorial that pins LND v0.20.x or Aperture before v0.6.0 misses the MPTCP mitigation, metering, and the Wavelength option.
  • Shipping the no-seed-backup flag. It exists for regtest. On mainnet it leaves an unencrypted wallet on disk with no recovery phrase.

Notice how many of these are configuration slips and not protocol bugs. The L402 handshake itself is small. The surrounding plumbing, from ports to paths to liquidity, is where the hours go.

Troubleshooting: 12 Failures and Fixes

Work from the bottom of the stack up. Confirm Bitcoin Core, then each LND node, then the channel, then Aperture, then the client. The table maps common symptoms to the layer that usually causes them.

When nothing above matches, raise the log level. Aperture already runs with debuglevel: "debug" in the lab, and LND writes to $LAB/alice.log. Read the first error and ignore the cascade after it. A failed invoice creation on Alice’s node usually shows up in Aperture’s log within the same second as the request.

Complete Working Project: One Script to Build the Whole Lab

The pieces so far fit together as one folder. Keep the files below in ~/l402-lab, and the lab rebuilds from nothing in a few minutes.

The start script below repeats Steps 2 to 4 with waits in place of sleeps, so it is safe to rerun from a clean folder. It also writes the two backend files from Step 7. Start the backend and Aperture yourself afterwards, in their own terminals.

Run order for a fresh session: ./start-lab.sh, then the backend in terminal 1, aperture in terminal 2, and ./test.sh in terminal 3. A passing run ends with the single PASS line from Step 11. To start over, run ./stop-lab.sh, delete ~/l402-lab/bitcoin, alice, and bob, remove tokens.json, and run the start script again.

Frequently Asked Questions

What is an L402 paywall? It is an API gate that charges per access with a Lightning payment. The server answers an unpaid request with HTTP 402, a macaroon token, and an invoice. After the client pays, the preimage plus the token acts as the credential for later requests.

Is L402 the same as LSAT? L402 is the current name for the protocol that earlier material called LSAT. Lightning Labs describes L402 as production-ready as of March 11, 2026 and identifies it as bLIP-0026.

Do I still need an LND node to sell with Aperture? Not always. Aperture v0.6.0 can create invoices through a Wavelength wallet, so a seller can skip running a node, managing channels, and sourcing inbound liquidity. An LND-backed setup, like the one in this lab, remains the path when you want to run your own infrastructure.

Which LND and Bitcoin Core versions should I run? At the time of writing, the LND repository lists v0.21.8-beta as the latest release as of November 14, 2026, and it is still labeled beta. For Bitcoin Core, use the current release listed on its official release page.

Can I test everything without real bitcoin? Yes. Regtest gives you a private chain where you mine your own blocks, and this lab uses it for every step. Moving to mainnet means a real seed, real channels, real inbound liquidity, a valid TLS certificate, and an Aperture-specific macaroon.

How much can I charge per request? Aperture prices are set in sats, and the lab uses 25. Anything below the routing cost can lose money, so test paths to your node before you pick a price. Metered pricing in v0.6.0 uses finer units and bills actual usage, which suits token-based services.

What does the client need to pay an L402 invoice? Any wallet that can pay a BOLT 11 invoice and expose the preimage. The lab uses lncli through a Python script. Lightning Labs also released lnget in its Agent Tools on February 11, 2026, as an L402-aware command-line client.

Dr. Elena Marchetti writes about cryptography and the math that underpins it: hash functions, collision attacks, and why algorithms age out of trust. She has a research background in applied cryptography and tests a claim before explaining it.