Reconciliation
Reconciliation compares the virtual balances in our ledger with the balances that you report. Its purpose is to find a drift between the two sides within hours, before it grows. This page explains when reconciliation runs, what it compares and where you read the result.
When it runs
Reconciliation runs for every tenant on two schedules:
- Hourly incremental run. It compares only the accounts that had movements since the last completed run. A drift is found within one hour at the latest.
- Daily full run. It compares all the user accounts of your tenant. It covers the accounts that the incremental run skipped, and it covers a missed hourly run.
You do not need to wait for reconciliation to get an instant comparison. Every balance-sync response returns the resulting balance on our side. Compare this value with your own record (Getting started).
What it compares
The basis of the comparison is the resulting_balance field that you send in balance syncs. This field is the balance that your system shows after the movement.
For an account, we take the last resulting_balance that you sent. To this value we add the movements that happened on our side after that sync: position openings, position settlements and market void refunds. If the result is not equal to the balance in our ledger, we open a reconciliation discrepancy for the account. Balance syncs that you sent after that sync are not part of the sum, because your next resulting_balance already includes them.
A debit movement that we rejected with 409 would_overdraw always opens a discrepancy. This rejection shows that the views of the two sides already differ (FAQ).
Accounts with no resulting_balance
If you never sent a resulting_balance for an account, there is no balance to compare. Reconciliation treats this account as unverifiable. An unverifiable account is not a discrepancy: we open no discrepancy record and we send no webhook. The status appears once in the reconciliation report as “unverifiable” and is not repeated in every run.
To make your accounts verifiable, send resulting_balance in every balance sync.
When a discrepancy is found
When reconciliation finds a discrepancy, it sends you the reconciliation.discrepancy event. The Webhook guide explains what you must do.
We do not report an open discrepancy again in every run. While an account has an open discrepancy, later runs open no new discrepancy record for it and send no new event. If the drift continues after our team resolves the discrepancy, the next run finds it again and reports it to you again.
Where you read the result
The result of reconciliation is in the reconciliation_statement report. This report is an account statement: the opening balance, the ledger movements of the period in order, the closing balance and the list of discrepancies of the period. You can request the report for one user or for the total of your tenant.
You can request the report in two ways:
- From the
Reportsscreen of the tenant portal. TheSettlementscreen of the portal shows the statement for the total of your tenant. - With
POST /v1/reports, using a key that has theread:reportsscope. For the statement of one user, give theexternal_user_idfilter.
We generate the report in the background. When it is ready, the report.ready event arrives. You can also poll the status with GET /v1/reports/{id}. The report downloads in JSON or CSV format. The API reference has the details.
The go-live item
The Go-live checklist asks for one clean reconciliation run: at least one full scheduled run over your sandbox traffic, with zero discrepancies. You show it in sandbox like this:
- Register users in sandbox and send balance syncs. Send
resulting_balancein every sync. If you do not, the accounts stay unverifiable. - Open positions on the sandbox markets and watch them settle.
- Wait for one daily full run to pass.
- Request the
reconciliation_statementreport for the total of your tenant, for the period that the run covers. The discrepancy list must be empty.
During this time, no reconciliation.discrepancy event must arrive. Our team verifies the item from the sandbox run records.