API Reference
Bank statement analysis and transaction classification endpoints
Analyze bank statements and classify transactions using the SmartScrub pipeline. Supports two modes: PDF upload (always async) and JSON transactions (sync for ≤500 transactions, async for >500).
POST /api/public/v1/analysis/bank-statements
Upload one or more PDF bank statements for async analysis. Files are parsed, transactions extracted, classified, and MCA positions detected.
Content-Type: multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
files | file[] | Yes | PDF files (max 10, each up to 50 MB) |
merchantId | string | No | Link analysis to a merchant |
dealId | string | No | Link analysis to a deal |
Required Scope: analysis:trigger
Response 202 Accepted
{
"data": {
"id": "clx_abc123",
"status": "pending",
"mode": "pdf"
}
}
PDF analysis is always asynchronous. Poll GET /analysis/{id} for results.
curl -X POST https://api.smartmca.com/api/public/v1/analysis/bank-statements \
-H "Authorization: Bearer smca_live_..." \
-F "files=@january-statement.pdf" \
-F "files=@february-statement.pdf" \
-F "merchantId=merch_123"
const form = new FormData();
form.append('files', fs.createReadStream('january-statement.pdf'));
form.append('files', fs.createReadStream('february-statement.pdf'));
form.append('merchantId', 'merch_123');
const res = await fetch('https://api.smartmca.com/api/public/v1/analysis/bank-statements', {
method: 'POST',
headers: { 'Authorization': 'Bearer smca_live_...' },
body: form,
});
const { data } = await res.json();
// data.id → use to poll for results
import requests
files = [
('files', ('jan.pdf', open('january-statement.pdf', 'rb'), 'application/pdf')),
('files', ('feb.pdf', open('february-statement.pdf', 'rb'), 'application/pdf')),
]
resp = requests.post(
'https://api.smartmca.com/api/public/v1/analysis/bank-statements',
headers={'Authorization': 'Bearer smca_live_...'},
files=files,
data={'merchantId': 'merch_123'},
)
analysis_id = resp.json()['data']['id']
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(File.ReadAllBytes("january-statement.pdf")),
"files", "january-statement.pdf");
form.Add(new StringContent("merch_123"), "merchantId");
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "smca_live_...");
var resp = await client.PostAsync(
"https://api.smartmca.com/api/public/v1/analysis/bank-statements", form);
POST /api/public/v1/analysis/transactions
Submit pre-parsed transactions as JSON. Transactions are classified inline.
Required Scope: analysis:trigger
{
"merchantId": "merch_123",
"dealId": "deal_456",
"transactions": [
{
"date": "2026-01-05",
"description": "DEPOSIT - Wire Transfer",
"amount": 15000,
"type": "credit"
},
{
"date": "2026-01-06",
"description": "ACH DEBIT - MCA Funding Co",
"amount": 750,
"type": "debit"
}
]
}
| Field | Type | Required | Description |
|---|---|---|---|
transactions | array | Yes | Transaction records |
transactions[].date | string | Yes | ISO date (YYYY-MM-DD) |
transactions[].description | string | Yes | Transaction description |
transactions[].amount | number | Yes | Absolute amount |
transactions[].type | string | Yes | credit or debit |
merchantId | string | No | Link to a merchant |
dealId | string | No | Link to a deal |
200 OK (≤500 transactions){
"data": {
"id": "clx_abc123",
"status": "completed",
"mode": "transactions",
"dealId": "deal_456",
"merchantId": "merch_123",
"startedAt": "2026-03-04T10:00:00Z",
"completedAt": "2026-03-04T10:00:02Z",
"error": null,
"summary": {
"totalTransactions": 120,
"dateRange": { "start": "2026-01-01", "end": "2026-03-01" },
"totalCredits": 450000,
"totalDebits": 380000,
"avgDailyBalance": 42500,
"mcaPositionsDetected": 3,
"revenueSourcesDetected": 45
},
"mcaPositions": [
{
"funderName": "MCA Funding Co",
"frequency": "daily",
"avgPayment": 750,
"totalPayments": 15000,
"transactionCount": 20,
"confidence": 0.95
}
],
"classifications": {
"revenue": { "total": 300000, "transactionCount": 45 },
"mcaRepayment": { "total": 45000, "transactionCount": 60 },
"loanPayment": { "total": 12000, "transactionCount": 6 },
"operatingExpense": { "total": 180000, "transactionCount": 80 },
"transfer": { "total": 50000, "transactionCount": 10 },
"otherCredit": { "total": 25000, "transactionCount": 8 },
"otherDebit": { "total": 8000, "transactionCount": 5 }
},
"transactions": [
{
"date": "2026-01-05",
"description": "DEPOSIT - Wire Transfer",
"amount": 15000,
"type": "credit",
"classification": "businessRevenue",
"subClassification": null,
"vendor": null,
"confidence": 0.92,
"classificationSource": "pattern"
}
]
}
}
202 Accepted (>500 transactions){
"data": {
"id": "clx_abc123",
"status": "pending",
"mode": "transactions",
"dealId": "deal_456",
"merchantId": "merch_123",
"startedAt": "2026-03-04T10:00:00Z",
"completedAt": null,
"error": null,
"summary": null,
"mcaPositions": null,
"classifications": null,
"transactions": null
}
}
GET /api/public/v1/analysis/{analysisId}
Returns the status and results for an analysis. When status is completed, the full response includes summary, mcaPositions, classifications, and transactions.
Required Scope: analysis:read
| Status | Description |
|---|---|
pending | Queued, not yet started |
processing | Pipeline is running |
completed | Analysis finished successfully |
failed | Pipeline encountered an error |
| Category | Direction | Description |
|---|---|---|
businessRevenue | credit | Operating revenue deposits |
mcaFunding | credit | MCA advance disbursements |
loanDisbursement | credit | Loan proceeds |
transferIn | credit | Internal transfers in |
refund | credit | Refunds received |
mcaRepayment | debit | MCA daily/weekly debits |
loanPayment | debit | Loan repayments |
businessExpense | debit | Operating expenses |
payroll | debit | Payroll debits |
taxPayment | debit | Tax payments |
nsfFee | debit | Insufficient fund fees |
bankFee | debit | Bank service fees |
transferOut | debit | Internal transfers out |
| Source | Description |
|---|---|
vendor_rules | Matched a known vendor pattern |
pattern | Matched keyword or behavioral rule |
llm | Classified by AI/LLM |
funder_db | Matched known funder database |
default | Default classification applied |
GET /api/public/v1/analysis
Required Scope: analysis:read
| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number |
limit | number | 20 | Items per page (max 100) |
deal_id | string | — | Filter by deal |
merchant_id | string | — | Filter by merchant |
status | string | — | Filter: pending, processing, completed, failed |
created_after | string | — | ISO datetime |
created_before | string | — | ISO datetime |
Response:
{
"data": [
{
"id": "clx_abc123",
"mode": "transactions",
"dealId": "deal_456",
"merchantId": "merch_123",
"status": "completed",
"statementCount": 3,
"createdAt": "2026-03-04T10:00:00Z"
}
],
"meta": {
"pagination": {
"page": 1,
"limit": 20,
"total": 42,
"totalPages": 3
}
}
}
DELETE /api/public/v1/analysis/{analysisId}
Deletes all analysis data for this ID (statements, transactions, detected positions). If the analysis is still running, it will be cancelled first.
Required Scope: analysis:trigger
Response 200 OK
{
"deleted": true,
"id": "clx_abc123"
}
| Action | Scope |
|---|---|
| Read analysis status & results | analysis:read |
| Trigger analysis, delete | analysis:trigger |