Menu

Explorer & Settings

Tempo Explorer Submit Project
Back to all projects

l402-go

by joelklabo · Updated 5 months ago

Go client library for L402 (HTTP 402 Payment Required with Lightning Network) - pay-per-request APIs

Open source alternative to:

In the AI payments ecosystem

l402-go is an early-stage Go project in the AI payments / x402 ecosystem, focused on api, bitcoin, go, golang. It currently has 0 GitHub stars and 0 forks, and sits alongside related tools like l402-js, routeweiler-python-sdk, lightning-wallet-mcp, boltzpay, squidbay, toll-booth.

README.md View on GitHub →

l402-go

A Go client library for L402 (HTTP 402 Payment Required with Lightning).

What is L402?

L402 is a payment protocol that enables pay-per-request APIs using Lightning Network:

  1. Client makes HTTP request to an L402 endpoint
  2. Server responds with 402 status + Lightning invoice
  3. Client pays invoice via Lightning
  4. Client retries request with payment proof
  5. Server validates payment and returns response

Installation

go get github.com/joelklabo/l402-go

Quick Start

Basic Usage (Manual Payment)

package main

import (
    "context"
    "fmt"
    "net/http"
    
    "github.com/joelklabo/l402-go"
)

func main() {
    // Make initial request
    resp, err := http.Get("https://example.com/api/paid-endpoint")
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    // Parse 402 challenge
    body, _ := io.ReadAll(resp.Body)
    challenge, err := l402.ParseChallenge(resp.StatusCode, resp.Header, body)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("Pay %d sats to: %s\n", challenge.AmountSats, challenge.Invoice)
    fmt.Printf("Payment hash: %s\n", challenge.PaymentHash)
    
    // Pay the invoice (using your Lightning wallet)
    // ... your payment logic here ...
    
    // Retry with payment proof
    req, _ := http.NewRequest("GET", "https://example.com/api/paid-endpoint", nil)
    req.Header.Set("X-Payment-Hash", challenge.PaymentHash)
    
    resp, err = http.DefaultClient.Do(req)
    // ... handle response
}

Auto-Pay with Wallet

package main

import (
    "context"
    "fmt"
    "net/http"
    
    "github.com/joelklabo/l402-go"
    "github.com/joelklabo/l402-go/wallet"
)

func main() {
    ctx := context.Background()
    
    // Create a wallet (implement the Wallet interface)
    w := wallet.NewLNbits("https://lnbits.example.com", "your-api-key")
    
    // Configure auto-pay options
    opt := l402.Options{
        AutoPay:       true,
        MaxSats:       1000,  // Maximum sats per request
        RetryBackoff:  []time.Duration{0, 250*time.Millisecond, 1*time.Second},
    }
    
    // Make request with auto-pay
    result, err := l402.Fetch(ctx, http.DefaultClient, w, func() (*http.Request, error) {
        return http.NewRequest("GET", "https://example.com/api/paid-endpoint", nil)
    }, opt)
    
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("Status: %d\n", result.Status)
    fmt.Printf("Paid: %v\n", result.Paid)
    fmt.Printf("Body: %s\n", result.Body)
}

API

ParseChallenge(status int, headers http.Header, body []byte) (*Challenge, error)

Parses an L402 payment challenge from a 402 response.

Fetch(ctx context.Context, client *http.Client, w Wallet, makeReq func() (*http.Request, error), opt Options) (*Result, error)

Executes a request with optional auto-pay support.

Types

type Challenge struct {
    Invoice     string  // BOLT11 Lightning invoice
    PaymentHash string  // Payment hash for proof
    AmountSats  int64   // Amount in satoshis
    Message     string  // Human-readable message
}

type Options struct {
    AutoPay           bool            // Enable automatic payment
    MaxSats           int64           // Maximum sats to auto-pay
    AllowUnknownAmount bool           // Allow payment when amount is unknown
    RetryBackoff      []time.Duration // Retry delays after payment
}

type Result struct {
    Status    int
    Headers   http.Header
    Body      []byte
    Challenge *Challenge
    Paid      bool
}

Wallet Interface

Implement the Wallet interface to use auto-pay:

type Wallet interface {
    PayInvoice(ctx context.Context, invoice string) (preimage string, err error)
}

Examples

Live Endpoints

Test against these live L402 endpoints:

  • WoT Scoring API: https://wot.klabo.world/score?pubkey=...
  • MaximumSats DVM: https://maximumsats.com/api/dvm

Both offer a free tier, then charge sats per request.

License

MIT

All L402 projects →