A lightweight HTTP facilitator that verifies and settles Bitcoin on-chain payments following the x402 protocol. No custodians. No accounts. Just transactions.
Three steps from payment claim to settled resource access
The client sends a Bitcoin transaction on-chain and encodes the txid, recipient address,
and amount (in sats) as a Base64 JSON header: X-Payment.
POST /verify decodes the header, hits the Blockstream API
to confirm the tx exists on-chain with sufficient confirmations and the correct output amount.
Replayed txids are rejected immediately.
POST /settle re-verifies and permanently records the txid
in SQLite. A signed Payment-Response header is returned.
The resource server grants access.
Base URL: https://x402-bitcoin.cdnsoft.net
// Response 200
{
"status": "ok",
"service": "x402-bitcoin",
"scheme": "bitcoin-onchain"
}
| Field | Type | Description |
|---|---|---|
| X-Payment | Base64 | Base64-encoded JSON payload (see below) |
| Field | Type | Description |
|---|---|---|
| txid | string | Bitcoin transaction hex ID required |
| recipient | string | Bitcoin address receiving payment required |
| amountSats | integer | Expected output value in satoshis required |
| scheme | string | "bitcoin-onchain" (optional) |
| resource | string | URL being accessed (optional) |
| nonce | string | Binding nonce (optional) |
// 200 — valid
{
"valid": true,
"txid": "abc123…",
"recipient": "148G6…",
"amountSats": 10000,
"confirmations": 3,
"scheme": "bitcoin-onchain"
}
// 402 — invalid
{
"valid": false,
"error": "Insufficient confirmations",
"code": "UNCONFIRMED",
"confirmations": 0
}
| Code | HTTP | Meaning |
|---|---|---|
| TX_NOT_FOUND | 402 | txid not on-chain |
| UNCONFIRMED | 402 | not enough confirmations |
| AMOUNT_MISMATCH | 402 | wrong amount or address |
| REPLAY | 402 | txid already settled |
| NETWORK_ERROR | 500 | Blockstream API failure |
| Field | Type | Description |
|---|---|---|
| X-Payment | Base64 | Same payload as /verify |
Settle re-runs the full /verify check before writing. If verification fails, nothing is recorded. Calling /settle twice with the same txid returns REPLAY on the second call.
// 200 — settled
{
"settled": true,
"txid": "abc123…",
"recipient": "148G6…",
"amountSats": 10000,
"settledAt": "2026-03-16T01:00:00.000Z",
"scheme": "bitcoin-onchain"
}
// Response header:
Payment-Response: <base64 receipt>
// 402 — not settled
{
"settled": false,
"error": "Transaction already settled",
"code": "REPLAY"
}
Hit the real API — use a confirmed mainnet tx from blockstream.info
Checks the tx on-chain via Blockstream. Returns valid/invalid without recording anything.
Re-verifies then records the txid in SQLite. Subsequent calls with the same txid are rejected.