Draft specification
A Bitcoin scheme for x402.
Native on-chain Bitcoin inside x402’s exact scheme. The payer signs and broadcasts. The merchant checks and accepts the payment before providing the resource.
The proposal uses the client-submitted, upfront flow. It works with a merchant’s own node or a provider and requires no Satsgate account. It is under review upstream.
- scheme
- exact
- network
- bip122:000000000019d6689c085ae165831e93
- CAIP-2. The first 32 hex of the Bitcoin mainnet genesis hash.
- extra.assetTransferMethod
- onchain
- extra.paymentFlow
- upfront
- Specification
- Proposed exact / bip122 method for x402 v2.
- Runtime packages
- Separate implementation work; this proposal defines the protocol.
- Upstream proposal
- Open. Pull request 3737 on x402-foundation/x402, awaiting review.
- Licence
- Apache 2.0, same as x402.
Payment flow
Bitcoin uses x402’s upfront flow. The merchant issues a fresh address and a private payment identifier bound to one operation. The payer broadcasts, pays the mining fee and retries with the payment outputs as proof.
paymentFlow: "upfront"
Client-submitted. Settlement can run locally or through a provider.
- pay
The payer signs, broadcasts, pays the miner fee, and retries with the output references.
- settle
Your server checks the exact total and advertised depth, then atomically claims the outputs and payment ID before expiry.
- respond
Your server runs the bound request and returns the result with the committed payment set.
Settlement validates the payment and records it as used; it does not broadcast. The merchant may settle locally or delegate to a facilitator. An outage can still delay acceptance or service, even after the payer has sent funds.
The payload
Each invoice carries its own address and its own payment identifier. The payer pays, then presents the outputs it used, each one a txid and a vout. Settlement checks they pay the address, sum to the exact satoshi amount and meet the confirmation policy. Before expiry, it records all selected outputs and the payment identifier as consumed in one atomic step, together with the operation they purchased.
{
"scheme": "exact",
"network": "bip122:000000000019d6689c085ae165831e93",
"amount": "412900",
"asset": "BTC",
"payTo": "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
"maxTimeoutSeconds": 3600,
"extra": {
"assetTransferMethod": "onchain",
"paymentFlow": "upfront",
"paymentId": "7b9e81c023d46fa598e6d304ca1f7260ef083cb519ad47e26f953a80d642c1bb",
"issuedAt": 1790000000,
"expiresAt": 1790003600,
"recoveryUntil": 1790090000,
"minConfirmations": 1,
"maxPaymentOutputs": 8,
"latePaymentPolicy": "no-automatic-refund"
}
}{
"outputs": [
{
"txid": "1111111111111111111111111111111111111111111111111111111111111111",
"vout": 0
}
]
}# After validation, before expiresAt, in one atomic commit:
claim all selected <network>/<txid>:<vout> outputs
claim the issuer's paymentId
record the bound operation and committed output set
# Execute the operation only after that commit.Examples are illustrative. The address has a publicly known private key; never send funds to it. Identifiers and timestamps are sample values. Keep real payment identifiers private and out of public logs.
The method works across x402 transports. Over HTTP, the server sends base64-encoded requirements in PAYMENT-REQUIRED. The client sends the full v2 payload, including unchanged accepted requirements and the output proof, in PAYMENT-SIGNATURE. Settlement results use PAYMENT-RESPONSE. See the complete envelopes.
Confirmation depth
The merchant chooses minConfirmations when issuing the payment. Every output must meet that threshold. Each settlement call returns promptly; it does not wait for a block.
- Zero confirmations
- A threshold of 0 permits acceptance from fresh, consistent mempool evidence. Replacement, eviction and double-spend risks remain. RBF signalling cannot establish that a transaction is safe from replacement.
- Waiting for depth
- An observed payment below the threshold returns settlement_pending with success: false. No output is consumed and no resource is executed. Retry against the original requirements before expiry.
- Monitoring
- A monitor can assemble the proof and commit payment before the client retries, using the same validation, deadline and atomic claim rules. Public transaction details never authorise access to the resource.
- Lightning coexistence
- Lightning uses lnbtc with millisatoshis. This on-chain draft uses bip122 with satoshis. Both use upfront.
Exact amounts and top-ups
asset: "BTC" uses satoshis in amount. The selected outputs must total exactly that amount; mining fees are extra. The quote stays fixed even if the exchange rate changes.
- One output or several
- maxPaymentOutputs: 1 requires a single output. A larger limit permits split payments and top-ups. References must be unique and sorted by txid, then vout.
- Completing a short payment
- Before expiry, add the shortfall and submit the complete set again. Each output must meet the confirmation policy. A shortfall below relay or dust limits may be impossible to top up.
- Overpayment
- A selected set above the quoted amount fails. The address balance is not the proof, and unrelated transfers do not invalidate an exact set. There is no automatic refund.
- No partial credit
- A failed or pending attempt consumes nothing. Partial payments cannot be carried into a new quote after expiry under this method.
Expiry and recovery
The first settlement must be durably committed before expiresAt. Broadcasting or reaching the required depth before that deadline is not enough by itself. The merchant must allow a window suited to its confirmation policy.
If payment was committed, an authorised retry can recover the original operation through recoveryUntil, including at that timestamp. Recovery keeps the original requirements, operation and receipt, even if the retry lists different outputs. It grants no second purchase. External side effects still need application idempotency.
latePaymentPolicy: "no-automatic-refund" means unconsumed funds at expiry grant no automatic resource or refund. Expiry cannot cancel a Bitcoin transaction. Any refund is a separate, authenticated arrangement with the merchant.
The payment receipt
SettleResponse.extensions["bip122-payment-set"] returns every output the merchant accepted. It is required on first success and authenticated already-settled recovery, including a single-output payment or a commitment made by a monitor. The top-level transaction identifies the first transaction in the committed set.
The receipt always comes from the stored commitment, even when the retry submits another set. It records payment acceptance under the issued policy; it does not certify service delivery or irreversible confirmation. Clients keep the receipt with the original requirements and check that the network matches.
Example settlement response
{
"success": true,
"transaction": "1111111111111111111111111111111111111111111111111111111111111111",
"network": "bip122:000000000019d6689c085ae165831e93",
"extensions": {
"bip122-payment-set": {
"info": {
"version": 1,
"outputs": [
{
"txid": "1111111111111111111111111111111111111111111111111111111111111111",
"vout": 0
}
]
},
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": [
"version",
"outputs"
],
"additionalProperties": false,
"properties": {
"version": {
"type": "integer",
"const": 1
},
"outputs": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "object",
"required": [
"txid",
"vout"
],
"additionalProperties": false,
"properties": {
"txid": {
"type": "string",
"pattern": "^[0-9a-f]{64}$"
},
"vout": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
}
}
}
}
}
}
}
}This extension appears only in the response. Servers do not advertise it in requirements, and clients do not echo it in their payloads. Other settlement failures omit it. A facilitator supporting this method lists bip122-payment-set in its /supported extensions.
The facilitator role
A separate facilitator is optional. A merchant can use its own validating node or a provider for Bitcoin evidence. Whoever performs settlement must also keep durable records that prevent outputs and payment identifiers from being claimed twice.
An indexer lookup supplies evidence; the settlement implementation authenticates the requirements and claims the payment. Changing providers must preserve those records. Blockchain history cannot reconstruct whether the resource was already granted. A read-only verify call never authorises execution.
Implementation scope
The upstream proposal defines the method. Client and server integrations must implement its validation, durable claims, recovery and receipts before claiming support. The method permits implementations independent of Satsgate.
Implementations advertise each supported network explicitly, with confirmation and output-count limits in /supported. The specified networks are Bitcoin mainnet, testnet4 and regtest. Supporting one does not imply support for every bip122 network. Lightning remains a separate mechanism under lnbtc.