# 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.