Key takeaways
- A blockchain event confirms movement between addresses; it does not decide whether a customer balance should change.
- Deposits need validation logic – matching the transaction status event against a separate vault balance update event – before crediting.
- Withdrawals should place a hold, not a permanent debit, until the network result is final.
- Custody providers handle vaults, addresses, signing and execution. Accounts, fees, limits, ledger entries and exception handling stay with the platform.
Five different things that all look like “a transaction”
Five records are frequently conflated:
- A blockchain transaction – an entry in a distributed ledger showing value moving between addresses, with a confirmation depth.
- A custody provider transaction status – the provider’s view of that transaction, enriched with its own status, substatus, screening result and internal identifiers.
- A customer account – the product-level entity a person or business sees, denominated in an asset.
- An internal ledger balance – the double-entry record of what that customer is entitled to, including available and held amounts.
- A business transaction status – the lifecycle of the deposit or withdrawal inside the FinTech platform: pending, processed, rejected, limited, failed.
The other four do not update automatically when the first one changes. Deciding when and how each transition happens is the design work.
What digital asset infrastructure for deposits and withdrawals includes
A production setup usually spans six layers, each with a distinct failure mode.
| Layer | Responsibility | What breaks when it is thin |
|---|---|---|
| Customer application | Account opening, deposit address display, withdrawal requests, status visibility | Customers resend funds or raise tickets because status is ambiguous |
| Account and transaction layer | Customer accounts, contracts, permissions, fees, limits, business transaction status | Balances change without an authorised, fee-aware workflow behind them |
| Internal ledger | Double-entry records, available and held balances, audit history | Balances cannot be explained or reconstructed after an incident |
| Event processing | Webhook receipt, signature verification, idempotency, ordering, replay | Duplicate credits, lost deposits, out-of-order state transitions |
| Custody and wallet provider | Vault accounts, asset wallets, address generation, signing, on-chain execution, policies | Key handling and execution risk sit inside a product not built for it |
| Treasury and operations | Consolidation, liquidity for outgoing transfers, sweeping, supervisor actions | Withdrawals stall on liquidity with no controlled way to resolve them |
The custody layer executes on-chain activity and reports what happened; the FinTech platform holds the customer-facing financial records and the workflows around them.

