Bitcoin
| Slug | btc |
| Address format | Native segwit (P2WPKH), bc1q… |
| Account path | m/84'/0'/0' (BIP-84) |
| Cloud stores | zpub |
| Derivation | ✅ M/0/{i} — public, no Edge required |
| Confirmations | 1, 2 and 3 — a webhook at each |
| Tokens | None. Native BTC only |
| Explorer | https://mempool.space/tx/{txid} · https://mempool.space/address/{address} |
Addresses
Native segwit, one per customer, issued once and kept.
{ "chain": "btc",
"address": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
"derivationPath": "m/84'/0'/0'/0/0" }
That address is what the published BIP-39 test vector derives at index 0 — useful for confirming your Edge's derivation is correct. See Installation.
Native segwit rather than legacy P2PKH or wrapped P2SH: it is cheaper to spend from (witness data
is discounted in the fee calculation), it is universally supported by senders in 2026, and it
produces the bc1q prefix your customers now expect. Nothing here issues a Taproot bc1p
address; if a sender insists on one, they cannot pay you, but that is not a case that occurs in
practice.
The confirmation ladder
Bitcoin is the only chain here with more than one threshold, and deposit_confirmed fires
three times for one deposit:
| Confirmations | Events you receive | threshold |
|---|---|---|
| 1 | deposit_detected and deposit_confirmed | 1 |
| 2 | deposit_confirmed | 2 |
| 3 | deposit_confirmed | 3 |
Read threshold from the payload to know which one you have. Three is settlement-safe for most
values; many fintechs credit small amounts at 1 and hold larger ones to 3, which is exactly why the
ladder exists rather than a single figure.
Each threshold fires exactly once, tracked in a bitmask, so a reorg-and-replay cannot re-fire one that already fired.
event.id aloneThree events, three ids, one deposit. If your credit is per event you credit three times. Dedupe
events on event.id, and key the credit on (txid, outputIndex). See
Idempotency.
Fees
fee = estimatedVBytes × satPerVbyte
| Field | |
|---|---|
satPerVbyte | The current rate for the target confirmation window |
estimatedVBytes | Transaction size estimate. Depends on UTXO selection |
inputCount | How many UTXOs the build expects to spend |
outputCount | Destination plus change |
The fee comes out of the inputs being spent. sum(inputs) − sum(outputs) is the fee, so
Bitcoin cannot have the INSUFFICIENT_GAS problem the EVM chains have — there is no separate gas
asset. A send that leaves nothing for the fee gets INSUFFICIENT_FUNDS.
estimatedVBytes is genuinely an estimate. It moves with how many UTXOs the build selects, which
depends on what has arrived at that address. Do not present a fee to a customer as final unless you
are prepared to absorb the difference.
UTXO consolidation
An address that has received many small deposits holds many small UTXOs, and spending from it requires including several of them — each adding about 68 vBytes. A withdrawal from such an address costs more than the same withdrawal from an address with one large UTXO, sometimes several times more.
This is the one Bitcoin-specific reason to sweep even when you otherwise would not: consolidating during a low-fee period is materially cheaper than paying the input premium on every future withdrawal.
Batching links your addresses, permanently
Sweeping twenty addresses in one transaction with twenty inputs is far cheaper than twenty separate transactions. It also proves, on-chain and forever, that those twenty addresses are controlled by the same entity.
Whether that matters is a decision about your customers, not a technical one. It cannot be undone. Decide deliberately rather than by picking whichever code was easier to write. See Sweeps.
Reorgs
Bitcoin's reorg risk is what the three-threshold ladder is calibrated against. A one-block reorg is routine; a three-block reorg has not happened outside of a consensus incident.
If a block containing a detected deposit is orphaned, the transaction returns to pending and the count resets. Any threshold not previously fired fires again when reached. A reversal after threshold 3 is a genuine incident — see Incident response.
No tokens
Bitcoin support is native BTC only. Ordinals, BRC-20, Runes and Lightning are all out of scope, and a deposit involving them is not detected as a token deposit — an inscription's associated sats appear as an ordinary BTC deposit of that amount, which for a fintech's purposes is the correct reading.
Operational notes
- Balances and UTXOs are address-indexed lookups, which is what deposit monitoring needs and
what a plain node RPC cannot answer. Ziklag operates that infrastructure. If balances return
503 CHAIN_UNAVAILABLEwhile derivation keeps working, that is ours to fix — see Incident response. zpub, notxpub. Cloud stores the BIP-84 form. If you import your mnemonic into a wallet to verify, point it atm/84'/0'/0'— the same seed atm/44'/0'/0'derives entirely different addresses, which look wrong but are not.- Dust limits. A send below about 294 satoshi to a segwit output is rejected by the network as
dust. It surfaces as
422 CHAIN_REJECTEDwith the node's reason. - Mempool congestion shows up as
satPerVbyteclimbing and confirmations taking much longer than ten minutes. There is nothing to fix; there is something to tell your customers.