Skip to main content
GET
List every loan of one lender
Early access: while the developer tier is in beta, the API serves this route to Investorlift’s team and trusted partners. Investorlift will restrict the route further before it opens to every key.
A page of lender loan rows. Every row has lender_id equal to the path id. With Accept: text/csv, the API returns the whole filtered window as a file (below).

Use it when

The loans table of a lender card. Also the feed a lender customer pulls by window (recorded_from and recorded_to). The customer pulls it to see what a competitor funded, where, and on what terms, as a page or as a spreadsheet. For the liens of one parcel, use GET /v1/properties/{property_id}/financing. Every lender name there now carries the lender_id that opens this route. For the lenders active in a place, use GET /v1/lenders.

Read the response

  • One row per instrument by default. source=both serves the open row where the instrument has one, else its recorded slot. source=open lists the open lien positions alone. source=recorded lists the history slots as the history holds them, duplicated slots included. loan_key joins the two views.
  • The rows are the lender of record’s. The open table can attribute an instrument to this lender while the history names another lender. Examples: an insurer against its servicer, or a spelling not yet joined. Such an instrument is on the other lender’s page. So the profile’s n_open_liens can exceed the open rows here by n_loans_lender_disagrees.
  • The filters read the row. product, term_band, loan_type and property_type filter as the file writes them. amount_min and amount_max filter on loan_amount, and unpriced rows drop out. zip and city filter on the parcel’s ZIP and city.
  • Since 0.16.0 the filters also include purpose (PURCHASE, NOT_PURCHASE, UNKNOWN), outcome, deal_kind and investor_id. deal_kind takes the six deal kinds of the deal a loan is tied to. investor_id keeps the loans whose main borrower resolves to that investor.
  • Since 0.19.0 foreclosed=true keeps the rows a take-back deed followed, and false keeps the rest. cell keeps the rows in one H3 cell, the index as hex, at res 7 or 8. A geometry keeps the rows around a point: lat and lng with radius_miles, a bbox, or property_id. The API resolves the geometry to the H3 res-8 cells whose centre lies inside it. Each cell is about a third of a square mile. So the edge of the geometry is a hex boundary, not the circle.
  • If you send a geometry beside cell, zip or city, the API answers 400 validation_error with code geography_conflict. With a geometry, a zip or a city, meta.geometry echoes the shape you asked for, with defaults filled (the envelope).
  • Since 0.16.0 each row says if it financed a purchase: purpose, with the deed and loan_to_price on a PURCHASE row. deal names the investor deal the loan is tied to. It says if the loan is the deal’s purchase loan and what the deeds show occurred. outcome says what became of the loan. The row also says who borrowed, as keys and investor ids. See What the deeds say about the loan.
  • Since 0.19.0 each row also says if a take-back deed followed. foreclosed carries the instrument, the deed date, and if the grantee was this lender. The instrument is a trustee’s deed, a sheriff’s deed or a deed in lieu. On a loan tied to a deal, outcome reads FORECLOSED (Foreclosed).
  • borrowers[] lists the borrowers of a RECORDED row as the recorded history names them, and an OPEN row names none. These are the same names the parcel’s Financing object carries on mortgage_history[].borrowers[]. The field is a contact field, and this host does not serve it: the row carries no such key, as the parcel products do.
  • sort=amount_desc orders the lender’s whole book in memory and is slower on the largest lenders. The two date sorts walk an index.

CSV

Accept: text/csv streams the whole filtered set as lender-<id>-loans.csv in the requested sort. The API ignores limit and cursor on a CSV request. The export is available from the Growth plan (Plans and limits). Below Growth, the API answers 403 plan_limit and names the plans that export. Send recorded_from on every CSV request, because the busiest lenders hold hundreds of thousands of rows. Without the window, the API answers 400 validation_error naming recorded_from, code window_required. recorded_to stays optional. The API counts the set before the first row streams. The cap is 50,000 rows. Above the cap, the API answers 422 csv_cap_exceeded with the cap in the body and in the X-Row-Cap header. When you get that answer, narrow the window. The export costs 0 credits. It counts against the CSV budget of 12 a minute and one in flight, per developer (Rate limits). The columns are the row’s fields in the order of the CSV representation. The Borrowers column is a contact column and is absent on this host. The export needs the platform release that passes Accept: text/csv through to this route. Until that release is live, the route answers the JSON page whatever Accept says. The changelog announces the release.

