> For the complete documentation index, see [llms.txt](https://bsv.brc.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bsv.brc.dev/payments/0166.md).

# P2PKH Payments for HTTP 402

Andy Rowe (<andy@bsv.cx>)

> **Read alongside** [**x402-foundation/x402#2890**](https://github.com/x402-foundation/x402/pull/2890) (@sirdeggen), which specifies the BRC-29/BRC-42 addressing mode for `exact` on BSV and should land first. This document describes a **plain P2PKH addressing mode** - the one that PR names in its Facilitator Deployment appendix and places out of scope:
>
> > "supporting third-party facilitators without recipient wallets would require either a different addressing mode (e.g. plain P2PKH to a static address in `payTo`) or a key-linkage-proof flow - both out of scope for this spec."
>
> The two are complementary: this mode makes the *payment itself* publicly checkable on-chain against the challenge (Section 9.1), that one gives on-chain payee unlinkability. A stronger third-party-verifiable *receipt* - binding invoice->address->transaction without trusting the origin - is out of scope for the base scheme here; an origin MAY provide one as an optional extension (Section 9.1). **Network identifiers:** aligned to `bsv:mainnet` / `bsv:testnet` per #2890, now that [ChainAgnostic/namespaces#190](https://github.com/ChainAgnostic/namespaces/pull/190) merged (2026-08-18); the old `bip122` form cannot distinguish BSV from BTC and MUST NOT be emitted.

## 1. Abstract

This document specifies an **ecosystem-independent, publicly-verifiable profile for HTTP `402 Payment Required`** settlement on BSV, using **plain P2PKH payments to a per-invoice address**. Two properties distinguish it from the other BSV 402 specifications:

1. **No client wallet ecosystem is required.** A payer needs only the ability to construct, sign and hex-encode a BSV transaction paying a given address - *not* a BRC-100 wallet, BRC-42 key derivation, an identity key, or BEEF serialization. Any holder of BSV can pay, which is the entire reason this profile exists (Section 3).
2. **Settlement is verifiable by any third party from public chain data alone**, without trusting the origin's database, because a payment is keyed off the on-chain locking script rather than a private invoice record (Section 9.1). This is what lets a facilitator *other than the payee* confirm a payment - precisely the case the key-derived modes cannot serve without the payee's own wallet.

Concretely, the profile realizes the `exact` payment scheme of the [x402 Foundation](https://github.com/x402-foundation/x402) HTTP payment protocol (hereafter **x402-F**) as its wire format: a server advertises one or more `PaymentRequirements` objects, each naming a `scheme`, and a client selects one it can satisfy. x402-F's upstream schemes are built on delegated-pull primitives (EIP-3009-style signed authorizations executed later by a facilitator); Bitcoin has no such primitive, so this profile carries a **complete, signed transaction** in the payload and the origin server acts as its own facilitator - verifying the transaction locally and broadcasting it. The x402-F envelope is the realization, not the identity: the ecosystem-independent, self-verifying settlement model is the contribution.

## 2. Status Note - and an important name collision

**There are two unrelated protocols named "x402" in circulation, and this document is about the one that is&#x20;*****not*****&#x20;BRC-120.** Implementers who miss this will build the wrong thing, so it is stated before anything else:

|                  | **BRC-120**                                                                | **This document**                                   |
| ---------------- | -------------------------------------------------------------------------- | --------------------------------------------------- |
| Protocol         | x402: Stateless Settlement-Gated HTTP Protocol v1.0 (Merkle Works, frozen) | x402 Foundation x402, protocol version 2            |
| Origin           | BSV-native, specified in `merkleworks-x402-spec`                           | Cross-chain, originally EVM; `x402-foundation/x402` |
| Challenge header | `X402-Challenge`                                                           | `PAYMENT-REQUIRED`                                  |
| Proof header     | `X402-Proof`                                                               | `PAYMENT-SIGNATURE`                                 |
| Replay control   | nonce UTXO + RFC 8785 canonical JSON binding                               | per-invoice address + server-side invoice state     |
| Extension point  | none (frozen; conformance is all-or-nothing)                               | `scheme` - which is what this document defines      |

The two share a number and an idea, not a wire format. They are not interoperable and neither is a profile of the other. This document does not modify, extend, or claim conformance with BRC-120.

Relationship to the other BSV 402 specifications:

* [**BRC-105**](https://bsv.brc.dev/payments/0105.md) (HTTP Service Monetization Framework) monetizes an already-authenticated BRC-103/104 session. It is the right choice when the client and server have a mutual-auth relationship and certificate exchange. This binding has no session and no identity layer.
* [**BRC-121**](https://bsv.brc.dev/payments/0121.md) (Simple 402 Payments) is the nearest neighbour in spirit - deliberately minimal, single round-trip pair. It differs in requiring a BRC-42-compatible wallet on the client, BRC-29 derivation, BEEF with SPV ancestry, and an identity key per payer.
* [**BRC-27**](https://bsv.brc.dev/payments/0027.md) (Direct Payment Protocol) is not HTTP-status-driven.

**The distinguishing property of this binding is that the paying client is not required to run a BSV wallet-ecosystem stack** - no BRC-100 wallet, BRC-29/BRC-42 derivation, identity key, or BEEF. It needs only a key that controls some BSV and the ability to sign a raw transaction. That is the entire reason it exists; see Section 3. Everything it gives up relative to BRC-121 follows from that one choice, and those costs are stated in Section 9 rather than buried.

## 3. Motivation

The intended payer is an autonomous agent, a CI job, or a script - software whose HTTP stack is being taught **one** 402 grammar by its SDK vendor, and that grammar is increasingly x402-F. Such a client typically has:

* an HTTP client with middleware hooks,
* the ability to sign a transaction (or an API that will), and
* **no BSV wallet stack, no identity key, and no reason to acquire one.**

Requiring BRC-42 derivation and BEEF from that client is not a small ask; it is a request to adopt an ecosystem in order to spend ten satoshis. The observed consequence is that the payment does not happen.

To be precise about the floor: this profile does assume the payer can spend BSV - it must hold a key with enough funds to cover the invoice and be able to build and sign a P2PKH-spending transaction (a few lines with any general Bitcoin library). That is a wallet only in the minimal sense of key custody plus signing. What it is *not* is the BSV wallet ecosystem - no wallet application, identity key, BRC-29/BRC-42 derivation, or BEEF

* and shedding that ecosystem requirement is exactly what this profile buys.

Conversely, x402-F's existing schemes cannot be honestly implemented on Bitcoin. A UTXO payment *is* a complete signed transaction; there is nothing left for a third-party facilitator to "execute" afterwards. Advertising `scheme: "exact"` while shipping a raw transaction would be a false statement in the one field a client reads to decide **how to pay**. Naming the scheme for what it actually is preserves the protocol's own failure mode: an unrecognised scheme is one a client can cleanly decline.

Design goals:

1. **No client-side wallet standard.** Sign a transaction to an address; that is all.
2. **Unambiguous attribution.** A payment settles exactly one invoice, by construction.
3. **Single round trip on the paying request.** Payment travels with the retry.
4. **Honest field semantics.** No field claims more than the implementation delivers.

## 4. Terminology

* **Origin** - the HTTP server exposing the paid resource. Under this scheme the origin is also the facilitator: it verifies and broadcasts.
* **Payer** - the client. It holds no account with the origin and is not identified.
* **Invoice** - server-side record of one challenge: a resource, an amount, a unique receiving address, and an expiry. This scheme is pay-per-call and mints no reusable credential; a settled invoice is retained only for idempotent retries (Section 5.6).

The key words MUST, MUST NOT, SHOULD, SHOULD NOT, MAY and OPTIONAL are to be interpreted as described in RFC 2119 and RFC 8174.

## 5. Specification

### 5.1 Scheme identifier

```
scheme = "exact"
```

An origin implementing this document MUST advertise exactly this string in the `scheme` field of any `PaymentRequirements` object it offers for BSV settlement, and MUST reject a `PAYMENT-SIGNATURE` payload whose `accepted.scheme` is present and names a different scheme, rather than attempting to interpret it.

**Disambiguating two `exact` addressing modes on BSV.** The sibling specification [x402#2890](https://github.com/x402-foundation/x402/pull/2890) also advertises `scheme: "exact"` on `bsv:mainnet`, for a BRC-29/BRC-42 *derived-address* payload carried as BEEF. `scheme` and `network` therefore do **not**, by themselves, tell a payer which payload to construct - a client that guessed would build the wrong transaction. This profile is identified by an explicit **payload-format discriminator** in `extra` (Section 5.3): an origin offering this plain-P2PKH mode MUST set `extra.payloadFormat.kind` to `"p2pkh-rawtx"` and MUST include `extra.lockingScriptHex`, and MUST NOT carry the BRC-29/BRC-42 derivation fields that #2890 defines (e.g. `derivationPrefix`, `derivationSuffix`, a `senderIdentityKey`). A payer MUST select this profile only when it recognises `extra.payloadFormat.kind` as `"p2pkh-rawtx"` - or, for an origin predating this field, only when `extra.lockingScriptHex` is present and no BRC-29 derivation fields are - and MUST otherwise decline the offer exactly as it would an unknown `scheme`, rather than guessing the payload shape. An origin MUST NOT describe both addressing modes in a single `PaymentRequirements` object; to offer both it MUST emit two entries in the `accepts` array, one per mode, each self-identified by its discriminator.

> **Design note (non-normative): why BSV carries two `exact` modes.** In x402, `exact` names an *amount* semantic, and each network otherwise defines a single payload for `(exact, network)`. BSV is a deliberate exception: it supports both a wallet-ecosystem addressing mode (BRC-29/BRC-42 derivation, #2890) and a permissionless plain-P2PKH mode (this document), and the second exists precisely to serve payers who cannot adopt the first. The two are complementary, not competing. The clean convention for their coexistence is that **both** modes carry an explicit `extra.payloadFormat.kind`, so a payer dispatches on `(scheme, network, payloadFormat.kind)` and never guesses from a silent default. This document self-identifies as `"p2pkh-rawtx"`; the derived-address mode is encouraged to self-identify symmetrically (e.g. `"brc29-beef"`). A single umbrella scheme document for BSV `exact` MAY enumerate both modes and their discriminators.

### 5.2 Network identifier

```
network = "bsv:mainnet"    (mainnet)
network = "bsv:testnet"    (testnet)
```

These are the registered CAIP-2 `bsv:` namespace references ([ChainAgnostic/namespaces#190](https://github.com/ChainAgnostic/namespaces/pull/190), merged 2026-08-18), which name the network directly. The older `bip122:<genesis-hash>` bitcoin-family form does **not** distinguish the chain - **BSV shares its genesis block with BTC and BCH**, so a fork is invisible to it - and MUST NOT be emitted. #2890 reached the same conclusion; this document matches it. Readers MAY still accept a legacy `bip122:` value for backward compatibility.

Origins MUST therefore also set `asset` to `"BSV"` and `extra.chain` to `"bsv"`, and payers that care which chain they are spending on MUST read those fields rather than relying on `network` alone. Inventing a non-standard chain identifier was considered and rejected: no existing library would recognise it, and the ambiguity would still need documenting.

### 5.3 The 402 challenge

On an unpaid request to a protected resource, the origin MUST respond with status `402 Payment Required` and a `PAYMENT-REQUIRED` header whose value is `base64(JSON(PaymentRequired))`, per x402-F v2.

The `PaymentRequired` object MUST contain `x402Version: 2`, a `resource` descriptor, and an `accepts` array containing at least one `PaymentRequirements` object of the following shape:

```jsonc
{
  "scheme": "exact",
  "network": "bsv:mainnet",
  "amount": "10",              // satoshis, decimal string (x402-F requires a string)
  "asset": "BSV",
  "payTo": "1Dy8XGHcuyjsfSs2QpyEiP1w4cVNQaXHYn",
  "maxTimeoutSeconds": 900,
  "extra": {
    "chain": "bsv",
    "unit": "satoshi",
    "invoiceId": "6f036062ef5f91f526faf7da",
    "lockingScriptHex": "76a9148e3f1506db9e226b5850554953829d536299312588ac",
    "expiresAt": "2026-08-21T12:00:00.000Z",
    "perCallSats": 10,
    "payloadFormat": { "kind": "p2pkh-rawtx", "rawtx": "...", "note": "..." },
    "submitUrl": "https://bsv.cx/pay/6f036062ef5f91f526faf7da/submit"
  }
}
```

Normative requirements on `extra`:

* `invoiceId` (string) - REQUIRED. Opaque; identifies the invoice on settlement.
* `lockingScriptHex` (string) - REQUIRED. The **exact** P2PKH locking script the origin will match. Publishing the script, not merely the address, lets a payer construct the output that will be recognised byte-for-byte and removes address-encoding as a failure mode.
* `payloadFormat.kind` (string) - REQUIRED. MUST be `"p2pkh-rawtx"`. It identifies this plain-P2PKH raw-transaction addressing mode and is the discriminator that distinguishes this profile from the BRC-29/BRC-42 `exact` mode of #2890 (Section 5.1); a payer keys its choice of payload off this field. `payloadFormat` MAY carry additional advisory keys (e.g. a human-readable `note`), which a payer MUST ignore for mode selection.
* `expiresAt` (RFC 3339 string) - REQUIRED. After this instant the origin MUST refuse settlement of this invoice.
* `chain`, `unit` - REQUIRED, per Section 5.2.
* `perCallSats` (number) - OPTIONAL, informational: the price of the one call this invoice buys. Under this pay-per-call scheme it equals `amount`; it is emitted so a reader need not divide.
* `submitUrl` (string) - OPTIONAL. A URL to which a payer MAY POST the `PaymentPayload` (Section 5.5) as an alternative to retrying the original request with the `PAYMENT-SIGNATURE` header. Both settle the same invoice identically; a payer that ignores it loses nothing.

An origin MAY additionally carry the same offer in the response body and MAY emit a `WWW-Authenticate` challenge, for clients that do not read the header. Where both are present they MUST describe the same invoice.

### 5.4 `payTo` - per-invoice addresses

The origin MUST issue a **fresh receiving address for every invoice**, and MUST NOT reuse an address across invoices.

This is what makes attribution unambiguous without any identity layer: a transaction paying invoice *X*'s address settles invoice *X* and nothing else. There is no "which invoice did this pay?" question, no cross-invoice replay, and no need for the payer to identify itself.

The derivation of that address is an **origin-local matter** and is deliberately not specified. An origin MAY derive it deterministically from a master secret and the invoice id (the reference implementation uses `sha256(secret || ":" || invoiceId)` as the private key scalar) so that funds remain sweepable without storing a key table, or MAY use any other method. The payer neither knows nor needs to know. Section 9.1 states what the payer consequently cannot verify.

### 5.5 The paying request

A payer that has obtained a challenge MUST retransmit the **identical** original request - same method, same URL, same body - with one header added:

```
PAYMENT-SIGNATURE: base64(JSON(PaymentPayload))
```

where `PaymentPayload` is:

```jsonc
{
  "x402Version": 2,
  "accepted": { /* the PaymentRequirements object the payer selected */ },
  "payload": {
    "lockingScriptHex": "76a9148e3f1506db9e226b5850554953829d536299312588ac",
    "rawtx": "0100000001..."     // hex-encoded, fully signed BSV transaction
  }
}
```

The transaction MUST contain one or more outputs whose locking script equals `extra.lockingScriptHex`, summing to at least `amount` satoshis. The payer SHOULD NOT broadcast the transaction itself (Section 5.6 explains why).

Origins MUST accept `lockingScriptHex` from either `payload` or `accepted.extra`, and MUST compare it case-insensitively. Rejecting an otherwise-valid payment over field placement or hex case costs the origin a sale and costs the payer a transaction fee that bought nothing; tolerance here is cheap and asymmetrically valuable. Tolerance MUST NOT extend to the `scheme` field (Section 5.1) - misreading what a payment *means* is how money goes missing.

### 5.6 Verification and settlement

On receiving a `PAYMENT-SIGNATURE`, the origin MUST, in order:

1. Reject with `400` if the payload is not base64-encoded JSON, names an unsupported scheme, or omits the transaction or any payment identifier (`lockingScriptHex` preferred, `invoiceId` accepted).
2. Resolve the invoice. Unknown -> `402` with `errorReason: "invoice_not_found"` (an unresolvable invoice is a failed payment, not a missing web resource; see Section 7).
3. Verify that the invoice's resource matches the resource actually being requested. Without this check a payer could buy the cheapest invoice and present it at the most expensive endpoint; the payment would verify perfectly and buy the wrong thing (reject with `402`, `errorReason: "resource_mismatch"`). This check MUST run before step 4: an already-settled invoice for resource A is not proof of payment for resource B, and the idempotent-replay shortcut in step 4 MUST NOT be allowed to bypass it.
4. **If the invoice is already settled, treat the request as paid and serve the resource again** rather than charging a second time - regardless of the invoice's expiry, since expiry governs acceptance of new payment, not a resource already bought. Settlement MUST be idempotent on the invoice: agents retry by default, and a dropped response must not cost the payer twice. The scheme mints **no credential**, so there is nothing to re-issue on retry and nothing an on-chain observer could replay to obtain one.
5. Expired -> `402` with `errorReason: "invoice_expired"`.
6. Parse the transaction. Sum the satoshis paid to `lockingScriptHex`. If less than `amount`, reject with `402` (`errorReason: "insufficient_funds"`) and report both figures. Overpayment MUST be accepted. (A malformed or unparseable payload is a `400` per step 1, not a `402`.)
7. **Broadcast the transaction.** The origin, not the payer, broadcasts: this is how the origin actually collects, and it lets the network arbitrate double-spends. A broadcast rejection meaning "already known to the mempool" MUST be treated as success - it is the expected result of an idempotent retry. A transaction the network **rejects** (e.g. a double-spend or an already-spent input) is a failed payment: `402` with `errorReason: "broadcast_rejected"` and `retryable: false`. A failure to **reach** a broadcaster is an origin-side fault, not a bad payment: `500` with `errorReason: "broadcast_unavailable"` and `retryable: true`, and the payer SHOULD retry the same signed transaction rather than paying a second fee.
8. Mark the invoice settled and serve the resource in the same response.

Concurrent settlement attempts for the same invoice MUST be serialized. The check "is this invoice already paid?" and the write "mark it paid" straddle a network round-trip; two concurrent submissions that both pass the check would both broadcast and both be served, giving away a second resource delivery for one payment.

Authorization is granted on **mempool acceptance (0-conf)**, not on confirmation. See Section 9.2.

### 5.7 Settlement response (the scheme is credential-less)

**This scheme is pay-per-call: one payment buys one resource access, and it issues no reusable credential.** A second call is a second 402 and a second payment. This is deliberate - it keeps the money path stateless-per-payment and gives an observer nothing to steal.

On success the origin MUST respond with the resource, status `200`, and:

```
PAYMENT-RESPONSE: base64({
  "success": true,
  "transaction": "<txid>",
  "network": "bsv:mainnet",
  "extensions": { "status": "mempool" }
})
```

The `transaction` id is the payer's receipt; there is no `extra` object and no token. The `extensions.status` field declares the confirmation policy in x402-F's extensions mechanism (the field the Cardano `exact` binding uses for it): this scheme authorizes on **mempool acceptance** (0-conf), stated in the response so a reader can judge the risk up front rather than discover it from a reorg (Section 9.2).

On a failed payment attempt the origin MUST emit `PAYMENT-RESPONSE: base64({"success": false, "network": "...", "errorReason": "..."})` alongside the error status, so a client learns *why* in the protocol's own vocabulary (Section 7).

**A note on layered credentials.** Because a per-invoice address becomes public the moment the settlement transaction is broadcast, any reusable credential an origin might layer on top of this scheme MUST be bound to a secret held only by the payer - for example, the preimage of a hash committed at payment time - and MUST NOT be re-derivable from, or re-issuable in response to, public chain data; otherwise any observer who names a settled invoice by its on-chain locking script could obtain it. The base scheme sidesteps this concern entirely by carrying no credential: pay-per-call has nothing to steal.

### 5.8 Production precedes settlement (no charge on handler failure)

The origin broadcasts - the only point at which money moves - only **after** it has produced the resource. A handler that fails therefore means the transaction was never broadcast and the payer was never charged: there is no debit to refund and no reconciliation to get wrong. An origin that instead settles before producing MUST refund on every handler-failure path, but produce-then-broadcast is the safer construction and the one the reference implementation uses.

### 5.9 Discovery (non-normative)

x402-F catalogues resources through facilitator-side indexing of the `bazaar` extension, not through a well-known URL. An origin MAY publish a convenience document listing its resources, prices and input/output schemas; the reference implementation serves one at `/.well-known/x402`. **This is not a standardised discovery endpoint and this document does not make it one.** Discovery that costs something does not get discovered, so such a document SHOULD be free and unmetered.

## 6. Complete example

A complete, tokenless round trip against the reference origin: one payment buys one call, and the response carries the settlement txid as the receipt - no credential is minted.

```
$ curl -i https://bsv.cx/pay/hello

HTTP/2 402
payment-required: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJwYXltZW50IHJlcXVpcmVkIiw...
www-authenticate: BSV-402 invoiceId="cbc69cd9d737b07ed1dd6430", amountSats="10"
```

Decoded, the payer learns it owes 10 satoshis to `1JtZVopxM5FAG9XdxjvPPG9YjuN5kPoVYi` and that the invoice expires in 15 minutes. It signs a transaction paying that script and retries with the payment attached:

```
$ curl -i https://bsv.cx/pay/hello \
    -H "PAYMENT-SIGNATURE: $(printf '%s' "$PAYLOAD" | base64 -w0)"

HTTP/2 200
payment-response: eyJzdWNjZXNzIjp0cnVlLCJ0cmFuc2FjdGlvbiI6...
x-pay-txid: 8beeaead43c578de...

{"resource":"hello","txid":"8beeaead43c578de...","data":{"ok":true,...}}
```

The `PAYMENT-RESPONSE` header decodes to `{success, transaction, network, extensions:{status}}`

* no `extra` object, per Section 5.7 - and `transaction` is the payer's receipt. A second call is a new `402` and a new payment - there is no reusable credential.

**Backed by a real payment.** The example above reflects a captured mainnet settlement - transaction `102699c752889a60a0c2cf687ba361d98b89b3842a4cc2f7014a1c3302613a2a`, whose output 0 pays 10 satoshis to the P2PKH script `76a914c43a7aaf410bceb07b7c45b1c44f96865f4b15dc88ac` (`1JtZVopxM5FAG9XdxjvPPG9YjuN5kPoVYi`). Any BSV explorer will confirm it. This section asks you to verify it, not to trust it.

## 7. Error codes

This profile follows the x402-F v2 HTTP error model: the status line carries only a coarse outcome, and the specific reason travels in the `errorReason` field of the `PAYMENT-RESPONSE` header (echoed in the JSON body). A well-formed payment that fails verification or settlement is a `402`, not a bespoke 4xx.

| Status | Meaning                                                                                                                    | Example `errorReason`                                                                                   |
| ------ | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `400`  | Invalid payment: payload not base64 JSON, unsupported scheme, missing/unparseable transaction                              | `malformed_payment`                                                                                     |
| `402`  | Payment required (challenge, no payment presented) OR a well-formed payment that failed verification or settlement         | `insufficient_funds`, `invoice_not_found`, `invoice_expired`, `resource_mismatch`, `broadcast_rejected` |
| `500`  | Origin-side fault while processing an otherwise-valid payment (e.g. a broadcaster could not be reached); `retryable: true` | `broadcast_unavailable`                                                                                 |
| `503`  | Payment rail unavailable or mispriced: the origin declines business *before* any payment, rather than selling below cost   | -                                                                                                       |
| `200`  | Payment verified and settled; the resource is served in the same response                                                  | -                                                                                                       |

The response body carries an explicit `retryable` boolean so a payer holding a signed transaction knows whether to try again or to stop: a `500 broadcast_unavailable` is `retryable: true` (the origin could not reach a broadcaster; the transaction is valid and SHOULD be re-presented), while a `402 broadcast_rejected` is `retryable: false` (the network rejected the payment, so re-sending only burns a second fee). Note that an unknown **resource** path - as opposed to a failed payment - is an ordinary `404`, outside this payment-flow taxonomy.

## 8. Security considerations

* **Replay of a payment across invoices is structurally impossible** (Section 5.4): the transaction pays an address that exists for exactly one invoice.
* **Replay of a settlement request** is handled by idempotency (Section 5.6 step 4): a settled invoice re-serves the resource without charging again. Because the base scheme issues no credential, a replay yields at most a repeat of a resource already paid for - there is nothing an observer can obtain that they could not already fetch. No timestamp window is required, and consequently there is no clock-skew failure mode.
* **Cross-resource substitution** is prevented by Section 5.6 step 3, which runs before the idempotency shortcut so a settled invoice can't be replayed against another resource.
* **No credential to steal.** Being pay-per-call, the scheme mints no reusable credential, so the theft surface that a bearer token would create simply does not exist. An origin that chooses to layer its own credential on top MUST bind it to a payer-held secret and MUST NOT make it re-derivable from public chain data (Section 5.7).
* **Receiving keys are not spending keys.** An origin SHOULD hold the payment-receiving secret separately from any hot wallet it spends from for other purposes. Commingling corrupts UTXO selection and the books at once.
* **Unmetered challenge creation** is a cheap request that allocates server state. Origins SHOULD rate-limit challenge issuance, but MUST NOT rate-limit a request carrying payment ahead of settling it - refusing a paid request leaves the payer holding a broadcast transaction and nothing to show for it.

## 9. Limitations

These are the costs of the design goal in Section 3. They are listed at the same weight as the benefits because an implementer choosing between this and BRC-121 needs them.

**9.1 The payer cannot verify the address is "theirs."** Under BRC-29/BRC-42 derivation the payer participates in deriving the destination key and can confirm the output is correctly formed. Here the origin simply asserts an address. A payer's protection is that the address is unique to its invoice and that non-delivery is publicly attributable to a named service - reputational, not cryptographic. **For payments large enough that this matters, use BRC-105 or BRC-121.** This scheme is designed for amounts where the transaction fee is a meaningful fraction of the payment.

What *is* checkable by any third party, from public data alone, is the **payment**: given a challenge (which names `payTo`/`lockingScriptHex`, `amount` and `invoiceId`), anyone can confirm on-chain that a transaction pays that script for at least that amount, without the origin's cooperation. What is *not* checkable at base is the **binding** - that the address genuinely belongs to that invoice, and that the origin did not issue the same address to two payers. An origin MAY provide a stronger construction that makes the full invoice->address->transaction binding verifiable without trusting the origin (for example, a signed receipt) as an **optional extension**; the base scheme neither requires nor guarantees it.

**9.2 Authorization is granted at 0-conf.** The origin serves on mempool acceptance. A double-spend could in principle claw back the payment after the resource is delivered. For sub-cent amounts this is economically absurd - the attack costs more than it recovers - but it is a real property and it does not scale to large payments. Genuine settlement finality is a payment-channel upgrade, not a fix to this scheme.

**9.3 No SPV ancestry.** BRC-121 ships BEEF, so the origin can validate the payment's ancestry locally. Here the origin receives a bare transaction and must consult the network to broadcast it, which is a liveness dependency on a broadcaster and a per-payment latency cost.

**9.4 No payer identity.** There is no `senderIdentityKey`. The origin cannot correlate payments to a payer, offer refunds to a known party, or build reputation. For the target use case this is a feature; for a subscription business it is disqualifying.

**9.5 The origin holds invoice state.** Invoices are server-side records with expiry, unlike BRC-121's stateless verification, so an origin must persist and prune them. The footprint is small: the scheme is pay-per-call and holds **no per-payer credential state** - only short-lived invoice records that a settled payment can retire.

## 10. Implementations

Live on mainnet at <https://bsv.cx/pay>, serving several resources behind this scheme. Machine-readable catalogue: <https://bsv.cx/.well-known/x402>.

Source: the `x402.ts` and `routes/pay.ts` modules of the bsv.cx service. The wire shapes in Section 6 match that endpoint's live output field-for-field, and Section 6 is backed by a real captured mainnet settlement: transaction `102699c752889a60a0c2cf687ba361d98b89b3842a4cc2f7014a1c3302613a2a`, whose output 0 pays 10 satoshis to the P2PKH script `76a914c43a7aaf410bceb07b7c45b1c44f96865f4b15dc88ac` (`1JtZVopxM5FAG9XdxjvPPG9YjuN5kPoVYi`). Verify it on any BSV explorer rather than trust it.

## 11. References

* x402 Foundation specification: <https://github.com/x402-foundation/x402>
* [BRC-27: Direct Payment Protocol](https://bsv.brc.dev/payments/0027.md)
* [BRC-29: Simple Authenticated BSV P2PKH Payment Protocol](https://bsv.brc.dev/payments/0029.md)
* [BRC-105: HTTP Service Monetization Framework](https://bsv.brc.dev/payments/0105.md)
* [BRC-120: x402 Stateless Settlement-Gated HTTP Protocol](https://bsv.brc.dev/payments/0120.md)
* [BRC-121: Simple 402 Payments](https://bsv.brc.dev/payments/0121.md)
* CAIP-2: <https://chainagnostic.org/CAIPs/caip-2>
* RFC 9110 Section 15.5.3: 402 Payment Required


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://bsv.brc.dev/payments/0166.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
