# Reconcile transactions

Source: https://fragment.dev/guides/reconcile-payments

[Documentation index](https://fragment.dev/llms.txt)

<a id="reconcile-payments"></a>

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

<a id="linked-ledger-accounts"></a>

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

<a id="reconcile-a-tx"></a>

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

<a id="reconciling-multiple-txs"></a>

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

<a id="unreconciled-txs"></a>

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