Gotchas

  • The busiest lenders have hundreds of thousands of rows. Page with cursor, or cut a window with recorded_from and recorded_to. The CSV takes the whole window at once, up to the cap (Give me a spreadsheet).
  • Send market= when the lender is in more than one loaded market. Without it, the API answers 400 market_required. If the lender has no profile in the market= you give, the API answers 404.
  • Lender names (lender_name_as_recorded, assigned_lender_name) are business records of the loan. The API serves them in full, whatever the lender_class. The borrowers are the one contact field of the row, and this host leaves the key out. The borrower keys and the investor ids of 0.16.0 are hashes and ids, not names. The API serves them.
  • purpose, outcome, deal_kind and investor_id read the deed link. On a registry built before the deed link, they answer 422 lenders_unavailable, and every such field on the row is null. foreclosed, cell and a geometry read the place rankings. On a registry built before the place rankings, they answer the same, and foreclosed on the row is null.
  • The CSV gained three cells in 0.19.0: Foreclosed on, Foreclosed instrument, Foreclosed by lender. The three cells come before As of. A file taken before that release has three fewer columns.
  • Every row is dated (meta.dated[]). With require_current=true, the API answers 422 dated_refused.
  • The API answers 400 invalid_id for an id without the len_ prefix, and 404 for an unknown id. It answers 422 lenders_unavailable in a market with no published lender registry. It answers 400 invalid_cursor for a cursor from another query or an older dataset.
  • The API follows old ids as on the profile route (since 0.17.0). A merged id answers 200 with meta.resolved_from and the current lender’s rows. A retired id answers 410 gone. An id the registry never issued answers 404 (Retired ids).
Who is this lender?.

Authorizations

Authorization
string
header
required

API key from the developer console (starts with zpka_). Create one at https://developers.investorlift.com/get-a-key.

Path Parameters

id
string
required

Lender id, len_ followed by 12 hex characters, for example len_d2028f0766fc. Take it from a search hit, a ranking row's lender.id or a parcel's financing block. The id is the same in every market and stable across data refreshes. The API follows an id from an earlier registry run to the current lender, and meta.resolved_from lists it. For a retired id with no successor, the API answers 410 gone.

Query Parameters

market
string

Market code, for example phx. The loaded markets are in meta.coverage[]. Send it only when the id exists in more than one loaded market. 400 market_required says so, and a lender has the same id in every market it lent in. Otherwise the API uses the id's own market.

Required string length: 1 - 16
source
enum<string>
default:both

Which rows to list. With open, the API lists open lien positions only. With recorded, it lists recorded history slots only, with duplicates as the history holds them. With both, the default, it lists one row per instrument: the open row where the instrument has one, else its recorded row.

Available options:
open,
recorded,
both
recorded_from
string

Keep loans recorded on or after this date, YYYY-MM-DD. With Accept: text/csv on api.investorlift.com you must send it (400 without it). So an export is a window of the book, never the whole of it.

recorded_to
string

Keep loans recorded on or before this date, YYYY-MM-DD. With recorded_from, one year is recorded_from=2025-01-01&recorded_to=2025-12-31.

product
enum<string>[]

Keep only loans of these products (comma list or repeated key): CONSTRUCTION, HELOC, OTHER.

Minimum array length: 1

What the file says the loan is, read from its flags and loan type and never from the label. CONSTRUCTION: the construction flag or a "Building or Construction Loan" type. HELOC: the credit-line flag or a "Credit Line (Revolving)" type. OTHER: everything else, that is a purchase-money or refinance mortgage of any kind.

Available options:
CONSTRUCTION,
HELOC,
OTHER
term_band
enum<string>[]

Keep only loans in these term bands (comma list or repeated key): LE_24M, 25_TO_120M, 121_TO_359M, GE_360M, UNKNOWN.

Minimum array length: 1

