Importing Loans from a Spreadsheet
If your loans live in a spreadsheet, or in software that can export one, the spreadsheet import brings your developments, tracts, borrowers, and loans into Lendiom in one guided run. You fill in up to five CSV files against Lendiom's own column layout, upload them, review what will be created or matched, then start the import.
It lives at Org Settings → Import/Export. Each import is its own record with five steps: Source, Upload, Analyze, Review, Import. Nothing is written to your organization until you start the import at the end.
Coming from MoneyLender Professional 3 instead? See Importing Your Existing Portfolio, which reads the files MoneyLender exports directly, notes and attachments included.
Before you start
- Loans import from their balances unless you supply the payment history. Without a transactions.csv, each loan starts from the principal balance and next due date you give it, with an empty history in Lendiom. Add a transactions.csv holding every payment since the loan closed and Lendiom replays that history onto the loan instead, so the borrower sees their past payments in Lendiom Pay.
- You need the data-import permission. Of the seeded roles, only admin holds it. See Roles and Permissions.
- One import runs at a time per organization.
- Excel files are not read directly. Save each sheet as CSV (File → Save As → CSV in Excel, or File → Download → CSV in Google Sheets) and keep the file name the wizard expects.
Step 1: Choose the spreadsheet source
Click New Import and pick Spreadsheet (CSV files) as the source. The choice between replaying the full history and importing balances only comes later, on the confirmation screen, and only when you have staged a transactions.csv.

Step 2: Prepare and upload your files
The upload step documents every column for each of the five files and offers a Template download per file. A template is the header row plus one example row you overwrite. Fill in whichever files you need, save them as CSV under the same names, and drop them into the uploader. Any one file imports on its own, so you can bring inventory first and loans later.
Importing in stages
You do not have to bring everything in one run. A common order is inventory first, then clients, then loans. Two things make that work:
- Loans need their borrowers in the same run, or already in Lendiom. A loan names its borrower by
client_id. Include clients.csv with the loans and give each row an email; a client who already exists with that email is matched instead of duplicated. If you leave clients.csv out, eachclient_idappears under Borrowers with no name, and you match it to an existing client or type a name before you can continue. - Loans find their tracts in your inventory. A tract that came over in an earlier run, or that you created by hand, matches by development name and tract number, so inventory.csv is not needed again.
transactions.csv and property_taxes.csv always travel with loans.csv, since their rows belong to the loans in that file.
If you ever undo staged imports, delete them in reverse order: the loans import first, then clients, then inventory. Deleting an earlier import while a later loan still holds its tract or its client leaves those records in place, and that import cannot be deleted again afterwards.

