Skip to content

Commit b294261

Browse files
committed
Just BRC-29 for http
Signed-off-by: Deggen <d.kellenschwiler@bsvassociation.org>
1 parent 457f9d6 commit b294261

4 files changed

Lines changed: 125 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ BRC | Standard
167167
118 | [Multipart Body Transport for BRC-105 Payments](./payments/0118.md)
168168
119 | [SubTree Unified Merkle Path (STUMP) Format](./transactions/0119.md)
169169
120 | [x402 Stateless Settlement-Gated HTTP Protocol](./payments/0120.md)
170+
121 | [HTTP 402 Payment Protocol for Content Monetization](./payments/0121.md)
170171

171172
## License
172173

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
* [HTTP Service Monetization Framework](./payments/0105.md)
110110
* [Multipart Body Transport for BRC-105 Payments](./payments/0118.md)
111111
* [x402 Stateless Settlement-Gated HTTP Protocol](./payments/0120.md)
112+
* [HTTP 402 Payment Protocol for Content Monetization](./payments/0121.md)
112113

113114
## Peer-to-Peer
114115

payments/0121.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# BRC-121: HTTP 402 Payment Protocol for Content Monetization
2+
3+
Deggen (sirdeggen@gmail.com)
4+
5+
## Abstract
6+
7+
This BRC specifies a lightweight protocol for monetizing HTTP resources using the `402 Payment Required` status code and a set of custom HTTP headers. A server advertises a price and its identity key in the 402 response. A client constructs a [BRC-29](./0029.md) payment transaction, encodes it in [BRC-95 BEEF](../transactions/0095.md) format, and retransmits the original request with payment headers. The server validates the transaction, internalizes the payment via its wallet, and serves the protected resource. The protocol is stateless from the server's perspective: each request is independently authorized by the presence or absence of valid payment headers.
8+
9+
## Motivation
10+
11+
HTTP 402 was reserved in the original HTTP/1.1 specification (RFC 7231) for future use in micropayment schemes, but no standard mechanism was adopted. Meanwhile, BSV transaction fees are low enough to make per-request payments practical for content such as articles, API calls, and media.
12+
13+
Existing BSV payment protocols ([BRC-27](./0027.md) Direct Payment Protocol, [BRC-105](./0105.md) HTTP Service Monetization Framework, [BRC-120](./0120.md) x402) each define comprehensive negotiation mechanisms. This BRC targets a simpler use case: a client that already holds a [BRC-42](../key-derivation/0042.md)-compatible wallet pays for an HTTP resource in a single round-trip pair (one 402 response, one paid request) using only standard HTTP headers and [BRC-29](./0029.md) payment remittance.
14+
15+
Design goals:
16+
17+
1. **Minimal surface area** -- no JSON body negotiation, no challenge tokens, no session state.
18+
2. **BRC-29 compatible** -- payment derivation uses the same protocol ID (`2-3241645161d8`), derivation prefix, and derivation suffix scheme defined in [BRC-29](./0029.md).
19+
3. **BEEF transport** -- the payment transaction is transmitted as a base64-encoded [BRC-95 BEEF](../transactions/0095.md) blob in a single header, carrying full SPV ancestry.
20+
4. **Stateless verification** -- the server validates and internalizes the payment on each request independently. Caching of paid status is a client-side optimization, not a protocol requirement.
21+
22+
## Specification
23+
24+
### 1. Header Namespace
25+
26+
All protocol headers use the prefix `x-bsv-`. The following headers are defined:
27+
28+
| Header | Direction | Description |
29+
|---|---|---|
30+
| `x-bsv-sats` | Server to client | Required satoshi amount for the resource. |
31+
| `x-bsv-server` | Server to client | Server's compressed, hex-encoded secp256k1 identity public key. |
32+
| `x-bsv-beef` | Client to server | Base64-encoded [BRC-95 BEEF](../transactions/0095.md) transaction containing the payment. |
33+
| `x-bsv-sender` | Client to server | Client's compressed, hex-encoded secp256k1 identity public key. |
34+
| `x-bsv-prefix` | Client to server | Base64-encoded [BRC-29](./0029.md) derivation prefix for the payment. |
35+
| `x-bsv-suffix` | Client to server | Base64-encoded [BRC-29](./0029.md) derivation suffix for the payment output. |
36+
| `x-bsv-vout` | Client to server | Output index (zero-based, decimal string) of the payment output within the transaction. |
37+
38+
### 2. Server: 402 Response
39+
40+
When a client requests a protected resource without payment headers, the server MUST respond with:
41+
42+
- HTTP status `402 Payment Required`
43+
- Header `x-bsv-sats` set to the required price in satoshis
44+
- Header `x-bsv-server` set to the server's identity public key
45+
- An empty body (the server MUST NOT serve the protected content)
46+
47+
The server SHOULD also set appropriate CORS headers to expose `x-bsv-sats` and `x-bsv-server` to browser-based clients:
48+
49+
```
50+
Access-Control-Expose-Headers: x-bsv-sats, x-bsv-server
51+
```
52+
53+
### 3. Client: Payment Construction
54+
55+
Upon receiving a 402 response, the client:
56+
57+
1. Reads `x-bsv-sats` to determine the required payment amount.
58+
2. Reads `x-bsv-server` to obtain the server's identity key (the payment recipient).
59+
3. Generates a derivation prefix and derivation suffix as specified in [BRC-29](./0029.md).
60+
4. Uses [BRC-42](../key-derivation/0042.md) key derivation with the invoice number format `2-3241645161d8-<prefix> <suffix>` to derive the recipient's public key.
61+
5. Constructs a BSV transaction with a P2PKH output of the required satoshi amount locked to the derived public key.
62+
6. Serializes the transaction in [BRC-95 BEEF](../transactions/0095.md) format and encodes it as base64.
63+
64+
### 4. Client: Paid Request
65+
66+
The client retransmits the original HTTP request with the following headers added:
67+
68+
| Header | Value |
69+
|---|---|
70+
| `x-bsv-beef` | Base64-encoded BEEF transaction |
71+
| `x-bsv-sender` | Client's identity public key (hex) |
72+
| `x-bsv-prefix` | Base64-encoded derivation prefix |
73+
| `x-bsv-suffix` | Base64-encoded derivation suffix |
74+
| `x-bsv-vout` | Output index of the payment output (decimal string) |
75+
76+
The request method, URL, and any other headers or body MUST be identical to the original request.
77+
78+
### 5. Server: Payment Validation
79+
80+
Upon receiving a request with payment headers, the server MUST:
81+
82+
1. Verify that all five client headers (`x-bsv-beef`, `x-bsv-sender`, `x-bsv-prefix`, `x-bsv-suffix`, `x-bsv-vout`) are present. If any are missing, respond with 402.
83+
2. Decode the BEEF transaction from base64.
84+
3. Internalize the payment using the wallet's `internalizeAction` operation with:
85+
- The decoded transaction bytes
86+
- Protocol: `wallet payment`
87+
- Payment remittance containing `derivationPrefix`, `derivationSuffix`, and `senderIdentityKey` from the provided headers
88+
- Output index from `x-bsv-vout`
89+
4. If internalization succeeds, serve the protected resource with HTTP status `200`.
90+
5. If internalization fails (invalid transaction, insufficient amount, invalid derivation, or SPV failure), respond with 402.
91+
92+
The server MUST NOT maintain per-client payment state. Each request is independently authorized.
93+
94+
### 6. Client: Caching (Optional)
95+
96+
A client MAY cache the set of URLs for which payment has been accepted and skip the 402 round-trip on subsequent requests to the same URL. This is a client-side optimization. The server makes no guarantees about how long a payment remains valid. A client SHOULD clear its payment cache when the user clears browsing history.
97+
98+
### 7. Error Handling
99+
100+
- If the server cannot initialize its wallet, it SHOULD return `500 Internal Server Error`.
101+
- If payment validation throws an exception, the server SHOULD return `402` to allow the client to retry.
102+
- A client that receives a `402` after submitting payment headers SHOULD NOT automatically retry without user confirmation to avoid double-spending.
103+
104+
## Implementations
105+
106+
1. **Server (Express/Node.js)** -- A reference implementation of the server-side middleware is available at [github.com/sirdeggen/article](https://github.com/sirdeggen/article). The middleware uses `@bsv/sdk` for BEEF parsing and `@bsv/wallet-toolbox` for payment internalization.
107+
108+
2. **Client (React Native WebView)** -- A reference client implementation intercepts 402 responses in a fetch wrapper, constructs payment headers using a [BRC-42](../key-derivation/0042.md)-compatible wallet, and retransmits the request. Source: [github.com/AnomalyCo/bsv-browser](https://github.com/AnomalyCo/bsv-browser).
109+
110+
3. **Wallet Compatibility** -- Any wallet implementing the `WalletInterface` from `@bsv/sdk` with support for `internalizeAction` and `getPublicKey({ identityKey: true })` can be used on either side of the protocol.
111+
112+
## References
113+
114+
- [BRC-29: Simple Authenticated BSV P2PKH Payment Protocol](./0029.md)
115+
- [BRC-42: Key Derivation Scheme](../key-derivation/0042.md)
116+
- [BRC-43: Security Levels and Protocol IDs](../key-derivation/0043.md)
117+
- [BRC-95: BEEF Transaction Format](../transactions/0095.md)
118+
- [BRC-105: HTTP Service Monetization Framework](./0105.md)
119+
- [BRC-120: x402 Stateless Settlement-Gated HTTP Protocol](./0120.md)
120+
- RFC 7231 Section 6.5.2: 402 Payment Required
121+
- Reference server implementation: https://github.com/sirdeggen/article
122+
- Reference client implementation: https://github.com/AnomalyCo/bsv-browser

payments/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ BRC | Standard
1414
105 | [HTTP Service Monetization Framework](./0105.md)
1515
118 | [Multipart Body Transport for BRC-105 Payments](./0118.md)
1616
120 | [x402 Stateless Settlement-Gated HTTP Protocol](./0120.md)
17+
121 | [HTTP 402 Payment Protocol for Content Monetization](./0121.md)

0 commit comments

Comments
 (0)