Guides
How to use the SmartScrub analysis API for bank statement classification
This guide covers both analysis modes — PDF upload and JSON transactions — and how to interpret the results for MCA underwriting decisions.
| Mode | When to use | Response |
|---|---|---|
| PDF upload | You have raw bank statement PDFs | Always async (202) |
| JSON transactions | You’ve already parsed the transactions | Sync if ≤500 txns, async if >500 |
Upload PDF bank statements and let SmartScrub handle parsing and classification.
const form = new FormData();
form.append('files', fs.createReadStream('jan-2026.pdf'));
form.append('files', fs.createReadStream('feb-2026.pdf'));
form.append('files', fs.createReadStream('mar-2026.pdf'));
form.append('merchantId', 'merch_123');
form.append('dealId', 'deal_456');
const res = await fetch('https://api.smartmca.com/api/public/v1/analysis/bank-statements', {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}` },
body: form,
});
const { data } = await res.json(); // { id, status: "pending", mode: "pdf" }
const analysisId = data.id;
async function pollAnalysis(analysisId) {
while (true) {
const res = await fetch(
`https://api.smartmca.com/api/public/v1/analysis/${analysisId}`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
);
const { data } = await res.json();
if (data.status === 'completed') return data;
if (data.status === 'failed') throw new Error(data.error);
// Wait 5 seconds before next poll
await new Promise(r => setTimeout(r, 5000));
}
}
const result = await pollAnalysis(analysisId);
If you’ve already extracted transactions (from your own parser, a banking API, or Plaid), submit them directly:
const res = await fetch('https://api.smartmca.com/api/public/v1/analysis/transactions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
merchantId: 'merch_123',
transactions: parsedTransactions.map(t => ({
date: t.date, // "2026-01-15"
description: t.memo, // "ACH DEBIT - FUNDER CO"
amount: Math.abs(t.amount),
type: t.amount > 0 ? 'credit' : 'debit',
})),
}),
});
const { data } = await res.json();
if (data.status === 'completed') {
// Sync response — results are already included
processResults(data);
} else {
// Async — poll for results
const result = await pollAnalysis(data.id);
processResults(result);
}
The mcaPositions array identifies existing MCA advances detected in the bank statements:
for (const position of result.mcaPositions) {
console.log(`Funder: ${position.funderName}`);
console.log(` Frequency: ${position.frequency}`);
console.log(` Avg payment: $${position.avgPayment.toFixed(2)}`);
console.log(` Total paid: $${position.totalPayments.toFixed(2)}`);
console.log(` Confidence: ${(position.confidence * 100).toFixed(0)}%`);
}
Use this to assess:
The classifications object groups transactions into buckets:
const { classifications } = result;
const totalRevenue = classifications.revenue.total;
const totalMCA = classifications.mcaRepayment.total;
const mcaBurden = (totalMCA / totalRevenue * 100).toFixed(1);
console.log(`Revenue: $${totalRevenue}`);
console.log(`MCA repayments: $${totalMCA} (${mcaBurden}% of revenue)`);
console.log(`Operating expenses: $${classifications.operatingExpense.total}`);
Each transaction includes its classification and confidence:
// Find high-confidence revenue transactions
const verifiedRevenue = result.transactions
.filter(t => t.classification === 'businessRevenue' && t.confidence > 0.8);
// Find NSF/overdraft events
const nsfEvents = result.transactions
.filter(t => t.classification === 'nsfFee' || t.classification === 'bankFee');
console.log(`Verified revenue transactions: ${verifiedRevenue.length}`);
console.log(`NSF/overdraft events: ${nsfEvents.length}`);
When you provide a dealId, the analysis is linked to the deal. You can then access it through the underwriting endpoints:
// Get all underwriting results for a deal (includes SmartScrub + other tools)
const results = await fetch(
`https://api.smartmca.com/api/public/v1/deals/${dealId}/underwriting/results`,
{ headers: { 'Authorization': `Bearer ${API_KEY}` } }
).then(r => r.json());
Delete analysis data when no longer needed:
await fetch(`https://api.smartmca.com/api/public/v1/analysis/${analysisId}`, {
method: 'DELETE',
headers: { 'Authorization': `Bearer ${API_KEY}` },
});