Consolidations
A consolidation group is a collection of analyses — typically 3–6 months of statements from the same customer — merged into a single ledger with cross-statement metrics.
This is the canonical shape for loan-underwriting integrations.
Why consolidate?
A single monthly statement is a snapshot. A loan decision needs the trend: 3-month average inflow, monthly volatility, peak-vs-trough balance, repeat-counterparty patterns. Consolidations give you all of that at the group level rather than reconstructing across individual analyses.
Create a group
/api/consolidations{
"name": "Budi Santoso — Loan #001",
"description": "5-month underwriting submission",
"externalRef": "loan-app-2026-05-24-001",
"customerId": "cus_01HXY..."
}Or auto-create at upload time with auto_create_group=true (see Upload PDF).
Add analyses to a group
If you've already uploaded analyses and want to group them after the fact, link them:
curl -X PATCH ".../api/analyses/ana_01HXY..." \
-H "Authorization: Bearer $QE_API_KEY" \
-d '{ "consolidationGroupId": "cgr_01HXY..." }'(Note: PATCH /api/analyses/{id} is implicit in the platform — exposed via the dashboard if not yet via API.)
Read the consolidated view
/api/consolidations/{id}/consolidated{
"data": {
"accountsConsolidated": 5,
"totalInflow": 125000000,
"totalOutflow": 92000000,
"netMovement": 33000000,
"averageMonthlyInflow": 25000000,
"averageMonthlyOutflow": 18400000,
"periodStart": "2026-01-01T00:00:00Z",
"periodEnd": "2026-05-31T23:59:59Z",
"transactionCount": 247,
"anomalyCount": 3,
"anomalies": [
{
"transactionId": "txn_01HXY...",
"type": "balance_mismatch | sudden_burst | doctored_row | suspicious_round",
"severity": "low | medium | high",
"description": "Balance after IDR 24.5M doesn't reconcile with prior + amount"
}
],
"affordabilityScore": 78,
"authenticityScore": 92,
"monthlyBuckets": [
{
"month": "2026-01",
"inflow": 22000000,
"outflow": 16500000,
"netMovement": 5500000,
"balanceEnd": 8500000,
"averageBalance": 7200000,
"transactionCount": 48
},
...
],
"categoryBreakdown": {
"salary": { "credits": 75000000, "debits": 0, "count": 5 },
"transfer_external":{ "credits": 28000000, "debits": 12000000, "count": 87 },
"ecommerce": { "credits": 0, "debits": 18500000, "count": 42 },
"loan_repayment": { "credits": 0, "debits": 24000000, "count": 12 },
...
},
"topCounterparties": [
{ "name": "PT XYZ", "count": 5, "totalAmount": 75000000, "direction": "in" },
{ "name": "Tokopedia", "count": 35, "totalAmount": 15500000, "direction": "out" }
]
}
}Key metrics for underwriting
| Metric | Why it matters |
|---|---|
averageMonthlyInflow | Repayment-capacity baseline. Loan tenor × monthly repayment should fit comfortably under this. |
affordabilityScore | Pre-computed: 78 means "78th percentile across our customer base." |
authenticityScore | Watch for < 80 — possible doctored statement. Cross-check anomalies. |
categoryBreakdown.loan_repayment | Existing debt load. Tells you what they're already paying. |
monthlyBuckets consistency | High variance = unstable income, treat with care. |
topCounterparties | Are inflows mostly salary (good) or single-source from one entity (concentrated)? |
List analyses in a group
/api/consolidations/{id}/analysesReturns each member analysis with its summary fields. Use this when you want per-statement detail rather than the merged view.
Update / delete a group
/api/consolidations/{id}Update name, description, externalRef, customerId.
/api/consolidations/{id}Deletes the group. Does not delete the member analyses — they just become orphaned (no group). To delete the analyses too, pass ?cascade=true.
Webhook on group completion
Subscribe to consolidation.completed — fires when the last queued analysis in a group transitions to completed. Most underwriting pipelines key off this rather than tracking per-analysis state.