Reconciliate balances
Compare token balances and transaction history between your system and on-chain state.
Reconciliation compares your internal records against on-chain state to detect discrepancies. Regular reconciliation catches integration bugs, missed events, and unauthorized transfers before they become audit findings.
Common use cases:
- Daily reconciliation - Compare end-of-day balances with your ledger
- Transaction matching - Verify all transfers in your system exist on-chain
- Audit preparation - Generate proof of on-chain state for compliance
- Incident investigation - Trace balance discrepancies to specific transactions
- Migration validation - Confirm balances after system upgrades
Indexer latency
All endpoints return indexed on-chain data. Typical latency is under 2 seconds after block confirmation. For real-time status of pending transactions, use transaction tracking.
Prerequisites
- Platform URL (e.g.,
https://your-platform.example.com) - API key (see Getting Started)
- Token contract address for the asset to reconcile
- Your internal balance records for comparison

Steps
Query current holder balances
Get all holder balances for a token:
curl -X GET "https://your-platform.example.com/api/token/0xTOKEN_ADDRESS/holders" \
-H "X-Api-Key: sm_dalp_xxxxxxxxxxxxxxxx"Response:
{
"token": {
"balances": [
{
"account": { "id": "0xHOLDER_1" },
"value": "1000.00",
"available": "800.00",
"frozen": "200.00",
"isFrozen": false,
"lastUpdatedAt": "2025-01-15T10:30:00.000Z"
},
{
"account": { "id": "0xHOLDER_2" },
"value": "500.00",
"available": "500.00",
"frozen": "0.00",
"isFrozen": false,
"lastUpdatedAt": "2025-01-14T15:20:00.000Z"
}
]
},
"totalCount": 2
}For a single holder:
curl -X GET "https://your-platform.example.com/api/token/0xTOKEN_ADDRESS/holder?holderAddress=0xHOLDER_ADDRESS" \
-H "X-Api-Key: sm_dalp_xxxxxxxxxxxxxxxx"Query transaction history
Get balance-affecting events for the token:
curl -X GET "https://your-platform.example.com/api/token/0xTOKEN_ADDRESS/events?eventNames=TransferCompleted&eventNames=MintCompleted&eventNames=BurnCompleted" \
-H "X-Api-Key: sm_dalp_xxxxxxxxxxxxxxxx"Response:
{
"events": [
{
"id": "0xEVENT_ID",
"eventName": "TransferCompleted",
"blockNumber": "12345678",
"blockTimestamp": "2025-01-15T10:30:00.000Z",
"transactionHash": "0xTX_HASH",
"emitter": { "id": "0xTOKEN_ADDRESS" },
"sender": { "id": "0xSENDER_ADDRESS" },
"values": [
{ "id": "0x...", "name": "from", "value": "0xFROM_ADDRESS" },
{ "id": "0x...", "name": "to", "value": "0xTO_ADDRESS" },
{ "id": "0x...", "name": "amount", "value": "1000000000000000000" }
]
}
]
}Compare with your records
Match on-chain data against your internal ledger:
- Balance check - For each holder, compare
valuefield with your records - Transaction check - For each event, verify a matching entry exists in your system
- Missing transactions - Events on-chain without internal records indicate missed processing
- Extra transactions - Internal records without on-chain events indicate failed submissions
Investigate discrepancies
For mismatches, query specific transactions:
curl -X GET "https://your-platform.example.com/api/token/0xTOKEN_ADDRESS/events?transactionHashes=0xTX_HASH_1&transactionHashes=0xTX_HASH_2" \
-H "X-Api-Key: sm_dalp_xxxxxxxxxxxxxxxx"Or filter by sender to find transactions initiated by a specific wallet:
curl -X GET "https://your-platform.example.com/api/token/0xTOKEN_ADDRESS/events?eventNames=TransferCompleted&senderAddress=0xYOUR_WALLET" \
-H "X-Api-Key: sm_dalp_xxxxxxxxxxxxxxxx"Reconciliation flow
API endpoints
All holders for a token
Endpoint: GET /api/token/{tokenAddress}/holders
Returns all holder balances for the specified token.
Single holder balance
Endpoint: GET /api/token/{tokenAddress}/holder
Query parameters:
| Parameter | Type | Description |
|---|---|---|
holderAddress | string | Wallet address to query |
All balances for a user
Endpoint: GET /api/user/assets
Query parameters:
| Parameter | Type | Description |
|---|---|---|
wallet | string | Wallet address to query |
Returns all token balances held by a specific wallet.
Token events
Endpoint: GET /api/token/{tokenAddress}/events
Query parameters:
| Parameter | Type | Description |
|---|---|---|
eventNames | string[] | Filter by event types |
senderAddress | string | Filter by transaction initiator |
transactionHashes | string[] | Filter by specific transactions |
User events
Endpoint: GET /api/user/events
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 20 | Max events (1-500) |
offset | number | 0 | Pagination offset |
orderBy | string | blockTimestamp | Sort field |
orderDirection | string | desc | Sort direction |
eventNames | string[] | — | Filter by event types |
senderAddress | string | — | Filter by initiator |
transactionHashes | string[] | — | Filter by transactions |
Event types for reconciliation
| Event | Description | Balance Impact |
|---|---|---|
TransferCompleted | Standard transfer between holders | Sender ↓, Receiver ↑ |
MintCompleted | New tokens created | Recipient ↑ |
BurnCompleted | Tokens destroyed | Holder ↓ |
ForcedTransfer | Custodian-initiated transfer | Sender ↓, Receiver ↑ |
Response fields
Balance fields
| Field | Type | Description |
|---|---|---|
value | string | Total balance (available + frozen) |
available | string | Balance available for transfer |
frozen | string | Balance locked by compliance or custodian |
isFrozen | boolean | Whether the entire account is frozen |
lastUpdatedAt | string | ISO timestamp of last balance change |
Event fields
| Field | Type | Description |
|---|---|---|
id | string | Unique event identifier |
eventName | string | Type of event |
transactionHash | string | On-chain transaction identifier |
blockTimestamp | string | ISO timestamp when event occurred |
blockNumber | string | Block containing the transaction |
emitter | object | Contract that emitted the event |
sender | object | Account that initiated the transaction |
involved | array | All accounts participating in the event |
values | array | Event parameters (from, to, amount, etc.) |
Sender vs involved
sender- The wallet that signed and submitted the transactioninvolved- All addresses participating in the event (sender, recipient, grantee, etc.)
Use senderAddress filter when you want only transactions you initiated, excluding those where you were merely a recipient.
Troubleshooting
| Issue | Solution |
|---|---|
| Balance mismatch | Check for pending transactions not yet indexed |
| Missing events | Verify event name filter matches exactly |
| Events show wrong amounts | Amounts are in wei; apply token decimals |
| Stale data | Indexer latency ~2 seconds; wait and retry |
| Too many results | Use pagination with limit and offset |
Related operations
- Transaction tracking - Check transaction status by hash
- Error handling - Handle API errors
- API reference - Complete endpoint documentation