This guide walks you through the basic workflow for using Formance Reconciliation: creating a policy, running reconciliations, and interpreting results.
reconciliation:read, reconciliation:write)Step 1: Create a Reconciliation Policy#
A policy defines which ledger accounts to compare with which cash pools. Create your first policy:
cat > policy.json << 'EOF'
{
"name": "Daily Stripe Reconciliation",
"ledgerName": "main",
"ledgerQuery": {
"account": "world",
"asset": "USD/2"
},
"paymentsPoolID": "your-stripe-cash-pool-id"
}
EOF
fctl reconciliation policies create policy.jsonResponse:
{
"data": {
"id": "01HGW4D6YK8QHZ9VC1T2MXBZ3F",
"name": "Daily Stripe Reconciliation",
"createdAt": "2024-01-15T10:30:00Z",
"ledgerName": "main",
"ledgerQuery": {
"account": "world",
"asset": "USD/2"
},
"paymentsPoolID": "your-stripe-cash-pool-id"
}
}Save the policy id - you'll need it for running reconciliations.
Step 2: Run Your First Reconciliation#
Execute a reconciliation using your policy to compare balances at a specific point in time:
fctl reconciliation policies reconcile 01HGW4D6YK8QHZ9VC1T2MXBZ3F 2024-01-15T23:59:59Z 2024-01-15T23:59:59ZBoth timestamps must be in the past. You can specify different timestamps for ledger and payments to accommodate processing delays between systems.
Response (Balances Match):
{
"data": {
"id": "01HGW4D7SXRQP8M2N6V1K9J4B3",
"policyID": "01HGW4D6YK8QHZ9VC1T2MXBZ3F",
"createdAt": "2024-01-16T09:15:30Z",
"reconciledAtLedger": "2024-01-15T23:59:59Z",
"reconciledAtPayments": "2024-01-15T23:59:59Z",
"status": "OK",
"ledgerBalances": {
"USD/2": "100000"
},
"paymentsBalances": {
"USD/2": "100000"
},
"driftBalances": {
"USD/2": "0"
}
}
}Response (Drift Detected):
{
"data": {
"id": "01HGW4D7SXRQP8M2N6V1K9J4B3",
"policyID": "01HGW4D6YK8QHZ9VC1T2MXBZ3F",
"createdAt": "2024-01-16T09:15:30Z",
"reconciledAtLedger": "2024-01-15T23:59:59Z",
"reconciledAtPayments": "2024-01-15T23:59:59Z",
"status": "NOT_OK",
"ledgerBalances": {
"USD/2": "100000"
},
"paymentsBalances": {
"USD/2": "99950"
},
"driftBalances": {
"USD/2": "50"
},
"error": "balance drift for asset USD/2"
}
}Step 3: Interpret Results#
Successful reconciliation (status: "OK"): All balances match, driftBalances shows zero.
Drift detected (status: "NOT_OK"): driftBalances shows discrepancies per asset, error field describes the issue. Common causes include balance differences, missing assets, or asset count mismatches.
Step 4: View Historical Reconciliations#
List all reconciliations to track your reconciliation history:
curl -X GET $FORMANCE_API_URL/api/reconciliation/reconciliationsOr get a specific reconciliation by ID:
curl -X GET $FORMANCE_API_URL/api/reconciliation/reconciliations/01HGW4D7SXRQP8M2N6V1K9J4B3