Why a custody API is not enough
A typical custody provider handles vault and wallet provisioning, address generation, transaction signing, on-chain execution, transaction and balance events, and configurable transaction policies. Key material and signing remain inside the provider’s environment rather than the FinTech platform’s.
None of that answers the questions a financial product has to answer.
The platform still needs customer accounts and the contracts governing them, available and held balances that behave correctly under concurrent operations, fee calculation and posting, and per-customer and per-asset limits.
It also needs double-entry ledger entries for every movement, a business transaction status with defined states, supervisor operations for exceptions, and an audit history explaining why each balance is what it is.
This separation is fundamental to digital asset infrastructure for FinTech products. It is also the practical reason a crypto product needs an internal ledger rather than treating custody balances as the source of truth. A vault balance tells you what the organisation holds on-chain in that vault.
It does not tell you which customer is entitled to which portion of it, what fees have been charged, what is held against a pending withdrawal, or what a customer ledger balance was at a given point in the past. The same real-time ledger software requirements that apply to fiat accounts apply to digital assets – with the added complication that the external record is a public network the platform does not control.
How crypto accounts and deposit addresses are structured
Address structure determines how deposits are attributed, whether sweeping is needed and how gas is funded.
- Shared or omnibus structures. Deposit addresses are generated inside one shared vault, so funds arrive already consolidated and no internal transfer is required afterwards.
- Per-customer vault structures. Each customer receives a dedicated vault account, with a separate wallet for each asset inside it. Attribution is more explicit, but the structure creates additional treasury and gas-management requirements, since deposits land in many places and need consolidating afterwards.
- Chain architecture influences the choice. UTXO-based assets such as Bitcoin and account-based assets such as Ethereum and its tokens behave differently enough that a single structure rarely suits both. Tag/Memo-based assets may use a shared address together with an additional customer-specific identifier; the exact provisioning and attribution flow depends on the supported asset and provider configuration.
How that resolves in practice is a property of the chosen provider. In the current SDK.finance integration with Fireblocks, UTXO-based assets use deposit addresses inside a shared Treasury Vault, while account-based assets use per-customer vault accounts and asset wallets. Other custody providers may support different wallet structures.
- Customer-to-address mapping is the control that ties the two worlds together. When a deposit event arrives, the destination address or identifier is what determines the account to credit.
If that mapping is wrong, incomplete, or reused across customers, a technically valid deposit reaches the wrong balance. Address records should be created with the account, stored against the customer reference, and not reassigned afterwards.
The exact wallet structure, event model and transaction statuses depend on the selected custody provider.
The Fireblocks examples below reflect the current SDK.finance integration.
How a production crypto deposit flow works
A workable deposit sequence:
- The customer opens an account in a supported asset.
- The platform requests a deposit address, or retrieves the existing one, from the custody provider.
- The address is linked to the customer account, with the internal customer reference also stored on the provider side.
- The customer sends assets from an external wallet.
- The custody provider detects the incoming transaction on-chain.
- The platform receives a transaction-created event from the custody provider and identifies the account by destination address.
- A deposit workflow is created with a pending business transaction status, the provider’s transaction identifier is stored as the external reference, and the commission is calculated.
- The platform waits for the transaction to reach the required confirmation and status, including any screening the provider applies.
- The completed transaction status is cross-checked against a separate vault balance update event for the same block.
- The fee is applied.
- The internal ledger credits the customer account and the deposit is marked processed.
- Where the asset structure requires it, consolidation into treasury begins.
The risks worth designing against are predictable: webhooks delivered more than once, events arriving out of order, confirmations delayed well beyond expectation, an expected vault balance update event that never arrives, an address mapped to the wrong account, and repeated crediting of the same customer where steps 6 and 9 are not idempotent.
Why deposit validation matters
A completed transaction status event, taken alone, is a weaker signal than it appears. It states that the custody provider considers the transaction final. It does not on its own confirm that the destination vault balance changed by the expected amount.
Crediting balances from any well-formed event creates replay risk and accounting-integrity risk: the same event, redelivered or reprocessed, can produce a second credit that the internal ledger has no way to distinguish from a genuine one.
Three controls address most of this:
- Signature verification and idempotency. Verify the cryptographic signature of every incoming event against the provider’s published key set, and make processing idempotent on the provider’s transaction identifier so replays cannot produce a second credit.
- Cross-checking status against balance. Treat the credit decision as requiring agreement between two events rather than one. The completed transaction status is cross-checked against a separate vault balance update event with the same block height and block hash.
Both events come from the custody provider, so this is a consistency check rather than independent confirmation of the blockchain itself: the provider’s view of the transaction and its view of the vault balance have to agree before a customer ledger balance changes.
In the SDK.finance integration with Fireblocks, which consumes Fireblocks Webhooks v2, a COMPLETED / CONFIRMED transaction is matched against a stored vault_account.asset.balance_updated event before the customer account is credited. Because either event can arrive first, both paths look for a counterpart before the ledger is touched.
- An explicit unvalidated state. When the counterpart event does not arrive, the deposit should stop in a distinct business transaction status — not silently succeed and not silently disappear. In the integration above, that state is
not_validated, and the customer account is not credited. An administrator can trigger automatic revalidation, which searches events already received for a match, and if none is found can mark the deposit validated on the basis of external verification, with the action recorded for audit.
How a controlled crypto withdrawal flow works
Withdrawals carry more risk than deposits because the platform initiates an irreversible transfer of customer funds. A controlled flow separates request validation, balance reservation, provider-side execution and final ledger posting. The diagram shows how SDK.finance orchestrates the financial workflow while Fireblocks creates, signs and executes the on-chain transaction.
Crypto withdrawal flow step by step
- The customer submits the asset, amount and destination address. The SDK.finance Fireblocks flow supports a user-provided one-time destination address.
- The platform validates account status, contract permissions and internal limits. Failures here are rejected before any provider call.
- The applicable fee is calculated.
- The platform checks that the available balance covers the withdrawal and applicable fees.
- The platform creates the required authorisation posting to reserve the funds used by the withdrawal workflow, moving them from available to held without removing them from the customer’s balance.
- The requested amount is compared against a configured safe withdrawal limit for the asset.
- Liquidity in the withdrawal vault is checked before submission.
- The custody provider creates and signs the on-chain transaction, applying its own policies — applying the configured Fireblocks policies and any connected screening, risk-scoring, whitelisting and transaction authorisation controls.
- Transaction status events are received as the transaction progresses; non-final statuses trigger no ledger action.
- On a successful final status, the reserved amount is captured and the customer account is debited.
- On a terminal failure, the reservation is released and the business transaction status is set to failed.
The reason for the reserve-then-capture pattern is worth stating plainly. If the ledger debits permanently at submission, a failed or cancelled on-chain transaction leaves the customer short until someone notices and posts a correction — an operational credit that is harder to explain in an audit than a released reservation.
If the ledger does nothing at submission, the same available balance can fund a second withdrawal before the first settles.
When either the safe withdrawal limit or the liquidity check fails, the useful outcome is not a rejection. It is a distinct limited business transaction status where the reservation is retained and no provider transaction is created, leaving an operator to process or cancel it deliberately.
Managing failed, delayed and ambiguous transactions
Much of the operational effort in crypto processing goes into states that are neither success nor clean failure. The scenarios recur across products:
- A deposit reached a completed transaction status but was never validated, because the expected vault balance update event did not arrive.
- A final webhook was not received at all, leaving the business transaction status stuck at pending.
- A withdrawal sits in pending and it is unclear whether the provider ever received the request.
- The original API call did not reach the provider, so no transaction exists on the provider’s side.
- A withdrawal exceeded the configured safe limit.
- The withdrawal vault held insufficient liquidity at submission time.
Each needs a defined operator action rather than a database edit.
For deposits, that means automatic revalidation against events already received, and manual validation on the basis of external verification where no matching event is found.
For withdrawals, it means manual finalisation — an operator confirms the real outcome externally and the platform either captures or releases the reserved funds — plus resending a pending withdrawal when external checks confirm no provider-side transaction exists, and processing or cancelling a withdrawal stopped by a limit, with the reservation captured or released to match.
Two conditions make these safe. Resending is only appropriate where there is no indication the transaction already executed, since the failure mode is a duplicate transfer. And every manual intervention should be flagged as such in the transaction record.
This is the crypto equivalent of the discipline described in real-time payment reconciliation: differences between an external record and an internal record are found and resolved through a defined process rather than an ad hoc correction.
Omnibus wallets and automated treasury sweeping
Leaving deposits spread across per-customer vaults means outgoing transfers have to be assembled from many sources, gas has to be present in many places, and treasury has limited view of what it holds. Consolidation into a treasury vault addresses this.
The structural distinction is between user vaults, which attribute incoming deposits, and a treasury vault, which holds consolidated assets. A separate withdrawal vault commonly funds outgoing transactions, which keeps the source of outbound movement explicit and limits how much is exposed to automated withdrawal.
Sweeping is the automated transfer from user vaults into treasury after a deposit is validated. It applies where deposits land in per-customer vaults.
In the current SDK.finance integration with Fireblocks, that means account-based assets. UTXO-based assets need no sweeping there, because their deposit addresses already sit inside the Treasury Vault. Under a different provider or wallet structure, the split may fall elsewhere.
Two details matter for account-based assets.
- The first is gas funding: a sweep is itself an on-chain transaction, so the source vault needs a fee balance before it can execute. Fireblocks sweeping for account-based assets uses AutoFuel on the vault account for this.
- The second is timing. A configurable per-asset timeout allows the platform to delay sweeping after deposit validation, providing additional time for the account and fee-funding conditions required by the transfer.
The customer’s deposit status and the sweeping status should be tracked separately. Sweeping is a treasury operation between accounts the organisation controls. A failed sweep is an internal issue to retry; it does not change the fact that the deposit was validated and credited, and the deposit should remain processed.
Connecting a custody provider with accounts and ledger infrastructure

