# Query data Source: https://fragment.dev/guides/query-data [Documentation index](https://fragment.dev/llms.txt) You can flexibly query your data to generate financial reports, embed Fragment in your product and build internal dashboards. [Visual: queryData. View on the HTML page.](https://fragment.dev/guides/query-data) ## Basics ### GraphQL Fragment is a GraphQL API, so data in the system is modeled as a graph. Entities in the API are nodes, and their relationships with other entities are edges. Ledgers have Ledger Accounts; Ledger Accounts and Ledger Entries have Ledger Lines; and so on. Fragment exposes several [queries](https://fragment.dev/markdown/api-reference/ledger-queries.md) as entry points to the data graph. They return data about a single entity, or a list of entities. When making a query, you can fetch related entities using expansions. As opposed to a REST interface, where you may require several round-trips to query nested data, expansions are nested queries that you let you retrieve related data in a single request. For example, you can [expand from a Ledger Entry to all the Ledger Lines](https://fragment.dev/markdown/guides/query-data.md#ledger-entries-expand-lines) in it in one API call. ### Connection types Fragment uses [connection types](https://relay.dev/graphql/connections.htm) to return lists of entities. A connection type is a list of nodes, and a `pageInfo` object that contains cursors to the next and previous pages of results. ```graphql title="ListLedgerAccounts" query ListLedgerAccounts($ledger: LedgerMatchInput!) { ledger(ledger: $ledger) { ledgerAccounts { nodes { name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ### Filtering You can filter connection types with a `filter` argument. For example, you can filter a list of Ledger Accounts by their type: ```graphql title="FilterLedgerAccounts query" query FilterLedgerAccounts( $ledger: LedgerMatchInput!, $filter: LedgerAccountsFilterSet! ) { ledger(ledger: $ledger) { ledgerAccounts { nodes { name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="FilterLedgerAccounts variables - by type" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "type": { "equalTo": "asset" } } } ``` You can combine filters by adding multiple components to the filter block. Results are AND'd: ```json title="FilterLedgerAccounts variables - by type" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "type": { "equalTo": "asset", "hasParentLedgerAccount": true } } } ``` ### Pagination Fields that return lists support cursor-based pagination: - Results are returned under a `nodes` property as an array. The `pageInfo` property contains cursors pointing to the next page and previous pages. - You can send a cursor to the `after` (or `before`) arguments on list fields to retrieve a specific page. - The `first` (or `last`) argument sets the page size. The default is 20 and the maximum is 200. - Once a page size has been set in the initial request, all subsequent pagination requests have to use the same page size. - Results are returned in a deterministic order. This is generally reverse chronological, newest first. This sort is by posted date for Ledger Lines and Ledger Entries, or creation date for other entities. This query uses pagination to retrieve two Ledger Accounts at a time: ```graphql title="GetLedgerAccounts query with pagination" query GetLedgerAccounts( $ledgerIk: SafeString! $after: String $first: Int $before: String ) { ledger(ledger: { ik: $ledgerIk }) { ledgerAccounts( after: $after first: $first before: $before ) { nodes { path name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="GetLedgerAccounts variables" { "ledgerIk": "ik-used-to-create-ledger", "first": 2 } ``` The response is: ```json title="GetLedgerAccounts first page response" { "data": { "ledger": { "ledgerAccounts": { "nodes": [ { "path": "assets/test-assets/test:1", "name": "Test 1", "type": "asset" }, { "path": "assets/test-assets/test:2", "name": "Test 2", "type": "asset" } ], "pageInfo": { "hasNextPage": true, "endCursor": "", "hasPreviousPage": false, "startCursor": null } } } } } ``` To retrieve the next page, send the same query but with the `after` parameter set on `ledgerAccounts`: ```json title="GetLedgerAccounts next page variables" { "ledgerIk": "ik-used-to-create-ledger", "after": "" } ``` The response is: ```json title="GetLedgerAccounts second page response" { "data": { "ledger": { "ledgerAccounts": { "nodes": [ { "path": "assets/test-assets/test:3", "name": "Test 3", "type": "asset" }, { "path": "assets/test-assets/test:4", "name": "Test 4", "type": "asset" } ], "pageInfo": { "hasNextPage": false, "endCursor": null, "hasPreviousPage": true, "startCursor": "" } } } } } ``` To retrieve the previous page of results, send the same query but with the `before` parameter set on `ledgerAccounts`. The response is the first page of results. ```json title="GetLedgerAccounts previous page variables" { "ledgerIk": "ik-used-to-create-ledger", "before": "" } ``` ## Ledgers ### Lookup Use the `ledger` query to retrieve a Ledger by the IK used to create it: ```graphql title="GetLedger" query GetLedger($ledger: LedgerMatchInput!) { ledger(ledger: $ledger) { name created balanceUTCOffset ledgerAccounts { nodes { name type } } schema { key } } } ``` ```json title="GetLedger variables" { "ledger": { "ik": "quickstart-ledger" } } ``` ### List Use the `ledgers` query to list all the Ledgers in your workspace: ```graphql title="ListLedgers" query ListLedgers { ledgers { nodes { name created balanceUTCOffset ledgerAccounts { nodes { name type } } schema { key } } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } ``` The response is a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of Ledgers. ## Ledger Accounts ### Lookup Use the `ledgerAccount` query to retrieve a Ledger Account by its path in the Schema: ```graphql title="GetLedgerAccount" query GetLedgerAccount( $ledgerAccount: LedgerAccountMatchInput! ) { ledgerAccount(ledgerAccount: $ledgerAccount) { path name balance type lines { nodes { amount posted } } } } ``` The IK of the Ledger needs to be provided along with the Ledger Account's path: ```json title="GetLedgerAccount Variables" { "ledgerAccount": { "path": "assets/banks/user-cash", "ledger": { "ik": "quickstart-ledger" } } } ``` ### Lookup multiple You can also retrieve multiple Ledger Accounts using the `ledgerAccounts` query and the `in` filter: ```graphql title="ListLedgerAccounts" query ListLedgerAccounts($ledger: LedgerMatchInput!, $filter: LedgerAccountsFilterSet) { ledger(ledger: $ledger) { ledgerAccounts(filter: $filter) { nodes { name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="GetLedgerAccount Variables with In" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "ledgerAccount": { "in": [ { "path": "assets/banks/user-cash" }, { "path": "income-root/income-revenue-root" } ] } } } ``` ### List Use the `ledger.ledgerAccounts` query to list all Ledger Accounts within a Ledger: ```graphql title="ListLedgerAccounts" query ListLedgerAccounts($ledger: LedgerMatchInput!) { ledger(ledger: $ledger) { ledgerAccounts { nodes { name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="ListLedgerAccounts variables" { "ledger": { "ik": "quickstart-ledger" } } ``` The response is a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of Ledger Accounts. ### Balances To read balances for Ledger Accounts, see: - [Read balances](https://fragment.dev/markdown/guides/read-balances.md) for single-currency accounts - [Handle currencies](https://fragment.dev/markdown/guides/handle-currencies.md#read-balances) for multi-currency accounts ### Filter by type Use the `type` parameter to filter Ledger Account lists: ```graphql title="FilterLedgerAccounts query" query FilterLedgerAccounts( $ledger: LedgerMatchInput!, $filter: LedgerAccountsFilterSet! ) { ledger(ledger: $ledger) { ledgerAccounts(filter: $filter) { nodes { name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` Use `type` to filter Ledger Accounts by their type: ```json title="FilterLedgerAccounts variables - by type" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "type": { "equalTo": "asset" } } } ``` You can also filter for multiple types in one query, using `in`. This can be useful to [Generate reports](https://fragment.dev/markdown/guides/generate-reports.md): ```json title="FilterLedgerAccounts variables - type in" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "type": { "in": ["asset", "liability"] } } } ``` ### Filter by path Use `path` and wildcard matching (`*`) in place of template variables to query all instances of Ledger Accounts with `template: true`. ```graphql title="FilterLedgerAccounts query" query FilterLedgerAccounts( $ledger: LedgerMatchInput!, $filter: LedgerAccountsFilterSet! ) { ledger(ledger: $ledger) { ledgerAccounts(filter: $filter) { nodes { name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="FilterLedgerAccounts variables - by external account" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "path": { "matches": "liability-root/user:*/pending" } } } ``` Read more about filtering Ledger Accounts in [filtering](https://fragment.dev/markdown/guides/query-data.md#basics-filtering). ### Filter by Link Use `linkedAccount` to filter Ledger Accounts by the External Account they're linked to: ```graphql title="FilterLedgerAccounts query" query FilterLedgerAccounts( $ledger: LedgerMatchInput!, $filter: LedgerAccountsFilterSet! ) { ledger(ledger: $ledger) { ledgerAccounts(filter: $filter) { nodes { name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="FilterLedgerAccounts variables - by external account" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "linkedAccount": { "in": [ { "linkId": "", "externalId": "account-id-at-bank" }, { "linkId": "", "externalId": "account2-id-at-bank" } ] } } } ``` ### Filter by parent Use `hasParentLedgerAccount` to filter Ledger Accounts by their parent status: ```graphql title="FilterLedgerAccounts query" query FilterLedgerAccounts( $ledger: LedgerMatchInput!, $filter: LedgerAccountsFilterSet! ) { ledger(ledger: $ledger) { ledgerAccounts(filter: $filter) { nodes { name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="FilterLedgerAccounts variables - by external account" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "hasParentLedgerAccount": false } } ``` Read more about filtering Ledger Accounts in [filtering](https://fragment.dev/markdown/guides/query-data.md#basics-filtering). ## Ledger Lines ### Lookup Use the `ledgerLine` query to retrieve a Ledger Line by its ID: ```graphql title="GetLedgerLine" query GetLedgerLine( $ledgerLine: LedgerLineMatchInput! ) { ledgerLine(ledgerLine: $ledgerLine) { amount currency { code customCurrencyId } account { name type } } } ``` ```json title="FilterLedgerAccountLines Variables" { "ledgerLine": { "id": "" } } ``` ### List Use the `ledgerAccount.lines` query to list the lines in a Ledger Account: ```graphql title="GetLedgerAccountLines" query GetLedgerAccountLines( $ledgerAccount: LedgerAccountMatchInput! ) { ledgerAccount(ledgerAccount: $ledgerAccount) { path name lines { nodes { amount currency { code customCurrencyId } } } } } ``` ```json title="GetLedgerAccountLines Variables" { "ledgerAccount": { "path": "assets/banks/user-cash", "ledger": { "ik": "quickstart-ledger" } } } ``` ### Filter by posted Use `posted` to filter Ledger Lines by their posted timestamp between any two points in time: ```graphql title="FilterLedgerAccountLines" query GetLedgerAccountLines( $ledgerAccount: LedgerAccountMatchInput!, $filter: LedgerLinesFilterSet! ) { ledgerAccount(ledgerAccount: $ledgerAccount) { path name lines(filter: $filter) { nodes { id amount currency { code customCurrencyId } } } } } ``` ```json title="FilterLedgerAccountLines Variables" { "ledgerAccount": { "path": "assets/banks/user-cash", "ledger": { "ik": "quickstart-ledger" } }, "filter": { "posted": { "after": "1969-07-01T00:00:00.000Z", "before": "1969-07-30T23:59:59.999Z" } } } ``` The `after` and `before` filters are inclusive, so use timestamps for the first and last moments of the period you're querying for. ### Filter by key Use `key` to filter Ledger Lines by their keys in your Schema: ```graphql title="FilterLedgerAccountLines" query GetLedgerAccountLines( $ledgerAccount: LedgerAccountMatchInput!, $filter: LedgerLinesFilterSet! ) { ledgerAccount(ledgerAccount: $ledgerAccount) { path name lines(filter: $filter) { nodes { id amount currency { code customCurrencyId } } } } } ``` ```json title="FilterLedgerAccountLines Variables" { "ledgerAccount": { "path": "assets/banks/user-cash", "ledger": { "ik": "quickstart-ledger" } }, "linesFilter": { "key": { "equalTo": "increase_user_balance" } } } ``` ## Ledger Entries ### Lookup Use the `ledgerEntry` query to retrieve a Ledger Entry by its IK. You provide the IK when posting entries via `addLedgerEntry`: ```graphql title="GetLedgerEntry" query GetLedgerEntry( $ledgerEntry: LedgerEntryMatchInput! ) { ledgerEntry(ledgerEntry: $ledgerEntry) { id ik ledger { id name } lines { nodes { amount currency { code customCurrencyId } } } } } ``` ```json title="GetLedgerEntry Variables - by IK" { "ledgerEntry": { "ik": "" } } ``` When you [Reconcile transactions](https://fragment.dev/markdown/guides/reconcile-payments.md#reconcile-a-tx) using `reconcileTx`, the IK is the Transaction's `externalId`. Query `entry.ik` in `ReconcileTxResult` to retrieve it: ```graphql title="Querying IK in reconcileTx" mutation ReconcileTx( $entry: LedgerEntryInput! ) { reconcileTx(entry: $entry) { ... on ReconcileTxResult { entry { ik type created posted } lines { amount account { path } } } ... on Error { code message } } } ``` A Ledger Entry can also be retrieved using its ID: ```json title="GetLedgerEntry Variables - by ID" { "ledgerEntry": { "id": "" } } ``` ### Lookup multiple You can also retrieve multiple Ledger Entries using the `ledgerEntries` query and the `in` filter: ```graphql title="ListLedgerEntries" query ListLedgerEntries( $ledger: LedgerMatchInput! $filter: LedgerEntriesFilterSet! ) { ledger(ledger: $ledger) { ledgerEntries(filter: $filter) { nodes { ik type posted lines { nodes { amount account { path } } } } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="ListLedgerEntries Variables with In" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "ledgerEntry": { "in": [ { "ik": "fund-user-1-account" }, { "ik": "fund-user-2-account" } ] } } } ``` ### List by group You can get a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of Ledger Entries in a given group using the `ledgerEntryGroup.ledgerEntries` expansion: ```graphql title="GetGroupedLedgerEntries" query GetGroupedLedgerEntries( $ledger: LedgerMatchInput!, $ledgerEntryGroup: EntryGroupMatchInput!, ) { ledger(ledger: $ledger) { ledgerEntryGroup(ledgerEntryGroup: $ledgerEntryGroup) { ledgerEntries { nodes { ik description posted } pageInfo { endCursor hasNextPage hasPreviousPage startCursor } } } } } ``` ```json title="GetGroupedLedgerEntries Variables" { "ledgerEntryGroup": { "key": "withdrawal", "value": "12345" }, "ledger": { "ik": "quickstart-ledger" } } ``` The response is: ```json title="GetGroupedLedgerEntries Response" { "data": { "ledger": { "ledgerEntryGroup": { "ledgerEntries": { "nodes": [ { "ik": "ledger-entry-2", "description":"User user-id withdrawal settled", "posted": "1969-06-21T02:56:05.000Z" }, { "ik": "ledger-entry-1", "description": "User user-id initiated withdrawal for 50000.", "posted": "1969-06-16T13:32:00.000Z" } ], "pageInfo": { "hasNextPage": false, "endCursor": null, "hasPreviousPage": false, "startCursor": null } } } } } } ``` ### List hidden Use the `showHidden` filter to get a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of all Ledger Entries, including those hidden by reversals. ```graphql title="FilterLedgerEntries" query FilterLedgerEntries( $ledger: LedgerMatchInput!, $entriesFilter: LedgerEntriesFilterSet! ) { ledger(ledger: $ledger) { ledgerEntries(filter: $entriesFilter) { nodes { ik type posted hidden } } } } ``` ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "showHidden": true } } ``` ### Expand lines Use the `ledgerEntry.lines` expansion to list the Ledger Lines in a Ledger Entry: ```graphql title="GetLedgerEntryLines" query GetLedgerEntryLines( $ledgerEntry: LedgerEntryMatchInput! ) { ledgerEntry(ledgerEntry: $ledgerEntry) { id ik lines { nodes { account { path } amount currency { code customCurrencyId } } pageInfo { endCursor hasNextPage hasPreviousPage startCursor } } } } ``` ```json title="GetLedgerEntryLines Variables" { "ledgerEntry": { "ik": "" } } ``` ### Filter by posted Similar to Ledger Lines, Ledger Entries can be filtered by their posted timestamp between any two points in time using `posted`: ```graphql title="FilterLedgerEntries" query FilterLedgerEntries( $ledger: LedgerMatchInput!, $entriesFilter: LedgerEntriesFilterSet! ) { ledger(ledger: $ledger) { ledgerEntries(filter: $entriesFilter) { nodes { ik type posted lines { nodes { amount account { path } } } } } } } ``` Use `after` and `before` to filter Ledger Entries by their posted timestamp between any two points in time: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "posted": { "after": "1968-01-01", "before": "1969-01-01" } } } ``` Use `date` to filter Ledger Entries by the date they were posted on: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "date": { "equalTo": "12-31-1968" } } } ``` ### Filter by type Use `type` to filter Ledger Entries by their type as defined in your Schema: ```graphql title="FilterLedgerEntries" query FilterLedgerEntries( $ledger: LedgerMatchInput!, $entriesFilter: LedgerEntriesFilterSet! ) { ledger(ledger: $ledger) { ledgerEntries(filter: $entriesFilter) { nodes { ik type posted lines { nodes { amount account { path } } } } } } } ``` ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "type": { "equalTo": "withdrawal" } } } ``` To retrieve Ledger Entries of multiple types, use the `in` operator: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "type": { "in": ["withdrawal", "p2p_transfer"] } } } ``` ### Filter by typeVersion Use `typeVersion` to filter Ledger Entries by [typeVersion](https://fragment.dev/markdown/guides/migrate-data.md#updating-entry-types) as defined in your Schema. It is not required but often useful to combine this with a `type` filter. Note that `typeVersion` is a String filter: ```graphql title="FilterLedgerEntries" query FilterLedgerEntries( $ledger: LedgerMatchInput!, $entriesFilter: LedgerEntriesFilterSet! ) { ledger(ledger: $ledger) { ledgerEntries(filter: $entriesFilter) { nodes { ik type posted lines { nodes { amount account { path } } } } } } } ``` ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "type": { "equalTo": "withdrawal" }, "typeVersion": { "equalTo": "2" } } } ``` To retrieve Ledger Entries of multiple typeVersions, use the `in` operator: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "type": { "equalTo": "withdrawal" }, "typeVersion": { "in": ["2", "3"] } } } ``` ### Filter by group Use `group` to filter Ledger Entries by [groups](https://fragment.dev/markdown/guides/group-ledger-entries.md): ```graphql title="FilterLedgerEntries" query FilterLedgerEntries( $ledger: LedgerMatchInput!, $entriesFilter: LedgerEntriesFilterSet! ) { ledger(ledger: $ledger) { ledgerEntries(filter: $entriesFilter) { nodes { ik type posted groups { key value } } } } } ``` Use the `equalTo` operator to find Ledger Entries that are in the specified group: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "group": { "equalTo": { "key": "department", "value": "sales" } } } } ``` Use the `in` operator to find Ledger Entries that are in any of the specified groups: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "group": { "in": [{ "key": "department", "value": "sales" },{ "key": "department", "value": "inventory" }] } } } ``` Use the `notEqualTo` operator to find Ledger Entries that are not in the specified group: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "group": { "notEqualTo": { "key": "department", "value": "sales" } } } } ``` Use the `notIn` operator to find Ledger Entries that are not in any of the specified groups: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "group": { "notIn": [{ "key": "department", "value": "sales" },{ "key": "department", "value": "inventory" }] } } } ``` Use the `keyEqualTo` operator to find Ledger Entries that are in a group with the specified group key: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "group": { "keyEqualTo": "department" } } } ``` Use the `notKeyEqualTo` operator to find Ledger Entries that are not in any group with the specified group key: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "group": { "notKeyEqualTo": "department" } } } ``` Use the `keyIn` operator to find Ledger Entries that are in any group with any of the specified group keys: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "group": { "keyIn": ["department", "priority"] } } } ``` Use the `notKeyIn` operator to find Ledger Entries that are not in any group with any of the specified group keys: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "group": { "notKeyIn": ["department", "priority"] } } } ``` ### Filter by tag Use `tag` to filter Ledger Entries by [tags](https://fragment.dev/markdown/guides/store-metadata.md): ```graphql title="FilterLedgerEntries" query FilterLedgerEntries( $ledger: LedgerMatchInput!, $entriesFilter: LedgerEntriesFilterSet! ) { ledger(ledger: $ledger) { ledgerEntries(filter: $entriesFilter) { nodes { ik type posted tags { key value } } } } } ``` ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "tag": { "equalTo": { "key": "user_id", "value": "user-1" } } } } ``` Use the `in` operator to find Ledger Entries that have any of the specified tags: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "tag": { "in": [{ "key": "user_id", "value": "user-1" },{ "key": "user_id", "value": "user-2" }] } } } ``` Use the `notEqualTo` operator to find Ledger Entries that do not have the specified tag: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "tag": { "notEqualTo": { "key": "invoice-status", "value": "invoice-paid" } } } } ``` Use the `notIn` operator to find Ledger Entries that do not have any of the specified tags: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "tag": { "notIn": [{ "key": "invoice-status", "value": "invoice-pending" },{ "key": "invoice-status", "value": "invoice-cancelled" }] } } } ``` Use the `contains` operator to find Ledger Entries that have a tag with a specific tag key and a partial match on the tag value. The filter matches when the tag value contains the specified tag value: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "tag": { "contains": { "key": "user-id", "value": "merchant-" } } } } ``` Use the `keyEqualTo` operator to find Ledger Entries that have a tag with the specified key: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "tag": { "keyEqualTo": "user-id" } } } ``` Use the `notKeyEqualTo` operator to find Ledger Entries that do not have a tag with a specified key: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "tag": { "notKeyEqualTo": "user-id" } } } ``` Use the `keyIn` operator to find Ledger Entries that have a tag with any of the specified tag keys: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "tag": { "keyIn": ["user-id", "invoice-status"] } } } ``` Use the `notKeyIn` operator to filter Ledger Entries that do not contain any of the specified keys: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "tag": { "notKeyIn": ["user-id", "invoice-status"] } } } ``` ### Filter by reversal Use: - `isReversal` to filter reversing Ledger Entries - `isReversed` to filter reversed Ledger Entries ```graphql title="FilterLedgerEntries" query FilterLedgerEntries( $ledger: LedgerMatchInput!, $entriesFilter: LedgerEntriesFilterSet! ) { ledger(ledger: $ledger) { ledgerEntries(filter: $entriesFilter) { nodes { ik type posted reversedBy { ik created } reverses { ik created } } } } } ``` For all Ledger Entries, only one of `isReversal` or `isReversed` will ever be `true`. The following will return all reversing Ledger Entries: ```json title="FilterLedgerEntries Variables" { "ledger": { "ik": "quickstart-ledger" }, "entriesFilter": { "isReversal": true } } ``` ## Ledger Entry Groups See [Group Ledger Entries](https://fragment.dev/markdown/guides/group-ledger-entries.md) for more information about how to use Ledger Entry Groups. ### Lookup Use the `ledger.ledgerEntryGroup` expansion to lookup a group by key and value. ```graphql title="GetLedgerEntryGroup" query GetLedgerEntryGroup( $ledger: LedgerMatchInput! $entryGroup: EntryGroupMatchInput! ) { ledger(ledger: $ledger) { ledgerEntryGroup(ledgerEntryGroup: $entryGroup) { key value created } } } ``` ```json title="GetLedgerEntryGroup Variables" { "entryGroup": { "key": "withdrawal", "value": "12345" }, "ledger": { "ik": "quickstart-ledger" } } ``` The response is: ```json title="GetLedgerEntryGroup Response" { "data": { "ledger": { "ledgerEntryGroup": { "key": "withdrawal", "value": "12345", "created": "1969-06-16T13:32:00.000Z" } } } } ``` ### List ```graphql title="ListLedgerEntryGroups" query ListLedgerEntryGroups( $ledger: LedgerMatchInput! ) { ledger(ledger: $ledger) { ledgerEntryGroups { nodes { key value created } pageInfo { endCursor hasNextPage hasPreviousPage startCursor } } } } ``` ```json title="ListLedgerEntryGroups Variables" { "ledger": { "ik": "quickstart-ledger" } } ``` The response is: ```json title="ListLedgerEntryGroups Response" { "data": { "ledger": { "ledgerEntryGroups": { "nodes": [ { "key": "withdrawal", "value": "12345", "created": "1969-06-16T13:32:00.000Z" }, { "key": "withdrawal", "value": "54321", "created": "1969-06-21T02:56:05.000Z" } ], "pageInfo": { "endCursor": null, "hasNextPage": false, "hasPreviousPage": false, "startCursor": null } } } } } ``` ### Filter You can filter groups by `key`, `value`, `created`, and/or `balance` ```graphql title="ListLedgerEntryGroups" query ListLedgerEntryGroups( $ledger: LedgerMatchInput! $filter: LedgerEntryGroupsFilterSet, ) { ledger(ledger: $ledger) { ledgerEntryGroups(filter: $filter) { nodes { key value created } pageInfo { endCursor hasNextPage hasPreviousPage startCursor } } } } ``` ```json title="ListLedgerEntryGroups Variables" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "key": { "equalTo": "withdrawal" }, "created": { "before": "1969-06-20T00:00:00.000Z" } } } ``` The response is: ```json title="ListLedgerEntryGroups Response" { "data": { "ledger": { "ledgerEntryGroups": { "nodes": [ { "key": "withdrawal", "value": "12345", "created": "1969-06-16T13:32:00.000Z" } ], "pageInfo": { "endCursor": null, "hasNextPage": false, "hasPreviousPage": false, "startCursor": null } } } } } ``` The `balance` filter enables querying for group values where the balance of an account in the group matches a provided condition. An example use-case is to find all groups with key "invoice" where a non-zero balance in a certain account represents an unpaid invoice. When filtering by balance, a `key` must be provided, and a `created` filter cannot be used. A `value` filter is optional. The `balance` filter uses the [LedgerEntryGroupBalanceFilterSet](https://fragment.dev/markdown/api-reference/ledger-types.md#filter-types-ledgerentrygroupbalancefilterset) API Type. An `account` field is required, and the `currency` and `ownBalance` fields are optional. ```graphql title="ListLedgerEntryGroups" query ListLedgerEntryGroups( $ledger: LedgerMatchInput! $filter: LedgerEntryGroupsFilterSet, ) { ledger(ledger: $ledger) { ledgerEntryGroups(filter: $filter) { nodes { key value created } pageInfo { endCursor hasNextPage hasPreviousPage startCursor } } } } ``` ```json title="ListLedgerEntryGroups Variables" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "key": { "equalTo": "invoice" }, "balance": { "account": { "path": { "equalTo": "liabilities/user-funds" } }, "currency": { "equalTo": { "code": "USD" } }, "ownBalance": { "ne": "0" } } } } ``` ## Links ### Lookup Use the `link` query to retrieve a Link by ID: ```graphql title="GetLink" query GetLink($link: LinkMatchInput!) { link(link: $link) { __typename name } } ``` ```json title="GetLink Variables" { "link": { "id": "" } } ``` The `__typename` field will indicate the type of of the [Link](https://fragment.dev/markdown/guides/sync-payments.md) ### External Accounts Use the `link.externalAccounts` to list External Accounts represented by the Link. ```graphql title="GetLinkExternalAccounts" query GetLinkExternalAccounts($link: LinkMatchInput!) { link(link: $link) { id externalAccounts { nodes { name id externalId } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="GetLinkExternalAccounts Variables" { "link": { "id": "" } } ``` The response is a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of External Accounts. ## External Accounts ### Lookup Use the `externalAccount` query to retrieve an ExternalAccount by its ID at your external system: ```graphql title="GetExternalAccountByExternalIdAndLinkId" query GetExternalAccount( $externalId: ID! $linkId: ID! ) { externalAccount( externalAccount: { externalId: $externalId linkId: $linkId } ) { name link { __typename id name } } } ``` ```json title="GetExternalAccountByExternalIdAndLinkId Variables" { "externalId": "", "linkId": "" } ``` Or by its Fragment ID: ```graphql title="GetExternalAccountByFragmentID" query GetExternalAccount($id: ID!) { externalAccount(externalAccount: { id: $id }) { name externalId linkId link { __typename id name } } } ``` ```json title="GetExternalAccountByFragmentID Variables" { "id": "" } ``` ### Txs Use the `externalAccount.txs` query to list Txs synced to an External Account: ```graphql title="ListExternalAccountTxs" query ListExternalAccountTxs( $externalAccount: ExternalAccountMatchInput! $after: String $first: Int $before: String ) { externalAccount( externalAccount: $externalAccount ) { externalId link { __typename id name } txs( after: $after first: $first before: $before ) { nodes { externalId } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` You may optionally specify `before` and `after` to paginate the results and `first` to specify the page size. ```json title="ListExternalAccountTxs Variables" { "externalAccount": { "externalId": "", "linkId": "" }, "after": "2023-07-01T00:00:00.000Z", "before": "2023-07-30T23:59:59.999Z", "first": 20 } ``` The response is a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of Txs. ### Linked Accounts Use the `externalAccount.ledgerAccounts` query to list Ledger Accounts linked to this External Account: ```graphql title="GetExternalAccountLinkedAccounts" query GetExternalAccountLinkedAccounts( $externalAccount: ExternalAccountMatchInput! ) { externalAccount( externalAccount: $externalAccount ) { externalId name link { __typename id name } ledgerAccounts { nodes { path name type } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` ```json title="GetExternalAccountLinkedAccounts Variables" { "externalAccount": { "externalId": "", "linkId": "" } } ``` The response is a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of Ledger Accounts. ## Txs ### Lookup Use the `tx` query to retrieve a Tx by its ID and Account ID at your external system: ```graphql title="GetTxByExternalIds" query GetTx( $externalId: ID! $externalAccountId: ID! $linkId: ID! ) { tx( tx: { externalId: $externalId externalAccountId: $externalAccountId linkId: $linkId } ) { id description amount currency { code } externalId link { id } externalAccount { id externalId } } } ``` ```json title="GetTxByExternalIds Variables" { "externalAccountId": "", "external": "", "linkId": "" } ``` Or by its Fragment ID: ```graphql title="GetTxByFragmentID" query GetTx( $id: ID! ) { tx( tx: { id: $id } ) { id description amount currency { code } externalId link { id } externalAccount { id externalId } } } ``` ```json title="GetTxByFragmentID Variables" { "id": "" } ``` ### Unreconciled Use the `ledgerAccount.unreconciledTx` query to list a Ledger Account's unreconciled Txs: ```graphql title="GetUnreconciledTxs" query GetUnreconciledTxs( $ledgerAccount: LedgerAccountMatchInput! $after: String $first: Int $before: String ) { ledgerAccount(ledgerAccount: $ledgerAccount) { path unreconciledTxs( after: $after first: $first before: $before ) { nodes { id description amount currency { code } externalId link { id } externalAccount { id externalId } } pageInfo { hasNextPage endCursor hasPreviousPage startCursor } } } } ``` You may optionally specify `before` and `after` to paginate the results and `first` to specify the page size. ```json title="GetUnreconciledTxs Variables" { "ledgerAccount": { "path": "assets/banks/user-cash", "ledger": { "ik": "quickstart-ledger" } }, "after": "2023-07-01T00:00:00.000Z", "before": "2023-07-30T23:59:59.999Z", "first": 20 } ``` The response is a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of Txs. ## Payments ### Lookup Use the `payment` query to look up a Payment by its `ik`: ```graphql title="GetPayment" query GetPayment($payment: PaymentMatchInput!) { payment(payment: $payment) { id ik type typeVersion status amount currency { code } parameters created } } ``` ```json title="GetPayment Variables" { "payment": { "ik": "order-1024", "ledger": { "ik": "quickstart-ledger" } } } ``` ### List Use `ledger.payments` to list all Payments within a Ledger: ```graphql title="ListPayments" query ListPayments( $ledger: LedgerMatchInput! $filter: PaymentsFilterSet $first: Int $after: String ) { ledger(ledger: $ledger) { payments(filter: $filter, first: $first, after: $after) { nodes { id ik type status amount currency { code } created } pageInfo { hasNextPage endCursor } } } } ``` ```json title="ListPayments Variables" { "ledger": { "ik": "quickstart-ledger" }, "first": 20 } ``` The response is a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of Payments. ### Filter by status Use `status` to filter Payments by their `status`: ```graphql title="FilterPaymentsByStatus" query ListPayments( $ledger: LedgerMatchInput! $filter: PaymentsFilterSet $first: Int $after: String ) { ledger(ledger: $ledger) { payments(filter: $filter, first: $first, after: $after) { nodes { id ik type status amount currency { code } created } pageInfo { hasNextPage endCursor } } } } ``` ```json title="FilterPaymentsByStatus Variables" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "status": { "equalTo": "settled" } } } ``` To retrieve Payments in multiple statuses, use the `in` operator: ```json title="FilterPaymentsByStatus Variables" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "status": { "in": ["needs_payment_method", "processing", "accepted"] } } } ``` ### Filter by created Use `created` to filter Payments by their created timestamp between any two points in time: ```graphql title="FilterPaymentsByCreated" query ListPayments( $ledger: LedgerMatchInput! $filter: PaymentsFilterSet $first: Int $after: String ) { ledger(ledger: $ledger) { payments(filter: $filter, first: $first, after: $after) { nodes { id ik type status amount currency { code } created } pageInfo { hasNextPage endCursor } } } } ``` ```json title="FilterPaymentsByCreated Variables" { "ledger": { "ik": "quickstart-ledger" }, "filter": { "created": { "after": "2026-09-01T00:00:00Z", "before": "2026-09-02T00:00:00Z" } } } ``` The `after` and `before` filters are inclusive, so use timestamps for the first and last moments of the period you're querying for. ## Schemas ### Lookup Use the `schema` query to retrieve a Schema by its key: ```graphql title="GetSchema" query GetSchema($schema: SchemaMatchInput!) { schema(schema: $schema) { key name latestVersion: version { created version } firstVersion: version(version: 1) { created version } } } ``` When retrieving a Schema, use the `version` argument to query a specific version of the Schema. By default, the latest version is returned: ```json title="GetSchema Variables" { "schema": { "key": "quickstart-schema" } } ``` The JSON of a Schema version can be retrieved by querying the `json` field: ```graphql title="GetLatestSchemaJSON" query GetLatestSchemaJSON( $schema: SchemaMatchInput! ) { schema(schema: $schema) { key name version { created version json } } } ``` ```json title="GetLatestSchemaJSON Variables" { "schema": { "key": "quickstart-schema" } } ``` ### List versions Use the `schema.versions` query to query all the versions of your Schema: ```graphql title="ListSchemaVersions" query ListSchemaVersions( $schema: SchemaMatchInput! ) { schema(schema: $schema) { key name versions { nodes { created version json } } } } ``` The response is a [paginated](https://fragment.dev/markdown/guides/query-data.md#basics-pagination) list of your Schema's versions: ```json title="ListSchemaVersions Variables" { "schema": { "key": "quickstart-schema" } } ``` ### List Ledgers Use the `schema.ledgers` query to list the Ledgers created off a Schema: ```graphql title="ListSchemaLedgers" query ListSchemaLedgers( $schema: SchemaMatchInput! ) { schema(schema: $schema) { key name ledgers { nodes { ik name created balanceUTCOffset } } } } ``` ```json title="ListSchemaLedgers Variables" { "schema": { "key": "quickstart-schema" } } ``` ### Migration status Fragment asynchronously migrates Ledgers when their Schema is updated. The current status of a Ledger's migration can be queried using the API, via `version.migrations`: ```graphql title="GetLedgerMigrationStatus" query GetLedgerMigrationStatus( $schema: SchemaMatchInput! ) { schema(schema: $schema) { key name latestVersion: version { migrations { nodes { ledger { ik name } status } } } } } ``` ```json title="ListSchemaLedgers Variables" { "schema": { "key": "quickstart-schema" } } ```