Guides
How to bulk-import your existing deal portfolio into SmartMCA
This guide covers importing an existing deal portfolio from a spreadsheet, legacy system, or another LMS into SmartMCA via the API.
For bulk imports, follow this order to satisfy foreign key dependencies:
Map your existing fields to SmartMCAβs schema. Key fields:
| Your Field | SmartMCA Field | Notes |
|---|---|---|
| Company Name | legalName | Required |
| DBA | dba | Optional |
| EIN/Tax ID | ein | Used for dedup |
| Funded Amount | fundedAmount | Decimal |
| Purchase Amount | purchaseAmount | Decimal (funded Γ factor rate) |
| Total Collected | totalCollected | Sum of all payments |
| Funded Date | fundedDate | ISO date |
| Status | status | Must match: active, paidOff, defaulted, etc. |
| Payment Frequency | paymentFrequency | daily, weekly, monthly |
async function importMerchant(row) {
const res = await fetch('https://api.smartmca.com/api/public/v1/merchants', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': `import-merchant-${row.ein}`,
},
body: JSON.stringify({
legalName: row.companyName,
dba: row.dba,
ein: row.ein,
industry: row.industry,
address: row.address,
city: row.city,
state: row.state,
zip: row.zip,
phone: row.phone,
}),
});
if (!res.ok) {
const err = await res.json();
console.error(`Failed to import merchant ${row.companyName}:`, err);
return null;
}
return (await res.json()).data;
}
async function importDeal(row, merchantId) {
const res = await fetch('https://api.smartmca.com/api/public/v1/deals', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': `import-deal-${row.legacyDealId}`,
},
body: JSON.stringify({
merchantId,
fundedAmount: row.fundedAmount,
purchaseAmount: row.purchaseAmount,
fundedDate: row.fundedDate,
paymentFrequency: row.paymentFrequency,
paymentAmount: row.dailyPayment,
status: mapStatus(row.status),
}),
});
if (!res.ok) {
const err = await res.json();
console.error(`Failed to import deal ${row.legacyDealId}:`, err);
return null;
}
return (await res.json()).data;
}
function mapStatus(legacyStatus) {
const mapping = {
'Active': 'active',
'Paid Off': 'paidOff',
'Paid-Off': 'paidOff',
'Default': 'defaulted',
'Collections': 'inCollections',
'Legal': 'inLegal',
'Settled': 'settled',
'Refinanced': 'refinanced',
};
return mapping[legacyStatus] || 'active';
}
For each deal, import the historical payment records:
async function importPayments(dealId, payments) {
for (const payment of payments) {
await fetch(`https://api.smartmca.com/api/public/v1/deals/${dealId}/payments`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': `import-payment-${payment.legacyId}`,
},
body: JSON.stringify({
amount: payment.amount,
type: payment.type, // "collection", "fee", "adjustment"
effectiveDate: payment.date,
description: payment.memo,
}),
});
// Respect rate limits β small delay between requests
await new Promise(r => setTimeout(r, 100));
}
}
const csv = require('csv-parse/sync');
const fs = require('fs');
async function runImport() {
const merchants = csv.parse(fs.readFileSync('merchants.csv'), { columns: true });
const deals = csv.parse(fs.readFileSync('deals.csv'), { columns: true });
const payments = csv.parse(fs.readFileSync('payments.csv'), { columns: true });
// Phase 1: Merchants
const merchantMap = {}; // legacyId β smartMcaId
for (const row of merchants) {
const result = await importMerchant(row);
if (result) merchantMap[row.legacyId] = result.id;
}
console.log(`Imported ${Object.keys(merchantMap).length} merchants`);
// Phase 2: Deals
const dealMap = {}; // legacyDealId β smartMcaDealId
for (const row of deals) {
const merchantId = merchantMap[row.legacyMerchantId];
if (!merchantId) {
console.warn(`Skipping deal ${row.legacyDealId} β merchant not found`);
continue;
}
const result = await importDeal(row, merchantId);
if (result) dealMap[row.legacyDealId] = result.id;
}
console.log(`Imported ${Object.keys(dealMap).length} deals`);
// Phase 3: Payments
let paymentCount = 0;
for (const row of payments) {
const dealId = dealMap[row.legacyDealId];
if (!dealId) continue;
await importPayments(dealId, [row]);
paymentCount++;
}
console.log(`Imported ${paymentCount} payments`);
}
runImport().catch(console.error);
For large imports (thousands of records):
Idempotency-Key headers so you can safely retry on failuresawait new Promise(r => setTimeout(r, 1000))After import, verify:
totalCollected on each deal matches sum of imported paymentsoutstandingBalance = purchaseAmount - totalCollected