Skip to content
TRES Finance Help Center home

API-Based Data Collection + Reconciliation

All endpoints below are GraphQL operations against a single URL:

POST https://api.prod.tres.finance/graphql

with header Authorization: Bearer <access_token> (obtained from the login endpoint — see the API reference's Introduction page).

The core concept

A commit is an asynchronous job: you tell Tres which accounts and which date range to collect, Tres goes and pulls transactions/balances from the source (chain or exchange) and rebuilds the ledger for that window, and then you can ask whether the result reconciles — i.e. whether Tres's computed balance for that account+asset matches the source balance, within tolerance.

triggerParallelCommit processes each account/asset independently in parallel, supports asset-level scoping (assetsToCollect) and throttling (maxTransactionLimit), and — unlike the sequential triggerCommit — its commits can be checked for reconciliation via checkParallelCommitReconciliationStatus. That combination is what makes it the right tool whenever you need to programmatically confirm collected data is reconciled.

End-to-end flow

  1. Trigger a parallel commit for the accounts/assets/date-range you care about → you get back a commitId.

  2. (Optional) Throttle it via updateCommitMaxTransactionLimit if it's ingesting more than expected.

  3. Poll checkParallelCommitReconciliationStatus(commitId) — this returns one result per account+asset in the commit, each with isReconciled and the underlying diff amounts.

  4. Act on the result: if reconciled, you're done. If not reconciled or the job is stuck, cancel it with killCommits (by ID, or all-at-once as an emergency stop) and re-trigger.


Endpoint reference

1. Trigger Parallel Commit — triggerParallelCommit

The production-grade version. Accounts can be specified either by Tres's internal ID (internalAccountIds) or by their external identifier/address (internalAccountIdentifiers). fromDate/toDate are required.

mutation TriggerParallelCommit( $internalAccountIds: [ID] $internalAccountIdentifiers: [String] $fromDate: DateTime! $toDate: DateTime! $commitId: UUID $assetsToCollect: [String] $fetchFullHistory: Boolean $commitRequestCustomerMetadata: CommitRequestCustomerMetadataInput ) { triggerParallelCommit( internalAccountIds: $internalAccountIds internalAccountIdentifiers: $internalAccountIdentifiers fromDate: $fromDate toDate: $toDate commitId: $commitId assetsToCollect: $assetsToCollect fetchFullHistory: $fetchFullHistory commitRequestCustomerMetadata: $commitRequestCustomerMetadata ) { status message commitId } }

Variables:

{ "internalAccountIdentifiers": ["0x6897938af83502d348720679fe7d8e83e7dd5ff2a13c9cad189302babceb7be9"], "assetsToCollect": ["substrate_kusama_native"], "fetchFullHistory": false, "fromDate": "2025-01-01T00:00:00Z", "toDate": "2025-09-28T23:59:59Z", "commitRequestCustomerMetadata": { "env": "EXAMPLE", "userId": "user" } }

Key fields:

  • assetsToCollect — narrow the commit to specific assets instead of the account's entire balance sheet. Optional here; required once you also pass maxTransactionLimit (see variant below).

  • fetchFullHistory — collect the account's entire history instead of just fromDatetoDate.

  • commitRequestCustomerMetadata (env, userId) — free-form tags you set so you can trace a commit back to what triggered it on your side. This metadata is echoed back in the reconciliation-status response, so it's the cheapest way to correlate a reconciliation result with your own request/job.

Save the returned commitId — every other endpoint in this set operates on it.

2. Trigger Parallel Commit + Max Transaction Limit

Same mutation, with assetsToCollect: [String]! now required and an added maxTransactionLimit: Int to cap how many transactions a single commit will pull per asset — useful for bounding a large backfill so a single call can't runaway ingest an unexpectedly large history.

mutation TriggerParallelCommit( $internalAccountIds: [ID] $internalAccountIdentifiers: [String] $fromDate: DateTime! $toDate: DateTime! $commitId: UUID $assetsToCollect: [String]! $maxTransactionLimit: Int ) { triggerParallelCommit( internalAccountIds: $internalAccountIds fromDate: $fromDate toDate: $toDate commitId: $commitId assetsToCollect: $assetsToCollect internalAccountIdentifiers: $internalAccountIdentifiers maxTransactionLimit: $maxTransactionLimit ) { status message commitId } }

Variables:

{ "toDate": "2025-08-07T23:59:59+00:00", "fromDate": "2025-07-07T00:00:00+00:00", "assetsToCollect": ["arbitrum_0xff970a61a04b1ca14834a43f5de4533ebddb5cc8"], "internalAccountIds": [679191] }

3. Update Parallel Commit Max Transaction Limit — updateCommitMaxTransactionLimit

Adjust the limit on a commit after it's already been triggered (e.g. you started a broad backfill and realize mid-flight it's larger than expected and want to cap it).

mutation UpdateCommitMaxTransactionLimit($commitId: UUID!, $maxTransactionLimit: Int!) { updateCommitMaxTransactionLimit(commitId: $commitId, maxTransactionLimit: $maxTransactionLimit) { success } }
{ "commitId": "6b16a105-422a-2f68-bafd-b4634eafc801", "maxTransactionLimit": 1000 }

4. Check Parallel Commit Reconciliation — checkParallelCommitReconciliationStatus

This is the endpoint that answers "did it reconcile?". Query it by commitId (poll it periodically after triggering — collection is asynchronous). It returns one entry per account+asset that was part of the commit.

