Accepting Bitcoin payments: where receipt accounting breaks
Accepting Bitcoin breaks not on cryptography, but on receipt accounting. Addresses are often issued manually: a manager takes a free address from the wallet, dictates it to the client, and does not mark which invoice it is assigned to.
Then comes address reuse: different clients pay to the same address, and amounts can no longer be allocated across invoices.
HD addresses remove this at the key derivation level: a sequence of addresses is deterministically generated from a single seed phrase, and each order gets its own.
On the server, an extended public key is sufficient — private material remains offline, and the system issues new addresses and reconciles receipts without access to funds.
Another bottleneck is incoming transaction accounting. While the service does not listen to the network, only the client knows about the payment: crediting is done manually after an email, and until that moment the order remains unpaid.
A watcher is needed that links a transaction to the invoice address, brings confirmations to the required threshold, and correctly survives a chain reorganization when a transaction drops out of confirmed.
Hence lost receipts: a transfer to an address not linked to an order reaches the wallet and does not appear in any report. Reconciliation lags by days and is done by exporting to a spreadsheet, while discrepancies surface during refunds and audits.
We explain how this is closed — a separate address for each invoice, monitoring with a confirmation threshold, and reconciliation without manual labor.
What managed acceptance gives: crediting, reconciliation, incident handling
Managed acceptance starts with addressing: an HD wallet issues a separate address for each invoice, and monitoring runs via an extended public key — private keys never leave cold storage.
We verify compliance with consensus rules on Bitcoin Core, without trusting third-party APIs: crediting is not built on unconfirmed data from someone else's indexer.
Receipt monitoring covers both blocks and mempool: an incoming transaction is visible within seconds after broadcast, even before the first confirmation. Until the confirmation threshold, the payment is shown as 'pending', afterward it is credited automatically.
Transaction notifications go to an internal queue with an idempotent key, so repeated delivery does not create duplicates in the accounting system.
Automatic reconciliation runs on a schedule and on events: the payment registry is compared with network state, and discrepancies are closed without manual search.
The share of credits processed without operator involvement exceeds 95%, and the volume of manual reconciliations is reduced to isolated discrepancies per period.
A separate workstream is incident handling: reorg, transaction replacement with a fee bump, a payment stuck in mempool during a congested network. Each scenario has a handler — rebroadcast, replacement with a higher fee, alerting the on-call engineer with full context.
Response time to a stuck transaction is measured in minutes, not in hours of waiting for the client to reach out.
Acceptance scheme options: own node, provider, hybrid
The acceptance scheme defines three things: where private keys are stored, who holds a synchronized copy of the chain, and on whose side incoming transactions are tracked.
Changing it after launch is more expensive than choosing deliberately: the scheme determines the address format, confirmation depth, and the procedure for handling disputed receipts.
The four alternatives differ not in 'reliability in general', but in the distribution of responsibility between you and the provider.
Comparison by applicability
| Option | When it fits | Limitations |
|---|---|---|
| Own node | Large payment volume, requirements for independence and audit, and someone available to maintain the infrastructure | Chain synchronization takes hours and disk space, requires updates and on-call monitoring |
| Acceptance service | Quick start, small and medium volume, no desire to maintain own infrastructure | Provider dependency, request limits, some data goes outside |
| Hybrid scheme | Need to launch now, with keys and acceptance inside the perimeter later | Harder to test: two processing paths and discrepancies in receipt statuses |
| Custodial acceptance | Accounting on the platform balance, internal transfers between users | Keys are not yours, added load for storage and handling requests |
The choice hits a ceiling: own node — in maintenance, acceptance service — in provider limits and availability, custodial acceptance — in storage requirements.
A hybrid scheme allows starting on a service and then moving acceptance to your own node without rewriting the integration: addresses and payment labeling remain the same.
Implementing Bitcoin payments: from flow audit to procedures
The order of steps here matters more than speed: the addressing scheme determines how receipts are matched to orders, and key access policies determine what can be recovered at all in an incident. That is why we start with an audit and finish with a procedure that support can follow without us.
- Audit of incoming flows. We look at where payments are accepted, how invoices are created, and how a receipt is linked to a specific client. The output is a flow map and a list of places where manual intervention is still required.
- Addressing scheme. We design the wallet hierarchy: a separate branch for each operation type, its own address per invoice, and a gap limit reserve. We fix which addresses are public and which remain internal.
- Monitoring setup. We enable tracking of addresses and unconfirmed transactions, count confirmations, handle transaction replacement and block rollback. Every event is written to a journal with a link to the invoice.
- Key access policies. We separate roles — generation, signing, issuance. The application does not receive the master key: only a separate vault with an operation log and a clear circle of responsible people.
- Testing on a staging environment. We run edge scenarios: underpayment, overpayment, repeated crediting, stuck transaction. We check that the balance reconciles and statuses do not diverge from the journal.
- Processing procedure. We describe support actions for each discrepancy, the refund and escalation procedure — this removes the process's dependence on a single engineer.
- Handover. We hand over documentation and access, train the team, and stay in touch until metrics reach a steady level.
Deliverables: wallet configurations, schemes, procedures
Accepting Bitcoin is not only working code, but also a set of artifacts by which the system can be developed, handed over to another team, and pass internal reviews.
We assemble the deliverables so that the customer has no knowledge that lives only in correspondence with the developer.
- Wallet configuration — node connection parameters, key storage mode (only the public part on the server), and rules for forming and signing transactions.
- Addressing scheme — path map for hierarchical addresses, rules for issuing a new address for each client and order, gap limit in the chain, and the procedure for extending it.
- Access policies — role matrix: who has access to keys, who confirms fund withdrawals, how action logs are maintained and where they are stored.
- Monitoring procedure — which events are tracked, how many confirmations are required for crediting, what to do in case of underpayment, address reuse, and chain reorganization.
- Incident response procedure — step-by-step scenarios for the on-call engineer: node unavailability, stuck transaction, balance discrepancy with the accounting system.
- Documentation — architecture and failure point description, recovery instructions from the seed phrase, key rotation procedure, and service decommissioning procedure.
Additionally, we provide a memo for support and finance: how to match a received payment with an order and what to tell the client when crediting is delayed. We place all artifacts in the customer's repository and review them with their team during handover.
Case study: how we reduced manual handling of stuck receipts
The client is a payment acceptance service with a flow of several thousand invoices per month: each order received a separate address from an HD chain, but receipt reconciliation was done manually using a block explorer statement.
An operator matched the amount, recalculated at the exchange rate, and closed the invoice — this took up to six hours, and payments with non-standard fees got stuck in the queue and arrived a day later.
Initial situation
The share of automatic credits was 62%, the rest was handled by a person. Average response time to a stuck transaction was up to six hours, and about 40 disputed cases accumulated per month when a client claimed they had paid but the invoice remained open.
The reason was not support: the system saw the transfer only after confirmation, which meant it could not distinguish 'still in progress' from 'will not happen'.
What we did and what resulted
Acceptance was moved to a watch-only wallet: an extended public key on the service side, private keys in cold storage.
Monitoring was built on our own Bitcoin Core node — it returns incoming transfers to chain addresses as soon as they appear in the unconfirmed queue, without waiting for a block.
Deduplication by transaction ID closed double credits on rebroadcast, and a separate rule marks fee-bump replacement and credits by the latest version of the transfer.
The share of automatic credits grew to 98%. Response to a stuck transaction is 2–3 minutes instead of hours: the system sees the transfer in the queue, shows confirmation depth, and notifies the client itself.
The number of disputed cases dropped to 2–4 per month, and manual handling remained only for small amounts that are not worth sending over the network.
How does an HD wallet differ from a set of individual addresses?
An HD wallet stores not a set of addresses, but a single backup phrase from which a key tree is deterministically derived.
Each new address gets an index, and it can be reproduced again at any time — the entire history of payment acceptance is restored from one phrase, without an archive of keys.
With a set of individual addresses, each key lives on its own: the backup becomes a list of all keys, and losing one means losing funds on it. Adding an address is a manual operation, so at thousands of invoices the scheme diverges from accounting and ceases to be verifiable.
The Bitcoin standard defines two independent branches: external for receiving and internal for change.
They do not intersect, so client payments and service transfers are not mixed in history, and different products or legal entities get their own branches with separate numbering.
Therefore, one address cannot be reused for a payment stream: transactions become linked to each other, the address becomes a public identifier of the client, and monitoring is forced to parse the entire incoming flow.
When issuing an address per invoice, the bottleneck is the search window during recovery: an address issued beyond its boundaries simply will not be found. We keep a reserve window and fix its size in the configuration.
The private part remains in cold storage, while the acceptance service works only with the public branch — server compromise does not open access to funds.
Technical concerns: lost keys, duplicates, stuck transfers
Disputed situations in Bitcoin acceptance almost always lie not in the network itself, but in the processes around it: who holds access to funds, what counts as a repeated payment, how to act with a stuck transaction.
Below are three scenarios that most often come up during system handover to the customer, and how they are handled in the acceptance scheme.
The scheme is built on an HD wallet: a chain of addresses is derived from one root phrase, and each invoice has its own.
Only the public part reaches the monitoring server, so it sees receipts and matches them to invoices, but cannot sign a withdrawal — loss or compromise of the working node does not open access to money.
What if an employee with access leaves or loses a key?
Withdrawal is built on a multi-signature scheme: a transaction is confirmed by several share holders, and no one can dispose of funds single-handedly. Rotation reduces to replacing one share — acceptance addresses and the entire receipt history do not change.
What if the client paid twice or sent again to the same address?
The receipt is matched by transaction ID, not by amount, so a repeat does not create a second order. After confirmation, the address is marked as used but remains valid: the wallet accepts all current address formats and issues a compatible one to the sender.
A transfer has been pending without confirmation for several hours
With a low fee, the payment waits in the network queue. The rate is calculated from current load, and when idle, the transaction is replaced with a higher-fee version, without canceling the original.
In the accounting system, the status changes transparently: 'queued' → 'confirmed' → 'replaced', so the order is neither lost nor duplicated.
Next are typical questions that we cover during handover: backup storage, access, and the withdrawal procedure.Let's discuss your acceptance scheme and come back with an estimate and plan
For the estimate to be substantive, it is enough to describe how Bitcoin acceptance is currently set up: where addresses are generated, how keys are stored and who signs outgoing transactions, what tracks incoming transactions, and how many confirmations you consider sufficient.
If you have incident logs — undercredited deposits, stuck receipts, disputed credits — attach them: they remove half of the clarifying questions.
- Review of the current scheme: address derivation, key tree, role separation, who reconciles balances and how.
- Estimate and stage-by-stage work plan — with a result visible at each step.
- List of edge scenarios: block chain reorganization, address reuse, dust receipts, fee-replacement transactions.
- Handover of procedures: confirmation policy, thresholds for large amounts, support instructions, and incident handling procedure.
- Monitoring and alerts: stuck incoming transactions, discrepancy between the address journal and actual receipts, node load spikes.
- Post-launch support: updates for network changes, logic improvements for new scenarios, and handling requests for specific transactions.
Describe the task in free form or send current configurations — we will come back with an estimate and plan, outline the stage boundaries and control points.
After that, all that remains is to agree on timelines and start with the area that currently generates the most manual work.