A concrete split of responsibilities makes the architecture easier to evaluate. Using Fireblocks as the custody example alongside SDK.finance as the account, ledger and transaction layer:
| Fireblocks | SDK.finance |
|---|---|
| Vault accounts | Customer accounts and contracts |
| Asset wallets | Internal available and held balances |
| Blockchain address generation | Deposit address-to-account mapping |
| Transaction signing | Fee calculation and posting |
| On-chain execution | Balance reservations and captures |
| Transaction and balance events | Safe withdrawal limits and liquidity checks |
| Screening and transaction policies | Deposit and withdrawal business workflows |
| Custody of key material | Ledger records and audit history |
| — | Exception handling and supervisor operations |
- The custody provider answers “did this move on-chain, and was it allowed to?”
- The platform answers “whose money is this, what did it cost, what is it committed to, and can that be explained six months from now?”
A separate article covers how SDK.finance and Fireblocks work together in more detail.
What to evaluate before implementing
| Area | What to establish before building |
|---|---|
| Custody model | Who holds keys, under what policy, with what recovery |
| Supported assets | Which specific assets and networks, not “crypto” in general |
| Wallet structure | Omnibus, per-customer, or mixed by chain type |
| Address mapping | How addresses and tags map to accounts, and how reuse is prevented |
| Webhook security | Signature verification, endpoint exposure, replay handling |
| Idempotency | Which identifier deduplicates processing, at which layer |
| Confirmation rules | What status and depth is required per asset before crediting |
| Internal ledger | Double-entry records, held versus available balances, history |
| Fees | Where fees are configured and posted, and what happens when a fee is left unset—an unconfigured fee can prevent an operation from completing, so set fees explicitly to zero where none apply |
| Limits | Safe withdrawal limits, per-contract limits, who can override |
| Treasury liquidity | How withdrawal-vault funding is monitored and replenished |
| Sweeping | Which assets sweep, gas funding, timing, failure handling |
| Recovery | The full list of supervisor actions and who is authorised to use them |
| Auditability | Whether every balance change traces to an event or a named operator |
| Sandbox testing | Whether the full deposit and withdrawal lifecycle, including failures, can be rehearsed |
Conclusion
Production crypto deposits and withdrawals are not merely a wallet feature. They are part of a broader digital asset infrastructure that coordinates six components with different failure modes: custody infrastructure, blockchain events, customer accounts, an internal ledger, business workflows and treasury controls.
The critical design decisions are when a customer account is credited, what happens when an expected event does not arrive, whether a withdrawal reserves funds or debits them outright, who can intervene, and what record that intervention leaves.
SDK.finance provides software and infrastructure for modern FinTech and payment products:
- customer accounts,
- available and held balances,
- internal ledger records,
- fees & limits,
- deposit and withdrawal workflows,
- exception handling and operational controls.
It is designed to sit alongside a custody provider rather than replace one. Its software for crypto and digital asset companies applies the same account and ledger model to digital assets as to fiat balances.
Ready to connect custody infrastructure with your FinTech product?
Explore how the SDK.finance integration with Fireblocks connects digital asset custody infrastructure with customer accounts, ledger records and controlled transaction workflows.
Everything you need to launch crypto wallets, payments, and custody
Learn more
