All payments flowing in and out of your financial systems must align with the balances shown in your product. For correct balances, update your ledger for every event in your product workflow and payments processor.
Payment workflows occur in two phases, each with one or more steps:
As a payment processes, you'll post to account combinations representing each step:
For complex payments, each additional step in either the initiation or settlement phase requires an additional clearing account and Ledger Entry type in your Schema.
Most payment settlements are single purpose and result in a single set of balance updates in your ledger. It's common to skip the initiation phase when receiving these payments. This happens when your counterparty initiates the payment and you don't know a payment is in-flight until it settles at your bank account.
Add a cash account:
asset Ledger Account with the linked flag setAdd a "reconcile_payment" Ledger Entry type to your Schema that posts to:
When you receive a payment:
reconcileTx to post the "reconcile_payment" Ledger Entry to reconcile the transaction.To automate this process, you'll need to correlate each payment to a product workflow, like which user topped up or which invoice was paid. You can use a trace ID from the payment sender, transaction descriptions or single-purpose payment routes, like VBANs or virtual card numbers, to determine the correct Ledger Entry Type to post and its parameters.
If you receive a payment that settles multiple product workflows, you'll need to split the payment using a clearing account. This account holds funds during the splitting process and ensures all splits add up to the received amount.
Add a cash account:
asset Ledger Account with the linked flag setAdd a clearing account:
liability Ledger Account with the clearing and template flags setAdd a "received_bulk_payment" Ledger Entry type that posts to:
A "split_bulk_payment" Ledger Entry type that posts to:
When you receive a bulk payment:
reconcileTx to post a "received_bulk_payment" Ledger Entry against the synced transaction. This reconciles the transaction and creates a pending clearing account.addLedgerEntry to post a "split_bulk_payment" Ledger Entry per item in the payment. Once this process is completed, the clearing account is "cleared".Some bulk settlements are batches of batches. For example with network-level card ledgering, you receive multiple "clearings" per day and a settlement once a day. Each day, you'll receive one settlement file, that breaks down the total payment per clearing, and multiple clearing files that break down each "clearing" into individual card transactions.
In this case, you'll have a three step settlement phase:
Sending a payment that has a single purpose requires two phases: initiation and settlement.
Add a cash account:
asset Ledger Account with the linked flag setAdd a clearing account:
liability Ledger Account with the clearing and template flags setAdd an "initiate_payment" Ledger Entry type that posts to:
Add a "settle_payment" Ledger Entry type that posts to:
When sending a payment:
addLedgerEntry to post the "initiate_payment" Ledger Entry. This creates a pending clearing account and updates your product balances.reconcileTx to post the "settle_payment" Ledger Entry. This reconciles the transaction and clears the pending payment.If a payment is cancelled after initiation but before settlement, you can either reverse the initiation entry or post a new entry with opposite amounts.
If a payment reverses after settlement, the bank or payment processor creates a reversal transaction. Sync this transaction and reconcile it with a Ledger Entry that posts opposite amounts to the original settlement.
If you initiate multiple payments that you batch into a single settlement, you'll need two clearing accounts. The first tracks individual payments. The second tracks the batch once initiated.
Add a cash account:
asset Ledger Account with the linked flag setAdd a pending initiation clearing account:
liability Ledger Account with the clearing and template flags setAdd a pending settlement clearing account:
liability Ledger Account with the clearing and template flags setAdd a "initiate_payment" Ledger Entry type that posts to:
Add a "prepare_batch" Ledger Entry type that posts to:
Add a "settle_batch" Ledger Entry type that posts to:
When sending a bulk payment:
addLedgerEntry to post a "initiate_payment" Ledger Entry for each payment. This creates pending clearing accounts and updates your product balances.addLedgerEntry to post a "prepare_batch" Ledger Entry. This clears the individual payment clearing accounts and creates a batch clearing account.reconcileTx to post the "settle_batch" Ledger Entry. This reconciles the transaction and clears the batch clearing account.If a payment is cancelled before joining a batch, reverse the "initiate_payment" entry or post a new entry with opposite amounts.
If a payment is cancelled after joining a batch but before settlement, reverse both the "initiate_payment" and "prepare_batch" entries, or post new entries with opposite amounts.
If a batch reverses after settlement, the bank or payment processor will create a reversal transaction. Sync this transaction and reconcile it with a Ledger Entry that posts opposite amounts to the original settlement. You'll also need to reverse the "initiate_payment" entries so that the payment clearing accounts are pending again.
You can monitor pending payments in two ways:
Transactions synced from a Link but not yet reconciled to a Ledger Entry represent payments you've received but haven't recorded in your ledger.
Use the unreconciledTxs field to find these payments:
query UnreconciledPayments {
ledgerAccount(
ledgerAccount: {
path: "assets/operating"
ledger: { ik: "ledger_123" }
}
) {
unreconciledTxs {
nodes {
id
description
amount
externalId
}
}
}
}See Integrate a bank for more details.
Clearing accounts represent temporary states in payment flows. FRAGMENT tracks the status of each clearing account to help you monitor payments waiting for the next step in a workflow.
Each clearing account has a clearingStatus field that indicates whether the account has a pending balance:
pending: The account has a non-zero balance. The payment is waiting for the next step in the workflow.cleared: The account has a zero balance. The payment workflow is complete.For multi-currency clearing accounts, the status is pending if any currency has a non-zero balance. Once you deploy a Ledger, the clearing property on a Ledger Account is immutable.
Use the clearingStatus filter to find pending payments:
query PendingPayments {
ledger(ledger: { ik: "ledger_123" }) {
ledgerAccounts(
filter: {
clearingStatus: { equalTo: pending }
}
) {
nodes {
path
clearingStatus
ownBalance
}
}
}
}Combine the clearingStatus filter with a path filter to find pending payments for a specific workflow. For non-template clearing accounts, use an exact path match:
query PendingBulkReceivables {
ledger(ledger: { ik: "ledger_123" }) {
ledgerAccounts(
filter: {
clearingStatus: { equalTo: pending }
path: { matches: "liabilities/bulk_receivables" }
}
) {
nodes {
path
clearingStatus
ownBalance
}
}
}
}For template clearing accounts, use a wildcard in the path:
query PendingWithdrawals {
ledger(ledger: { ik: "ledger_123" }) {
ledgerAccounts(
filter: {
clearingStatus: { equalTo: pending }
path: { matches: "liabilities/pending_withdrawals:*" }
}
) {
nodes {
path
clearingStatus
ownBalance
}
}
}
}The clearingStatus filter only accepts the path filter as an additional filter. Other filters will return an error.