Digital Wallets

Companies that hold balances for external users use Ledgers to log transactions and calculate balances automatically.


Technology companies with products that move money often need to hold balances for users or external counterparties. For example, your app might allow users to deposit funds into a wallet from which they can invest, or it might let your vendors accumulate points in a rewards wallet. This is a common use case across fintech, marketplaces, vertical SaaS, and e-commerce. Any time balances are being held, a unified data store is required to keep track of transactions and balances.

Ledgers is such a data store - an immutable financial database that allows companies to hold balances at scale.

Who is this guide for

We assume you are a company interested in spinning up digital wallets as part of your product offering. This guide explains how to use Ledgers as the underlying infrastructure to power such digital wallets, and it is divided in three parts.

  • First, we will create a sample chart of accounts. Accounts are the balances your platform will track (more detail in our guide to ledger objects).
  • Next, we will work through a sample set of transactions. As business events happen in your digital wallet platform, you can use the guidance here to define how to write these transactions in the ledger. Transactions are logged in the ledger with the create ledger transaction endpoint. For sample API calls, review our quickstart guide for digital wallets.
  • Finally, we’ll discuss the use of metadata, transaction timing, account categories, and other features that can be helpful to any company launching a digital wallet.

Step 1. Designing Your Chart of Accounts

Ledgers implements double-entry accounting concepts. This ensures scalable consistency. If you are not familiar with debits and credits, start with our guide to debits and credits. We also recommend reviewing our guide to Ledgers Objects, as it explains ledger accounts, transactions, and categories in detail.

Balances are tracked on Ledgers by way of ledger accounts. Implementing a digital wallet requires the following set of accounts:

  • User balance accounts, which track balances exposed to users;
  • Cash accounts, which track cash positions associated with your digital wallet product;
  • Expense accounts such as fees, which track expenses incurred in your digital wallet product;
  • Revenue accounts which track different revenue streams captured by your digital wallet product;

User Balance Accounts

User balance accounts are credit normal accounts that track user balances. These are credit normal accounts because they represent funds your platform owes - or sources of funds. (For more, read our guide to debits and credits).

Your platform needs one ledger account per user. New accounts can be created using the create ledger account endpoint. Accounts can be enriched with free-form metadata. Here is a sample user balance account:

Account NameNormalityRepresentsIncreased By (Credits)Decreased By (Debits)Sample Metadata
User #1241241 BalanceCredit NormalBalance for user Robert Dylan.User deposits or credits.User withdrawals, fees.accountType: "User Balance", userFirstName: "Bob", userLastName: "Dylan", userState: "NY", userActive: "yes"

Cash Accounts

Cash accounts track different cash positions associated with the digital wallet app. They are debit normal given they represent funds your platform owns.

There are many different cash positions you might want to track in your digital wallet app:

  • Reserve funds that represent cash that needs to be available to users for withdrawals;
  • Operating cash accounts that represent pools of funds you direct income to and deduct expenses from;
  • Any other cash pools tied to operational or regulatory requirements.

Here is a sample cash account:

Account NameNormalityRepresentsIncreased By (Debits)Decreased By (Credits)Sample Metadata
SendCash Operating Cash AccountDebit NormalOverall cash position of SendCash appCash inflows of any kindCash outflows of any kindaccountType: "Cash Omnibus", active: yes

Expense Accounts

Expense accounts track expenses incurred in the regular operation of the digital wallet app. These can be debit normal when they represent expenses paid (as they reflect money outflows in a regular course of business) and credit normal when they represent expenses due (as they reflect payables).

A few types of expense accounts include:

  • Card fees incurred in the event of an account deposit or withdrawal;
  • Any taxes or fees to third parties paid on balances or transfers in the platform;
  • Banking fees associated with specific transactions.

Here is a sample expense account:

Account NameNormalityRepresentsIncreased By (Debits)Decreased By (Credits)Sample Metadata
Credit card fees paidDebit NormalTotal paid in credit card feesNew credit card fees paidTypically not decreased unless in the event of an adjusting entryaccountType: expense
Payable to vendor XCredit NormalBalance due to vendor XNew amounts are recorded as due to vendor XPayoutsaccountType: expense,
vendor: X

