F Reconcile payments#

Your Ledger should track payments made by your product. To do this, you need to represent every account you hold at external financial systems in your Ledger.

.

This section covers the second of two steps to record payments in your Ledger:

  1. Sync payments from external financial systems into FRAGMENT using Links.
  2. Once synced, you can record them in your Ledger using reconcileTx.

a. Linked Ledger Accounts

#

To represent external accounts in your Ledger, create a Ledger Account and link it to an External Account.

Any Ledger Line that posts to a linked Ledger Account must match a synced transaction in its corresponding External Account.

To link a Ledger Account to an External Account, set linkedAccount on a Ledger Account in your Schema:

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:

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:

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.

b. 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:

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:

reconcileTx mutation
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:

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

c. Reconciling multiple Txs

#

Book transfers are a common type of money movement which produce two Txs at your bank as part of one payment.

To reconcile multiple Txs using reconcileTx:

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.

d. Unreconciled Txs

#

Transactions synced to FRAGMENT but not reconciled to a Ledger are considered unreconciled.

You can query unreconciled transactions in a linked Ledger Account using the unreconciledTxs field on theLedgerAccount.

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.

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.