Column order does not matter, columns you do not need can be left blank or removed, and extra columns are ignored. Money can be written as 45000 or $45,000.00 . Re-uploading a file replaces the previous copy.
Dates can be written the way Excel writes them: 2023-06-15 , 6/15/2023 (also with dashes or dots), 15-Jun-2023 , June 15, 2023 , or the raw number Excel exports from an unformatted date cell. If a file uses day/month/year order, the import notices when any date has a day above 12 and reads the whole file that way; the review then says so, so spot-check one date. In Excel, File → Save As → CSV UTF-8 (Comma delimited) produces a file the import reads without any of this guesswork.
inventory.csv, one row per tract
A development that does not exist yet is created; one that already exists is reused by name. A tract that already exists is left exactly as it is.
| Column | Required | What goes in it |
|---|---|---|
development |
Yes | The development (subdivision) the tract belongs to, matched to your existing developments by name. |
tract_number |
Yes | The tract (lot) number, a whole number. |
label |
The tract's display name. Defaults to "Tract 12" style. | |
acres |
For a financed tract | The tract's acreage. A tract a loan will be written against must have it; a blank cell is flagged in the review and holds the import until you fill it in. An existing tract without acreage is flagged the same way and is fixed on the tract in Lendiom. |
clients.csv, one row per borrower
The client_id is any unique value of your choosing; loans.csv uses it to say who the borrower is. A row whose email already belongs to one of your clients is matched to that client instead of creating a duplicate.
| Column | Required | What goes in it |
|---|---|---|
client_id |
Yes | Your unique identifier for the client. |
first_name, last_name |
Unless company is set | The borrower's name. middle_name is optional. |
company |
The business name when the client is a company rather than a person. | |
email, phone, phone_2 |
Contact details. Email is what matches an existing client. | |
tax_id, tax_id_type |
The borrower's SSN or the company's EIN, nine digits with or without dashes. Left blank, the type is an SSN for a person and an EIN for a company row with no contact name; set tax_id_type to ein or ssn to say so yourself, for example on a company row that also names its contact. A value that is not nine digits is ignored and flagged. |
|
date_of_birth |
The borrower's date of birth. | |
address_line_1, address_line_2, city, state, zip, county |
Physical address. State as a two-letter code or its full name. | |
mailing_address_line_1, mailing_address_line_2, mailing_city, mailing_state, mailing_zip |
Mailing address, only when it differs from the physical one. | |
notes |
Free text, recorded as a note on the client. |
loans.csv, one row per loan
Each loan names its borrower by client_id and its property by development plus tract_numbers . The tract can come from inventory.csv in the same import or from inventory you already have in Lendiom.
| Column | Required | What goes in it |
|---|---|---|
loan_id |
Yes | Your unique identifier for the loan. Also used as the loan's label unless you set label. |
client_id |
Yes | The borrower's client_id from clients.csv. |
development, tract_numbers |
Yes | The financed tract. Separate several tract numbers with semicolons, for example 5;6. |
status |
open (the default), paid-off, or canceled. |
|
sales_price, down_payment |
Price yes | The financed amount is the sales price minus the down payment. |
interest_rate, term_months |
Yes | Annual rate as a percentage (for example 8.5) and the loan length in months. |
interest_formula |
How interest accrues. Leave it blank for Lendiom's default, one month of interest per scheduled payment. Enter 30/360, actual/360, or actual/365 for a loan that accrues interest daily on that day-count basis. |
|
payment_amount |
The monthly principal-and-interest payment. Left blank, Lendiom computes it from the terms. | |
closing_date, first_payment_date |
Yes | When the loan closed and when the first payment was due. |
principal_balance, next_payment_due |
For open loans | The current principal balance and the next unpaid due date. |
last_payment_date, interest_paid, interest_paid_ytd |
Snapshot figures carried onto the loan's existing-loan details. | |
escrow_payment, escrow_balance |
The monthly escrow amount collected on top of the payment, and the current escrow balance. | |
late_fee_amount |
The loan's fixed late fee. Blank falls back to your organization's default, or to the default you set during the review. | |
paid_off_date |
For paid-off loans | When the loan was paid off. last_payment_date is accepted in its place. |
transactions.csv, one row per payment or fee (optional)
Skip this file if you only want current balances. Include it when you want the loan's payment history in Lendiom. Each row names its loan by loan_id from loans.csv. The down payment is not a row here; it comes from loans.csv.
| Column | Required | What goes in it |
|---|---|---|
loan_id |
Yes | The loan's loan_id from loans.csv. |
date |
Yes | When it happened, in any of the date formats above. |
type |
payment (the default when blank), principal-payment, payoff, late-fee, waive, or adjustment. |
|
amount |
Yes | Positive for payments, fees, waives, and payoffs. An adjustment reduces principal and must be negative. |
method, reference, memo |
How it was paid (cash, check, ach, card, and so on), the check number or confirmation code, and a free-text comment. All three are kept on the transaction. | |
to_principal, to_interest, to_escrow |
How your old system split the payment. Lendiom allocates every payment by the loan's own rules and uses these only to check the file against the loan's balances. When every payment on a loan carries to_interest, interest paid to date is taken from those splits instead of loans.csv. |
The history has to be complete. Lendiom replays the rows in date order from the first payment date and then compares the result with the principal_balance and next_payment_due in loans.csv. A loan whose rows cover every payment since it closed imports with its full history. A loan with only some of its payments, or none at all, is flagged in the review and imports from its balances instead, so a partial file never leaves a loan behind on its due date. Payments dated in the future are ignored.
The replayed history rarely lands on the exact balance, because the old system may have rounded or charged interest a little differently. A replay that ends above your principal_balance is adjusted down to match. One that ends up to $10 below it is kept as is, with a note on the loan recording the balance you reported. Further below than that, the loan imports from its balances instead of its history.
property_taxes.csv, one row per loan per tax year (optional)
Include this file to bring property tax history over. Each row is one tract's share of one year's tax bill and what the borrower has paid toward it. Rows for the same development and year become one property tax record, so you do not need the development's total bill; the record's total is the sum of the shares you give it.
| Column | Required | What goes in it |
|---|---|---|
loan_id |
Yes | The loan's loan_id from loans.csv. The tax belongs to the tract it finances. |
tract_number |
When the loan finances several tracts | Which of the loan's tracts the share is for. |
tax_year |
Yes | The tax year, as a four-digit year. |
amount |
Yes | The tract's share of that year's bill. |
due_date |
When the tax was due. Blank means December 31 of the tax year. | |
amount_paid, date_paid |
How much the borrower has paid toward the share and when. A payment without a date is dated on the due date. | |
method, memo |
How it was paid and a free-text comment, kept on the payment. |
A paid share is recorded as a property tax payment on the loan. A share that is still owed imports as owed, so the borrower sees it in Lendiom Pay. The review lists every such row under Property taxes and you can Skip any that should not be billed.
Once at least one file shows as staged, click Analyze the files.