The loan term in months, from the file's term where it carries one, else from the maturity date less the recording date. LE_24M: up to 24 months, the bridge and fix-and-flip range. 25_TO_120M: 25 to 120 months. 121_TO_359M: 121 to 359 months. GE_360M: 30 years and longer. UNKNOWN: neither a term nor a maturity on file, which is most hard-money rows.

Available options:
LE_24M,
25_TO_120M,
121_TO_359M,
GE_360M,
UNKNOWN
loan_type
string[]

Keep only loans whose loan_type is one of these, as the file writes it (comma list or repeated key), for example "New Conventional" or "FHA".

Minimum array length: 1
Required string length: 1 - 80
property_type
string[]

Keep only loans on parcels whose property_type_category is one of these, as the assessor feed writes it (comma list or repeated key), for example "Residential".

Minimum array length: 1
Required string length: 1 - 80
amount_min
integer

Keep only loans with loan_amount at or above this, in whole dollars. The filter drops unpriced loans.

Required range: 0 <= x <= 9007199254740991
amount_max
integer

Keep only loans with loan_amount at or below this, in whole dollars. The filter drops unpriced loans.

Required range: 0 <= x <= 9007199254740991
zip
string

Keep only loans on parcels in this 5-digit ZIP.

Pattern: ^\d{5}$
city
string

Keep only loans on parcels in this city, as the parcel table writes it (case does not matter).

Required string length: 1 - 100
purpose
enum<string>[]

Keep only loans of these purposes by the deed link (comma list or repeated key): PURCHASE, NOT_PURCHASE, UNKNOWN. While the market's registry predates the deed link, the API answers 422 lenders_unavailable.

Minimum array length: 1

The loan's purpose, that is if it financed a purchase, read from the recorded deeds and never from the file's label. PURCHASE: a priced deed on the parcel, $10,000 or more, is dated in the 45 days up to and including the recording date. A deed after the loan is a later sale, never this loan's purchase. NOT_PURCHASE: the deed registry covers those 45 days, the parcel has priced deeds, and none falls in them. Such a loan is a refinance, a second, a HELOC or a construction draw. UNKNOWN: the deed registry does not cover the window: its deeds or the parcel's deeds start after the loan, or the market has none.

Available options:
PURCHASE,
NOT_PURCHASE,
UNKNOWN
outcome
enum<string>[]

Keep only loans tied to a deal with these outcomes (comma list or repeated key): RESOLVED_BY_RESALE, REFINANCED, OPEN, FORECLOSED, UNKNOWN. A loan tied to no deal has no outcome, and the filter drops it. While the registry predates the deal link, the API answers 422 lenders_unavailable.

Minimum array length: 1

What became of a loan tied to a deal: a performance proxy read from the deed chain, never from a delinquency record or payment history. RESOLVED_BY_RESALE is a priced deed on the parcel after the loan, and REFINANCED is a later mortgage on it in either table before any resale. OPEN is an open lien position at the slice date and nothing later, and UNKNOWN is none of these because the chain runs out. FORECLOSED: a take-back deed on the parcel more than 90 days after the loan's recording, before any priced resale and any later mortgage. A take-back deed is a trustee's deed, a sheriff's deed or a deed in lieu, and the foreclosed block on the loan row carries it. A shorter gap is the auction buyer's own deed, not a foreclosure of this loan.

Available options:
RESOLVED_BY_RESALE,
REFINANCED,
OPEN,
FORECLOSED,
UNKNOWN
deal_kind
enum<string>[]

Keep only loans tied to a deal of these kinds (comma list or repeated key): flip, wholesale, hold, long_hold, other, build. While the registry predates the deal link, the API answers 422 lenders_unavailable.

Minimum array length: 1

