H Read balances#

FRAGMENT supports querying a Ledger Account for its latest balances, historical balances and balance changes.

a. Latest

#

Use the ledgerAccount query to look up a Ledger Account's balance.

GetBalances query
query GetBalance(
  $ledgerAccount: LedgerAccountMatchInput!
) {
  ledgerAccount(ledgerAccount: $ledgerAccount) {
    balance
  }
}
GetBalances variables
{
  "ledgerAccount": {
    "path": "assets/banks/user-cash",
    "ledger": {
      "ik": "quickstart-ledger"
    }
  }
}

b. Aggregated

#

Ledger Accounts have three balances:

  • ownBalance is the sum of all Ledger Lines posted to the Ledger Account, excluding Ledger Lines in child Ledger Accounts
  • childBalance is the sum of all Ledger Lines posted to the children of this Ledger Account
  • balance is the sum of all Ledger Lines posted to this Ledger Account and its children
GetAggregatedBalances query
query GetAggregatedBalances(
  $ledgerAccount: LedgerAccountMatchInput!
) {
  ledgerAccount(ledgerAccount: $ledgerAccount) {
    childBalance
    balance
  }
}
GetAggregatedBalances variables
{
  "ledgerAccount": {
    "path": "liabilities/users"
  }
}

c. Consistent

#

Balance reads are eventually consistent by default. This means that the balance may not reflect all the Ledger Lines in the account.

To read a strongly consistent balance, a Ledger Account must have its balances updated in a strongly consistent manner. This is set in the Schema on a Ledger Account's consistencyConfig:

Strongly consistent Ledger Accounts
{
  "key": "strongly-consistent-ledger-accounts",
  "name": "Strongly consistent Ledger Accounts",
  "chartOfAccounts": {
    "defaultCurrency": { "code": "USD" },
    "accounts": [
      {
        "key": "liabilities",
        "type": "liability",
        "children": [
          {
            "key": "users",
            "template": true,
            "consistencyConfig": {
              "ownBalanceUpdates": "strong"
            },
            "children": [
              {
                "key": "available",
                "consistencyConfig": {
                  "ownBalanceUpdates": "strong"
                }
              },
              {
                "key": "pending"
              },
              {
                "key": "blocked"
              }
            ]
          }
        ]
      }
    ]
  }
}
 

Once a Ledger Account's balance is updated consistently, set the consistencyMode on balance queries to determine the consistency of the read you issue.

Strongly consistent ownBalance read
query GetStronglyConsistentBalance(
    $ledgerAccount: LedgerAccountMatchInput!
) {
  ledgerAccount(ledgerAccount: $ledgerAccount) {
    ownBalance(consistencyMode: strong)
  }
}

consistencyMode can be set to:

  • strong to perform a strongly consistent balance read
  • eventual to perform an eventually consistent balance read
  • use_account to use the value of consistencyConfig.ownBalanceUpdates when performing a balance read
Strongly consistent ownBalance read variables
{
  "ledgerAccount": {
    "path": "liabilities/users:user-1/available",
    "ledger": {
      "ik": "quickstart-ledger"
    }
  }
}

Only ownBalance can be queried with consistencyMode: strong.

Read the Configure consistency section to learn more about FRAGMENT's consistency semantics and Ledger Account consistency modes.

d. Historical

#

To query the balance of a Ledger Account at a particular point in time use the at argument:

Balance queries
query GetHistoricalBalances(
  $ledgerAccount: LedgerAccountMatchInput!
) {
  ledgerAccount(ledgerAccount: $ledgerAccount) {
    end_of_year: balance(at: "1969")
    end_of_month: balance(at: "1969-07")
    end_of_day: balance(at: "1969-07-21")
    end_of_hour: balance(at: "1969-07-21T02")
  }
}

If you don't specify at, you'll get the latest balance. at is supported for all balances and works granularly to the hour.

e. Balance changes

#

You can also query the net change on a Ledger Account over a specific reporting period. This can be useful for generating financial statements.

Similar to balances, there are three types of balance changes:

  • ownBalanceChange, how much ownBalance changed
  • childBalanceChange, how much childBalance changed
  • balanceChange, how much balance changed

Balance change queries require you to specify a period. This can be a year, quarter, month, day or hour.

Balance change queries
query GetBalanceChanges(
  $ledgerAccount: LedgerAccountMatchInput!
) {
  ledgerAccount(ledgerAccount: $ledgerAccount) {
    ownBalanceChange(period: "1969")
    childBalanceChange(period: "1969")
    balanceChange(period: "1969")
    currentYear: balanceChange(period: "1969")
    lastYear: balanceChange(period: "1968")
    lastYearQ4: balanceChange(period: "1968-Q4")
    lastYearDecember: balanceChange(period: "1968-12")
    lastYearChristmas: balanceChange(period: "1968-12-25")
    lastYearLastHour: balanceChange(period: "1968-12-31T23")
  }
}

You can also perform multiple balance queries using aliases.

Balance change query variables
{
  "ledgerAccount": {
    "path": "liabilities/users:user-1/available",
    "ledger": {
      "ik": "quickstart-ledger"
    }
  }
}

f. Balance history

#