Step 3: Analyze
Analysis runs in the background and usually takes a few seconds. It reads the files, matches developments and tracts against your inventory, matches borrowers by email, and checks every row. Nothing is written yet, and analyzing again is always safe.
If a file cannot be read at all (a missing required column, or a file that is not comma-separated), the analysis stops and tells you which file and what was wrong. Click Replace files, upload the corrected file under the same name, and analyze again.
Step 4: Review
The review shows exactly what the import will do, and every decision you make here autosaves.
Inventory
The Inventory tab lists each development and tract from inventory.csv with its outcome: Will be created or Already exists. This tab is read-only. If a row is wrong, fix it in the file and use Replace files (below).

Loans
Each loan shows its borrower, status, matched tract, principal, and a match confidence. A tract the import itself will create is marked (new). Two things need your attention before you can continue:
- Unmatched: the development or tract number was not found in inventory.csv or your existing inventory. Use Fix match to pick the tract, or Skip the loan.
- Conflict: the tract already has a live loan, or another loan in the same file claims it. Fix the match or skip one of them.
When a transactions.csv is staged, each loan also shows how many payments, fees, and waivers were read for it. A loan whose history looks incomplete, or whose recorded history does not add up to the balance you reported, is flagged here. It still imports, from its balances rather than its history.

Borrowers
Each borrower is either created as a new client or matched to an existing one by email. You can change the action per borrower, pick a different existing client to match, or skip a borrower entirely. A borrower no loan references is flagged for your awareness and still created.
A loan whose client_id has no row in clients.csv, or a loans.csv uploaded without a clients file at all, adds a borrower with no name to this tab. Pick Match existing client and choose the client, or type a first and last name (or a company) to create one; every loan naming that id follows. This is how you import loans against clients that are already in Lendiom, or that came over in an earlier import. Matching is by email only, never by name.
Row problems in clients.csv are handled here too:
- No name. A row with neither a first and last name nor a company shows First name, Last name, and Company boxes right in the table. Type the name and the row imports under it.
- Repeated client_id. Loans reference the first row with that id, so the repeat is set to Skip. If it is really a different person, change its action to Create new client, or give it its own id and use Replace files.
- Blank client_id. No loan can reference the row, so it simply imports as a client of its own.
- Email shared by two existing clients. The import will not guess which one; the row is set to Create new client with a note. Switch it to Match existing client and pick the right one if it should match.

Property taxes
This tab appears when property_taxes.csv is staged. Each row shows the loan, year, amount, what was paid, and what is still owed. A row with a balance owed is flagged, because that balance will be billed to the borrower; tick Skip to leave it out. A payment on a later year while an earlier year is still owed is flagged too, since Lendiom applies tax payments to the oldest year owed first.
Matching & settings
A spreadsheet does not carry your late-fee grace period, so the review asks you to confirm the Late fee grace period that applies to the imported loans. If your organization has no default late fee and some loans left late_fee_amount blank, you also set a Default late fee for the import. Click Save & re-run matching after changing either. An import with no loans skips this section.
Fixing a file
Some problems can only be fixed in the file itself: a tract number that is not a whole number, a duplicate loan_id , a loan whose status is not one of the three allowed values, a balance larger than the financed amount. The review lists them under Before you can continue, each with the file and line number. Correct the row, then click Replace files at the top of the review to upload the corrected file under the same name. That replaces the staged copy and clears the analysis, so you analyze again. Your grace days, skipped loans, and fixed matches are kept where they still apply.

Step 5: Confirm and import
The confirmation screen totals what will happen: developments and tracts to create, clients to create or match, and loans by status. With a transactions.csv staged, this screen also asks how to import the loans: Full history replay recreates every transaction row on each loan, and Balances only ignores the history and starts each loan from its balances. Type IMPORT to start. The import creates inventory first, then clients, then loans, and keeps running on the server even if you close the page. You can come back to it from the imports list.

After the import
Property tax years the import recorded appear on each development under Property Taxes, with the borrower's payments on the loan.
The results screen lists every record with its outcome, and you can download the whole ledger as CSV. Each imported loan carries a system note saying it was imported from a spreadsheet, and its story starts from the balances you supplied, or from the replayed payments when you provided a transactions.csv. The results list shows which of the two each loan received.

A few things worth checking afterwards:
- Spot-check a couple of loans: the payment amount, next due date, and escrow balance should match your spreadsheet.
- Re-enable any organization automation you turned off for the import, such as loan document automation.
- Invite your borrowers to Lendiom Pay so they can enroll their payment methods. Card and bank details never move over from another system.
Each import can be deleted from its results screen while nothing else depends on its records. If you imported in stages, delete the latest import first (see Importing in stages above).