What occurred on the deal. flip: bought, fixed and resold within about a year at a profit-shaped margin; wholesale: bought and resold in under 30 days, or a chain resale or round trip within 90 (a double close); hold: bought and still owned at data_end, a confirmed holding or an un-resold purchase; long_hold: held over a year, then sold (a landlord exit); other: an investor resale that is not a clean flip. Reasons: a loss, a thin margin, a builder's new home resold, an iBuyer resale, or a chain resale of 3 to 12 months; build: a registered investor bought a lot or teardown, built a house on it during the hold, then sold. A builder's finished home bought and resold is other. On data built after 2026-09-17 the kind keeps only a single-family parcel held over 90 days, its house complete by the sale year. A market built on or before 2026-09-17 (meta.coverage[].loaded_at) counts every lot-to-build resale by a registered investor as a build until its next build.

Available options:
flip,
wholesale,
hold,
long_hold,
other,
build
investor_id
string

Keep only loans whose main borrower resolves to this registered investor: the investor's loans from this lender. The id is inv_ followed by 12 hex characters, the loan row's investor_id. While the registry predates the borrower match, the API answers 422 lenders_unavailable.

Pattern: ^inv_[0-9a-f]{12}$
foreclosed
enum<string>

true keeps only loans followed by a take-back deed on the parcel (foreclosed set on the row). false keeps the rest. Default: every loan. A take-back deed is a trustee's deed, a sheriff's deed or a deed in lieu after the recording. While the registry predates the take-back join, the API answers 422 lenders_unavailable.

Available options:
true,
false
cell
string

Keep only loans on parcels in this H3 cell. Send the index as a hex string at res 7 or 8, for example 8848eba59dfffff, as GET /v1/lenders/{id}/cells and /v1/deals/cells serve them. The API reads the resolution off the index (400 validation_error, code invalid_cell, otherwise). Do not send it with zip, city or a geometry (400 geography_conflict). While the registry predates the place rankings, the API answers 422 lenders_unavailable.

Pattern: ^[0-9a-f]{15}$
lat
number

Point latitude (with lng). With radius_miles it is the geometry. The API resolves the circle to the H3 res-8 cells whose centre lies inside it, so its edge is a hex boundary. Do not send it with zip, city or county (400 geography_conflict). On a registry built before the place rankings, the API answers 422 lenders_unavailable.

Required range: -90 <= x <= 90
lng
number

Point longitude (with lat).

Required range: -180 <= x <= 180
radius_miles
number

Search radius in miles around the point or around the centre of the property_id parcel, 0.25 to 20 (default 2). Not allowed with bbox.

Required range: 0.25 <= x <= 20
bbox
string

Viewport as west,south,east,north (WGS84 degrees). West must be less than east, south less than north, and the diagonal at most 40 mi. It must intersect a loaded market's coverage bbox (422 outside_coverage otherwise). It can carry lat + lng (without radius_miles) as the reference point for distances and sort=distance.

property_id
string

Parcel geometry: search around the centre of that parcel, with radius_miles. Not allowed with lat, lng or bbox.

Pattern: ^prop_[0-9a-f]{32}$
sort
enum<string>
default:recorded_desc

Row order of a lender's loans: recorded_desc, the default, puts the newest recording first and undated rows last. With recorded_asc, the oldest recording comes first. With amount_desc, the largest loan amount comes first and unpriced rows last. This sort is slower on the largest lenders, which have no index in that order.

Available options:
recorded_desc,
recorded_asc,
amount_desc
limit
integer
default:100

Page size, 1-500 (default 100). Ignored by CSV.

Required range: 1 <= x <= 500
cursor
string

Opaque cursor from page.next_cursor of the previous page. A change of query, sort, weights or data version invalidates it (400 invalid_cursor). Then restart from page 1.

Required string length: 1 - 4096
require_current
enum<string>
default:false

true refuses the request with 422 dated_refused while the registry's source, the financing slice, is a dated snapshot. The default false serves it, and meta.dated[] carries the lenders and financing blocks.

Available options:
true,
false

Response

The lender's loans in one market, one page in the requested sort. With Accept: text/csv every filtered row as a CSV file. On api.investorlift.com the CSV needs a recorded_from window.

The lender's loans in one market, one page in the requested sort.

data
object[]
required

The rows of this page.

page
object
required

Pagination: the page size, the rows returned and the cursor for the next page. Paged lists carry no total. The summary block does.

meta
object
required

Response metadata: when the API produced it, which markets it covers, and how fresh they are.