Stablecoin Reconciliation & Ledger Integrity Guide
Ensure your internal balances, Bitnob wallet balances, and on-chain transactions stay perfectly in sync—always.
Why This Matters
In a multi-chain stablecoin system:
On-chain transactions are probabilistic until confirmed
Webhook delivery may fail or delay
Transfers may succeed on Bitnob but fail on-chain
Deposits may arrive without a known customer mapping
Even one unnoticed mismatch breaks trust
Your business must track and reconcile:
What you think the balance is (your internal ledger)
What Bitnob says the balance is (wallet API)
What the blockchain actually shows (confirmed txs to/from deposit addresses)
This guide shows how.
Reconciliation Strategy
Your Reconciliation System Should Answer:
Question | Example |
---|---|
Did we credit a deposit before it had enough confirmations? | "Deposit shown, but only 4/15 confirmations" |
Did Bitnob emit a webhook but our system missed it? | "Webhook succeeded but our job failed to process it" |
Did we mark a transfer as completed that actually failed? | "txHash reverted — user was shown success" |
Did a wallet balance change without a matching ledger event? | "Bitnob wallet says +$100 but no known deposit or webhook" |
Core Ledger Rules
Your internal ledger should:
Record every deposit and withdrawal with a reference, txHash, chain, token, wallet_id, timestamp, and source (Bitnob or internal)
Only allow a deposit credit once the deposit.succeeded webhook is received
Only allow a withdrawal debit once Bitnob returns a 200 OK AND emits transfer.completed
Log every webhook in a separate webhook_event_log table for traceability
Support reconciliation diffs, i.e.,
Daily Reconciliation Job
Inputs:
Bitnob wallet balances per chain/token (GET /wallets)
Your internal ledger balance per wallet/chain/token
Known incoming deposits (confirmed txs)
Known outgoing transfers with final status
What to Compare:
Check | What to Do if Mismatch |
---|---|
Wallet balances Bitnob vs internal ledger | Log discrepancy, investigate missing tx |
Deposit webhooks missing in ledger | Backfill ledger from webhook_event_log |
Transfers marked successful but failed | Reverse ledger entry and notify support |
Transfers initiated but not confirmed | Wait or mark as stuck and escalate |
Orphaned on-chain tx (no wallet mapping) | Create holding wallet + assign manually |
All mismatches should be grouped into “Pending Investigation”, “Resolved”, or “False Positive” buckets.
Reconciliation Alerts (for Ops/Finance)
Trigger alerts for:
Discrepancy ≥ threshold ($1 or 0.5%)
Stuck transfer in pending > 30 mins
Webhook not processed after 3 retries
Daily ledger delta ≠ expected net movement
Dashboard suggestion:
Wallet ID | Token | Bitnob Balance | Internal Ledger | Diff | Status |
---|---|---|---|---|---|
X123 | USDT | $10,000.00 | $9,800.00 | -200 | Underinvestigation |
Handling Missed Webhooks
Bitnob guarantees at-least-once delivery. But your app must:
Deduplicate based on event + txHash
Log every received event and its process result
Provide a retry mechanism (manual or automated) for:
deposit.succeeded
transfer.completed
transfer.failed
Missed webhooks are often the root cause of ledger mismatch.
Handling Partial Confirmations
Don’t credit a customer unless:
deposit.succeeded webhook was received OR: You poll a txHash and see it has ≥ required confirmations for the chain
Chain | Minimum Confirmations |
---|---|
Ethereum | 15 |
BSC | 15 |
Polygon | 15 |
Tron | 19 |
Solana | 1 |
TON | 3+ (chain-specific) |
Internal Recovery Tools
Replay webhook by reference or txHash
Ledger explorer: filter by wallet, token, chain, date, discrepancy
Manual credit/debit override UI (restricted access)
Webhook ingestion log with status (success, retrying, dead-letter)
Export CSV for finance audits
Weekly Ops Checklist
Task | Status |
---|---|
Ledger balances reconcile with Bitnob | ✅/❌ |
All deposit.succeeded events processed | ✅/❌ |
All transfer.completed match ledger | ✅/❌ |
No stuck pending transfers | ✅/❌ |
Alert review + false positives tagged | ✅/❌ |
Golden Rules for Integrity
Webhook-driven, not API-poll-driven . Only use polling as a failsafe.
Ledger is your truth, not the UI . Don’t show a transaction as completed unless it is reconciled.
Every Bitnob event must map to one and only one ledger action.
Your system should fail loudly . Never silently skip a webhook or write to ledger without audit.