We recommend holding payable balances only if necessary and using debit normal expense accounts to tally up expenses incurred whenever possible.

Revenue Accounts

Revenue accounts are counter to expense accounts and represent money inflows categorized as revenue by your digital wallet app. They are always credit normal accounts.

Different revenue accounts can be created to differentiate between revenue streams. Here are a few examples:

Account NameNormalityRepresentsIncreased By (Credits)Decreased By (Debits)Sample Metadata
Revenue from deposit feesCredit NormalRevenue incurred when users deposit funds in the appDepositsTypically ledger adjustmentsaccountType: revenue,
revenueStream: deposit_fees
Revenue from transfer feesCredit NormalRevenue incurred when users transfer funds from each other in the platformUser to user transfersTypically ledger adjustmentsaccountType: revenue,
revenueStream: transfer_fees

Step 2. Defining Transaction Logic

With a set of accounts mapped out, the next step is define transaction logic for your digital wallet app. The table below shows the most common transactions happening in a digital wallet app and how they get recorded on Ledgers.

We will walk through the following flows:

  • Deposit: a user adds money to their digital wallet account;
  • In-app transfer: two users send money to each other;
  • Withdrawal: user takes money out of their balance. In this example we will assume your app charges a 2% fee on withdrawals, which is recognized as revenue;

For a refresher on account normality and how debits and credits work review our guide to debits and credits.

Sample TransactionDebited AccountsCredited AccountsNotes
DepositCash account (increase)User balance account (increase)As a user deposits in their balance, we capture the increase in cash and corresponding increase in the user balance.
In-App TransferSender user balance account (decrease)Receiver user balance account (increase)A transfer from user A to user B will deduct the sender balance and increase the receiver's. There is no actual money movement in this transaction, it's simply a ledger mutation.
WithdrawalUser balance account (decrease)Cash account (decrease);
Revenue from fees (increase)
This is the inverse flow to a deposit, with the exception that 2% of the withdrawal would be recognized as a revenue.

Your application code would handle transactions appropriately write them into the ledger according to the guidance presented above. Our team can help you structure your transaction rules in a way that meets your product requirements and optimizes database performance.

Step 3. Defining metadata, categories, and transaction timing

With your chart of accounts and overall transaction schema mapped out, a few important questions remain.

Ledgers supports free-form metadata in the form of key-value pairs. Common metadata fields seen amongst digital wallet customers include:

ledger accountwalletID; userId; accountType
ledger transactiontransactionType
ledger account categorycategoryType

Ledgers supports querying based on metadata. Any time objects refer to an important concept, it’s helpful to tag them with relevant metadata. By using the list ledger transactions endpoint to query all accounts associated with user wallet #31512, for instance, the system will return all the transactions that modified this account.

As mentioned before, categories are aggregations at the account level. Categories group multiple accounts. The balance in an account category is equal to the sum of the balances of the accounts within it.

A common category for digital wallets is a user balances grouping, which aggregate the overall balance held in user wallets according to a pre-defined criteria. Read more about categories here.

Transaction timing
Ledgers supports multi-state transactions. Transactions in the ledger can have one of the following status values: pending, posted, or archived.

Digital wallet companies might choose to leave transactions at a pending status until a certain condition is met. For instance: a user may execute a deposit in your digital wallet via ACH but you decide to only take the transaction into account once it clears. You can choose to represent these balances as pending until transactions are finalized, at which point they would become posted. Once posted, they are immutable.

Each account will have one of three balances: posted (sum of all posted entries), pending (sum of posted and pending entries), and available (sum of all posted entries minus outgoing pending entries).

Finally, Ledgers supports back and future dating in the form of an effective_date field on the ledger transaction object. This gives you the flexibility to differentiate between posted dates and effective dates for reporting purposes, as well as include future events in the ledger.

Next Steps

Some of the most successful business featuring digital wallets are being built on Ledgers. From here you can:

  • Review our Quickstart Guide for Digital Wallets for sample API calls;
  • Explore other Use Case Guides;