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.