query CheckParallelCommitReconciliationStatus($commitId: UUID!) { checkParallelCommitReconciliationStatus(commitId: $commitId) { inflowAmount outflowAmount feeAmount totalAmount openingBalance closingBalance balanceDiff closingUnbondingBalance openingUnbondingBalance reconciliationDiff internalAccountIdentifier assetKey reconciliationDiffUsd internalAccountName fromDate toDate isReconciled commitRequestCustomerMetadata { env userId } } }
{ "commitId": "1047cc60-dc1c-477a-8104-084ebdf5a74e" }

Field meaning:

Field

Meaning

isReconciled

The bottom line. true if Tres's rebuilt closing balance matches the source-of-truth balance for this account+asset within tolerance.

reconciliationDiff / reconciliationDiffUsd

The size of the mismatch (native asset units / USD) when not reconciled — use this to decide if a diff is negligible (dust/rounding) or a real problem.

openingBalance / closingBalance

Balance at the start/end of the fromDatetoDate window, as computed by Tres.

balanceDiff

closingBalance - openingBalance as derived from the ledger.

inflowAmount / outflowAmount / feeAmount / totalAmount

Breakdown of activity that produced balanceDiff over the window.

openingUnbondingBalance / closingUnbondingBalance

Same idea, for assets that have a staking/unbonding balance (e.g. bonded/unbonding stake).

assetKey, internalAccountIdentifier, internalAccountName

Which account+asset this row describes — needed because one commit can cover many accounts/assets.

commitRequestCustomerMetadata

Echoes back the env/userId you sent on triggerParallelCommit, for correlating results to your own request.

Polling tip: collection runs asynchronously after you trigger the commit. Poll this query on a backoff (e.g. every 5–15s) rather than immediately — an empty/incomplete result right after triggering just means the job hasn't finished yet, not that it failed.

5. Kill Commits — killCommits

Cancels running/queued commits. Call with no arguments to stop all active commits (emergency stop), or pass specific commitIds to cancel precisely the one(s) you started.

mutation KillCommits { killCommits { status } }
mutation KillCommits($commitIds: [String]) { killCommits(commitIds: $commitIds) { status } }
{ "commitIds": ["51f27092-f6e9-4fd8-a8d9-c36100ba7c05"] }

Use this when a commit is stuck, taking far longer than expected, or you triggered it with the wrong parameters and want to retry cleanly instead of letting it finish.


Putting it all together (worked example)

1) Trigger collection for an account over a date range, scoped to one asset curl --location -g 'https://api.prod.tres.finance/graphql' \ --header 'Authorization: Bearer <access_token>' \ --header 'Content-Type: application/json' \ --data '{ "query": "mutation TriggerParallelCommit($internalAccountIds:[ID],$fromDate:DateTime!,$toDate:DateTime!,$assetsToCollect:[String]){ triggerParallelCommit(internalAccountIds:$internalAccountIds, fromDate:$fromDate, toDate:$toDate, assetsToCollect:$assetsToCollect){ status message commitId } }", "variables": { "internalAccountIds": [679191], "fromDate": "2025-07-07T00:00:00+00:00", "toDate": "2025-08-07T23:59:59+00:00", "assetsToCollect": ["arbitrum_0xff970a61a04b1ca14834a43f5de4533ebddb5cc8"] } }' => { "data": { "triggerParallelCommit": { "status": "PENDING", "commitId": "1047cc60-...", "message": null } } } 2) Poll until the collection settles curl --location -g 'https://api.prod.tres.finance/graphql' \ --header 'Authorization: Bearer <access_token>' \ --header 'Content-Type: application/json' \ --data '{ "query": "query($commitId:UUID!){ checkParallelCommitReconciliationStatus(commitId:$commitId){ assetKey isReconciled reconciliationDiff reconciliationDiffUsd } }", "variables": { "commitId": "1047cc60-..." } }' => { "data": { "checkParallelCommitReconciliationStatus": [ { "assetKey": "arbitrum_0xff97...", "isReconciled": true, "reconciliationDiff": 0, "reconciliationDiffUsd": 0 } ] } } 3) If it's taking too long or you need to abort, cancel it explicitly curl --location -g 'https://api.prod.tres.finance/graphql' \ --header 'Authorization: Bearer <access_token>' \ --header 'Content-Type: application/json' \ --data '{ "query": "mutation($ids:[String]){ killCommits(commitIds:$ids){ status } }", "variables": { "ids": ["1047cc60-..."] } }'

Best practices

  • Always capture the returned commitId immediately after triggering; you'll need it for every subsequent call in this set.

  • Poll with backoff, don't hammer checkParallelCommitReconciliationStatus in a tight loop — collection is async and can take time proportional to date range/history size.

  • Scope with assetsToCollect when you only care about specific tokens — it reduces both collection time and the number of reconciliation rows you have to evaluate.

  • Tag requests with commitRequestCustomerMetadata (env, userId) so reconciliation results are traceable back to whatever triggered them in your system, without needing to separately store a mapping of commitId → your job.

  • Guard large backfills with maxTransactionLimit up front, or throttle mid-flight with updateCommitMaxTransactionLimit if a commit turns out bigger than expected.

  • Cancel precisely with killCommits(commitIds: [...]); reserve the no-argument killCommits (kill everything) for genuine emergencies, since it affects every commit in flight, not just yours.

  • Treat small non-zero reconciliationDiff/reconciliationDiffUsd as expected rounding noise; treat large or growing diffs as a signal to investigate before trusting the ledger for that account+asset.