FRAGMENT provides two queries for tracking balances and balance changes over time: balancesDuring and balanceChangesDuring. You can use them to analyze balance history at different granularities.

  • ownBalancesDuring and ownBalanceChangesDuring for a Ledger Account's own balance
  • childBalancesDuring and childBalanceChangesDuring for a Ledger Account's child balance
  • balancesDuring and balanceChangesDuring for a Ledger Account's total balance

To query a Ledger Account's balances, or balance changes, over a period, you must provide:

  • startTime, a date string in UTC that specifies the first moment of the period
  • duration, the length of the time period. Duration can be either positive or negative. When negative, the response will be balances, or balance changes, for duration period before (not including) startTime
  • granularity, which specifies the unit for duration. Valid values are hourly, daily, or monthly

The granularity must have a finer time resolution than the start time string.

Start TimeExample Start TimeValid Granularity
Year"2021"monthly, daily, hourly
Quarter"2021-Q1"monthly, daily, hourly
Month"2021-01"monthly, daily, hourly
Day"2021-01-01"daily, hourly
Hour"2021-01-01T00"hourly

The maximum absolute value for the duration is granularity dependent. Values outside the ranges defined below will be rejected.

GranularityMaximum DurationTime Period
monthly24020 years
daily7312 years including a leap year
hourly74431 days
Balance history queries
query GetBalanceHistory(
  $ledgerAccount: LedgerAccountMatchInput!
) {
  ledgerAccount(ledgerAccount: $ledgerAccount) {
    # Get monthly balances for a year
    yearlyBalances: balancesDuring(
      startTime: "2021"
      duration: 12
      granularity: monthly
    ) {
      startTime
      endTime
      granularity
      nodes {
        at
        amount {
          currency {
            code
          }
          amount
        }
      }
    }

    # Get daily balances for January 2021
    monthlyBalances: balancesDuring(
      startTime: "2021-01"
      duration: 31
      granularity: daily
    ) {
      startTime
      endTime
      granularity
      nodes {
        at
        amount {
          currency {
            code
          }
          amount
        }
      }
    }

    # Get daily balances changes for the two weeks 
    # before the start of Q4 of 2021
    quarterlyChanges: balanceChangesDuring(
      startTime: "2021-Q4"
      duration: -14
      granularity: daily
    ) {
      startTime
      endTime
      granularity
      nodes {
        period
        amount {
          currency {
            code
          }
          amount
        }
      }
    }

    # Get hourly balanceChanges for the 48 hour 
    # period starting on August 9th, 2024 at 
    # 11:00am UTC
    hourlyChanges: balanceChangesDuring(
      startTime: "2024-08-09T11"
      duration: 48
      granularity: hourly
    ) {
      startTime
      endTime
      granularity
      nodes {
        period
        amount {
          currency {
            code
          }
          amount
        }
      }
    }
  }
}

The format of the response is:

  • startTime: The start of the period being queried as an ISO Time string
  • endTime: The last time in the period being queried as an ISO Time string
  • granularity: The granularity of the data (monthly, daily, or hourly)
  • nodes: an array of either HistoricalBalance or BalanceChangeDuring objects

For multi-currency Ledger Accounts, you must specify the currency you want to query:

Multi-currency balance history
query GetMultiCurrencyBalanceHistory(
  $ledgerAccount: LedgerAccountMatchInput!
) {
  ledgerAccount(ledgerAccount: $ledgerAccount) {
    usdBalances: balancesDuring(
      startTime: "2021"
      duration: 12
      granularity: monthly
      currency: { code: USD }
    ) {
      nodes {
        at
        amount {
          amount
        }
      }
    }
    
    gbpChanges: balanceChangesDuring(
      startTime: "2021"
      duration: 100
      granularity: daily
      currency: { code: GBP }
    ) {
      nodes {
        period
        amount {
          amount
        }
      }
    }
  }
}

g. Multi-currency mode

#

For Ledger Accounts in currencyMode: multi, use the currency argument to query the balance in a specific currency.

Multi-currency balance queries
query GetMultiCurrencyBalances(
  $ledgerAccount: LedgerAccountMatchInput!
) {
  ledgerAccount(ledgerAccount: $ledgerAccount) {
    latestUSDBalance: balance(currency: { code: USD })
    latestGBPBalance: balance(currency: { code: GBP })

    USDBalanceChange:
      balanceChange(period: "1969", currency: { code: USD })
    GBPBalanceChange:
      balanceChange(period: "1969", currency: { code: GBP })
  }
}
Multi-currency balance query variables
{
  "ledgerAccount": {
    "path": "liabilities/users:user-1/available",
    "ledger": {
      "ik": "quickstart-ledger"
    }
  }
}

You can also query balances in all of a multi-currency Ledger Account's currencies, see Handle currencies.

h. Timezone offsets

#

Balance queries respect the Ledger's balanceUTCOffset when specifying periods and times. This field is specified when creating the Ledger.

  • If a Ledger has an offset of -08:00, then querying balance(at: "1969-01-31") returns the balance at midnight PT on that date, or 8am on 1969-02-01 UTC.
  • Querying balanceChange(period: "1969") returns the net change between 8am on 1969-01-01 UTC and 8am on 1969-01-01 UTC. This gives you the net change between midnights local time.
  • Daylight savings is ignored, so every day throughout the year has exactly 24 hours.