<>ts-stack
Get StartedArchitecturePackagesSpecsGuides
⌘K
Reference
Home
Get StartedOverviewInstallChoose your stackKey concepts
ArchitectureOverviewStack layersBEEF (BRC-62)BRC-100 Wallet InterfaceIdentity & AuthConformance pipeline
PackagesOverviewSDKWalletNetworkOverlaysMessagingMiddlewareHelpers
InfrastructureOverviewmessage-box-serveroverlay-serveruhrp-server-basicuhrp-server-cloud-bucketwabwallet-infrachaintracks-server
SpecsOverviewBRC-100 Wallet InterfaceOverlay HTTPMessage-box HTTPAuthsocket (WebSocket)BRC-31 Auth HandshakeBRC-29 Peer PaymentBRC-121 / HTTP 402ARC BroadcastMerkle ServiceStorage AdapterGASP SyncUHRPAir-Gap Optical (BRC-141)
ConformanceOverviewVector catalogTS runnerContributing vectors
GuidesOverviewBuild a wallet-aware appRun an overlay nodePeer-to-peer messagingHTTP 402 payments
ReferenceOverviewBRC indexRepository health
AboutVersioningContributingDoc agentDocumentation sources
Loading…
Edit this page on GitHub
© 2026 BSV Blockchain. ts-stack is open-source.
GitHubContributingVersioning

BRC-121 HTTP 402 Payment Required

BRC-121 monetizes HTTP API endpoints with a single-round-trip payment flow: client requests a resource, server responds with 402 and payment instructions (a nonce), client derives a payment address, constructs a BSV transaction, and re-sends the original request with payment headers. Server validates and serves the resource (or rejects with another 402).

At a glance

FieldValue
FormatOpenAPI 3.1
Version1.0.0
Statusstable
Implementation@bsv/402-pay

What problem this solves

Monetize APIs without subscriptions or token systems. Traditional APIs require accounts, credit cards, or API keys. BRC-121 enables instant monetization: each request is micro-paid in satoshis. No signup, no account needed—just pay per request and immediate access.

Request-bound payment derivation. The client supplies a fresh nonce and timestamp that participate in payment-key derivation. Those values bind the payment proof, but they are not a replay database by themselves. The server must also validate freshness and request fields, and the wallet must not newly accept the same transaction twice.

No authentication session required. Requests do not require BRC-103/104 mutual-auth state. Wallet transaction state and any application cache/replay policy are still stateful security dependencies.

Protocol overview

Single round-trip with payment:

  1. Client → Server GET /protected-resource (no payment headers)

    • Server checks if resource is free (price = 0) → serve it
    • Otherwise, server sends 402 Payment Required
  2. Server → Client HTTP 402 response

    • x-bsv-server: <serverPublicKey> — Server's identity key
    • x-bsv-sats: <amount> — Satoshis required
  3. Client (constructs payment)

    • Generates a fresh random nonce and millisecond timestamp
    • Calls wallet.createAction() with one P2PKH output
    • Derives address using key ID <nonce> <base64(timestamp)>
    • Uses BRC-42 to derive (pubKeyA, pubKeyB) from sender+server keys
    • Locks the output to the derived server payment key
    • Signs and constructs Atomic BEEF (BRC-95)
  4. Client → Server same request with payment headers

    • x-bsv-beef: <beefBase64> — Atomic BEEF transaction
    • x-bsv-sender: <clientPublicKey> — Sender's identity key
    • x-bsv-nonce: <nonce> — Client-generated derivation prefix
    • x-bsv-time: <timestamp> — Unix millisecond timestamp
    • x-bsv-vout: <outputIndex> — Which output contains the payment
  5. Server (validates & serves)

    • Calls wallet.internalizeAction() with BEEF
    • If accepted === true → payment accepted, serve resource (HTTP 200)
    • If the transaction, nonce, amount, or output index is invalid → reject (HTTP 402)
    • If amount < required → reject (HTTP 402)

Key types / endpoints

MethodPathPurposeRequestResponse
GET/POST/etc./{resourcePath}First request (unpaid)(none)402 + x-bsv-sats, x-bsv-server
GET/POST/etc./{resourcePath}Second request with paymentx-bsv-beef, x-bsv-sender, x-bsv-nonce, x-bsv-time, x-bsv-vout200 + resource body, or 402 on failure

Example: Monetized Express endpoint

typescript
import express from 'express'
import { createPaymentMiddleware } from '@bsv/402-pay/server'
import { ServerWallet } from '@bsv/simple/server'

const wallet = await ServerWallet.create({
  privateKey: process.env.SERVER_PRIVATE_KEY!,
  network: 'main',
  storageUrl: 'https://store-us-1.bsvb.tech'
})
const app = express()

app.use(
  createPaymentMiddleware({
    wallet,
    calculatePrice: path => {
      // Pricing logic
      if (path === '/premium') return 500 // 500 sats
      if (path === '/free') return 0 // Free
      return 100 // Default 100 sats
    }
  })
)

// Protected endpoint
app.get('/premium', (req, res) => {
  // If we reach here, payment was accepted
  res.json({
    content: 'Premium article here',
    paidBy: req.payment.senderIdentityKey,
    amount: req.payment.satoshisPaid,
    txid: req.payment.txid
  })
})

app.listen(3000)

Client-side (using create402Fetch):

typescript
import { create402Fetch } from '@bsv/402-pay/client'
import { WalletClient } from '@bsv/sdk'

const wallet = new WalletClient()

// Fetch wrapper that auto-handles 402
const fetch402 = create402Fetch({ wallet })

const response = await fetch402('https://api.example.com/premium')
const data = await response.json()
console.log(data.content) // Automatic payment + resource retrieval

Conformance vectors

There is no standalone BRC-121 vector directory in the current conformance corpus. Related portable fixtures live in conformance/vectors/wallet/brc29/payment-derivation.json for payment derivation and conformance/vectors/wallet/brc100/ for wallet methods used by payment clients and servers.

Implementations in ts-stack

PackageNotes
@bsv/402-pay/serverServer-side middleware for independent 402 handling without BRC-31 auth
@bsv/402-pay/clientClient-side fetch wrapper that auto-detects 402 and constructs payment headers
@bsv/payment-express-middlewareRelated legacy authenticated JSON flow; not a BRC-121 implementation

Related specs

  • BRC-29 Peer Payment — Key derivation and payment format
  • BRC-42/43 — Key derivation for payment address
  • BRC-95 / BRC-62 — Atomic BEEF format
  • BRC-31 Auth — Often combined with 402 for dual auth + payment
  • BRC-100 Wallet — internalizeAction() for payment validation

Spec artifact

brc121.yaml