# Reconcile transactions Source: https://fragment.dev/guides/reconcile-payments [Documentation index](https://fragment.dev/llms.txt) Your Ledger should track transactions made by your product. To do this, you need to represent every account you hold at external financial systems in your Ledger. [Visual: reconciliation. View on the HTML page.](https://fragment.dev/guides/reconcile-payments) This section covers the second of two steps to record transactions in your Ledger: 1. [Sync transactions](https://fragment.dev/markdown/guides/sync-payments.md) from external financial systems into Fragment using Links. 2. Once synced, you can record them in your Ledger using [reconcileTx](https://fragment.dev/markdown/guides/reconcile-payments.md#reconcile-a-tx). ## Linked Ledger Accounts To represent external accounts in your Ledger, create a Ledger Account and link it to an External Account. [Visual: linkedLedgerAccount. View on the HTML page.](https://fragment.dev/guides/reconcile-payments) Any Ledger Line that posts to a linked Ledger Account must match a synced transaction in its corresponding External Account. [Visual: reconcilingTransactions. View on the HTML page.](https://fragment.dev/guides/reconcile-payments) To link a Ledger Account to an External Account, set `linkedAccount` on a Ledger Account in your Schema: ```json title="Linked Ledger Account with hardcoded IDs" { "chartOfAccounts": { "accounts": [ { "key": "assets-root", "name": "Assets", "type": "asset", "children": [{ "key": "operating", "name": "Operating Bank", "linkedAccount": { "linkId": "some-link-id", "externalId": "bank-account-1" } }] } ] } } ``` The `linkId` comes from the Link you create in the dashboard. The `externalId` is the ID of the account at your external financial system. The CLI automatically replaces variables with `${ENV_VAR}` syntax when running `fragment store-schema`. This lets you use different External Accounts per environment: ```json title="Linked Ledger Account with env var IDs" { "chartOfAccounts": { "accounts": [ { "key": "assets-root", "name": "Assets", "type": "asset", "children": [{ "key": "operating", "name": "Operating Bank", "linkedAccount": { "linkId": "${BANK_LINK_ID}", "externalId": "${BANK_ACCOUNT_ID}" } }] } ] } } ``` To link a Ledger Account template to an External Account, parameterize the `linkedAccount` field: ```json title="Linked Ledger Account with parameter IDs" { "chartOfAccounts": { "accounts": [ { "key": "assets-root", "name": "Assets", "type": "asset", "children": [{ "key": "operating", "name": "Operating Bank", "template": true, "linkedAccount": { "linkId": "{{BANK_LINK_ID}}", "externalId": "{{BANK_ACCOUNT_ID}}" } }] } ] } } ``` These parameters will be required when posting a Ledger Entry to a linked Ledger Account. This can be useful if you're creating bank accounts per customer, for example. ## Reconcile a Tx To reconcile a transaction from an external system, follow the same two-step process as when posting Ledger Entries: 1. Define the structure of the Ledger Entry in your Schema. 2. Post the Ledger Entry using the API. Ledger Entries posting to a linked Ledger Account must specify the Tx from the External Account tied to the Ledger Account. This lets Fragment know which transaction to reconcile: ```json title="LedgerEntrySchema with Linked Ledger Account" { "key": "schema-key", "chartOfAccounts": {...}, "ledgerEntries": { "types": [ { "type": "user_funds_account_via_link", "description": "Funding {{user_id}} for {{funding_amount}}", "lines": [ { "account": { "path": "assets/operating" }, "key": "funds_arrive_in_bank", "tx": { "externalId": "{{bank_transaction_id}}" } }, { "account": { "path": "liabilities/users:{{user_id}}/available" }, "key": "increase_user_balance" } ] } ] } } ``` Notes: - Ledger Lines posting to a linked Ledger Account must match 1:1 with the Tx that's being reconciled. - `bank_transaction_id` represents the ID of the transaction at the external system. Instead of calling `addLedgerEntry`, use the `reconcileTx` mutation: ```graphql title="reconcileTx mutation" expandable mutation ReconcileTx( $entry: LedgerEntryInput! ) { reconcileTx( entry: $entry ) { ... on ReconcileTxResult { entry { type created posted } lines { amount key description account { path } } } ... on Error { code message } } } ``` The parameters look similar to `addLedgerEntry`. Specify the Ledger Entry `type` that you are using and provide the `parameters` defined in the Schema: ```json title="reconcileTx variables" { "entry": { "type": "user_funding", "ledger": { "ik": "quickstart-ledger" }, "parameters": { "txId": "tx_12345", "customerId": "customer-1" } } } ``` `ik` and `posted` are optional when posting Ledger Entries with `reconcileTx`: - `ik`: the `Tx.externalId` is used to ensure that reconciling a transaction is idempotent - `posted`: the timestamp of the Ledger Entry is taken from the Tx to ensure the Ledger mirrors the external system ## Reconciling multiple Txs Book transfers are a common type of money movement which produce two Txs at your bank as part of one transaction. To reconcile multiple Txs using `reconcileTx`: ```json title="LedgerEntrySchema with multiple Txs" { "key": "schema-key", "chartOfAccounts": {...}, "ledgerEntries": { "types": [ { "type": "user_funds_account_via_link", "description": "Funding {{user_id}} for {{funding_amount}}", "lines": [ { "key": "funds_arrive_in_operating_bank", "account": { "path": "assets/operating-bank-account" }, "tx": { "externalId": "{{bank_transaction_id}}" } }, { "key": "funds_leave_holding_bank", "account": { "path": "assets/holding-bank-account" }, "tx": { "externalId": "{{bank_transaction_id}}" } } ] } ] } } ``` Notes: - Reconciling multiple Txs is only permitted if they have the same `posted` timestamp. - You can only reconcile multiple Txs within the same Link. ## Unreconciled Txs Transactions synced to Fragment but not reconciled to a Ledger are considered unreconciled. [Visual: unreconciledTxs. View on the HTML page.](https://fragment.dev/guides/reconcile-payments) You can query unreconciled transactions in a linked Ledger Account using the `unreconciledTxs` field on the`LedgerAccount`. ```graphql title="unreconciledTxs query" query GetUnreconciledTxs ( $ledgerAccount: LedgerAccountMatchInput! ) { ledgerAccount(ledgerAccount: $ledgerAccount) { id unreconciledTxs { nodes { id description amount externalId externalAccountId } pageInfo { endCursor hasNextPage } } } } ``` The variables specify the `path` of the linked Ledger Account you are querying and the Ledger it belongs to. ```json title="unreconciledTxs variables" { "ledgerAccount": { "path": "assets/operating", "ledger": {...} } } ``` `unreconciledTxs` is eventually consistent, so if you've recently transacted at a Native Link or just synced manually for a Custom Link, you may not see the transaction in the query results immediately.