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:
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:
{
"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:
{
"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:
{
"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.
To reconcile a transaction from an external system, follow the same two-step process as when posting Ledger Entries:
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:
{
"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:
bank_transaction_id represents the ID of the transaction at the external system.Instead of calling addLedgerEntry, use the 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:
{
"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 idempotentposted: the timestamp of the Ledger Entry is taken from the Tx to ensure the Ledger mirrors the external systemBook 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:
{
"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:
posted timestamp.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.
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.
{
"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.