Bitcoin checkout for agents, and for people.
One REST call creates a checkout. A signed webhook tells you it was paid. The coins go from the payer straight to a wallet only you can spend from.
- 01Your agent asks for something behind a paywall.
- 02You answer 402 with a fresh address, payment ID, amount, deadline and confirmation policy.
- 03The payer signs and broadcasts its own Bitcoin transaction.
- 04The payer retries with output references. Your server checks the payment against the issued terms.
- 05At the required depth, your server claims the payment before expiry, then runs the request.
01
Create the checkout
You post an amount and a reference. Satsgate derives a fresh address from your extended public key, which can watch your wallet and cannot spend from it. That address belongs to this checkout and is never reused. For x402, a private payment identifier also binds the quote to the purchase.
curl https://api.satsgate.io/v1/checkouts \
-H "Authorization: Bearer sk_test_4eC39Hq" \
-H "Idempotency-Key: order_4821" \
-d amount=4200 \
-d currency=usd \
-d reference=order_4821 \
-d min_confirmations=1 \
-d expires_in=3600{
"id": "co_3PmQ2r8kLxN1",
"status": "pending",
"amount_sat": 412900,
"rate_locked_until": "2026-09-21T15:13:20Z",
"address": "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
"livemode": false
}02
Return the 402
Return the requirements in the v2 PAYMENT-REQUIRED header. A client implementing the proposed Bitcoin method reads the exact satoshi amount, deadline and confirmation policy. After paying, it retries with the original requirements and output references in PAYMENT-SIGNATURE.
{
"x402Version": 2,
"resource": {
"url": "https://example.com/report",
"mimeType": "application/json"
},
"accepts": [
{
"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"
}
}
]
}The header carries this object as base64-encoded JSON. Keep each live payment identifier private; the one shown here is illustrative.
03
The payer broadcasts
The payer signs and broadcasts its own transaction, and pays the miner fee on top of the quoted recipient amount. The merchant can check payment locally or delegate the checks to a provider.
The payer chooses its wallet and broadcast provider. An external facilitator is optional and never needs to sign or broadcast the payment for this method.
Satsgate holds no spending keys and no funds. The coins go from the payer to a wallet only you can spend from, and there is no account balance here to withdraw.
04
Pick the depth you accept
Set min_confirmations per checkout, so a £4 download and a £4,000 order can use different policies. The x402 requirements call this minConfirmations. Every selected payment must meet it before the first settlement is recorded, before expiry.
- 0Mempool acceptanceFresh evidence from a validating node is required. Replacement and eviction remain possible.
- 1One blockThe payment is included in the active chain. A reorganisation can still remove it.
- 3Three blocksMore work secures the payment than at depth 1. Reorganisation risk remains.
- 6Six blocksA deeper confirmation policy for higher-value orders. It still gives no absolute finality.
Zero confirmations is a merchant choice when the settlement backend supports it. Blocks average ten minutes apart; fee rates and block timing can make the wait longer.
05
Record payment, then fulfil
For x402, the server checks that the selected outputs total the exact quote, then records all of them and the payment identifier together before running the purchase. A retry recovers that same purchase. The receipt lists the complete accepted output set.
POST /webhooks/satsgate HTTP/1.1
Content-Type: application/json
Satsgate-Signature: t=1790000600,v1=<signature>
{
"id": "evt_1NnQ4kLxP2mT",
"type": "checkout.settled",
"data": {
"object": {
"id": "co_3PmQ2r8kLxN1",
"status": "settled",
"confirmations": 1,
"txid": "1111111111111111111111111111111111111111111111111111111111111111",
"amount_sat": 412900
}
}
}Satsgate checkout webhooks use HMAC-SHA256 over the timestamp and raw body, with three days of retries and a retrievable event log. They are a merchant API notification; the x402 payment receipt travels separately in PAYMENT-RESPONSE.
Addresses shown here are the published BIP173 test vector. No live wallet appears on this site.
What can still go wrong
Confirmation policy, deadlines and recovery matter when a payment leaves the happy path.
The payment is replaced
An unconfirmed payment can be replaced, even without opt-in RBF signalling. A replacement may pay less or nothing. Choose a confirmation depth that suits the purchase; zero confirmations carries that risk.
checkout.payment_reverted
The payment is dropped
A transaction can leave the mempool without confirming. Before acceptance, the purchase stays unpaid. After x402 settlement, a drop or reorganisation does not reopen the purchase or authorise another delivery.
checkout.payment_reverted
The amount is short
The quoted satoshi amount stays fixed. If fees or withdrawal deductions leave it short, the payer can add outputs within the advertised limit. The complete set must total the exact quote and qualify before expiry. A tiny shortfall may be too small to relay as a top-up.
checkout.underpaid
Payment is not accepted before expiry
Funds may arrive even when the first settlement misses its deadline. The x402 method grants no automatic delivery or refund in that case. A payment already accepted before expiry can still recover its purchase through the advertised recovery window.
checkout.expired
Limits worth knowing
- Blocks average ten minutes apart. No API can guarantee inclusion by a deadline. Depth 0 avoids waiting for a block but still needs a fresh check against a validating node.
- On-chain fees can outweigh a small purchase. Satsgate is not built for per-request micropayments.
- Satsgate cannot reverse a payment, because it never held it. Refunds are a new transaction from your wallet to an address the payer gives you.
- A service outage does not stop Bitcoin transfers. It can stop settlement before expiry, even after funds arrive. Preserve the payment requirements and transaction references so an uncertain result can be reconciled before paying again.
1%
One percent of what settles. Nothing else.
No monthly fee, no setup fee, no charge for a checkout nobody pays. The first five transactions on a live account are free, so you can put it in front of a real customer before you owe anything.
- The merchant serviceFirst five transactions free
- 1% of settled volume
- The walletAgent side, no account needed
- Free
- The scheme and the runtime packagesNative Bitcoin specification proposed upstream
- Free
- Test modeUnlimited, on the simulated chain
- Free