Skip to main content
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.
One row of GET /v1/lenders/{id}/loans: a recorded instrument with the parcel it sits on. property_id is the key to the parcel’s financing block.

Two tables, one instrument

source says where the row comes from. OPEN is an open lien position at the slice date, 1 to 4 per parcel. An open row carries the estimated balance, rate, term and maturity from the open-lien table. RECORDED is a slot of the recorded mortgage history, the 5 most recent per parcel. The same instrument is in both tables when the parcel, the recording date and the amount match. Then in_both is true, loan_key is the same on both rows, and the default source=both serves the open row alone.
  • position is the row’s slot in its own table. On an open row it is the lien position, where 1 is senior. On a recorded row it is the history slot, where 1 is the oldest kept slot and the highest filled slot is the newest. open_position is the lien position of the instrument on either row. It is null when a recorded row has no open twin.
  • lender_id is the lender of record. When the instrument is in both tables, it is the recorded history’s lender. It equals the path id on this route. lender_id_open is the lender the open table names. lender_disagrees is true when the two differ: the insurer (HUD, the VA) against the servicer, or a spelling the dictionary does not join yet.
  • lender_name_as_recorded is the spelling on this row as the file writes it. It is the spelling the parcel’s financing block serves. lender_class and identity_basis describe that spelling.

What the file states and what is read from it

loan_amount, recording_date, due_date, term_months, interest_rate and loan_type come from the file. current_balance, and the rate on an open row, are the file’s estimates at the slice date. These fields come from them:

What the deeds say about the loan

Since 0.16.0 every row carries a join to the recorded deeds, and four fields read the join. Each is null on a registry built before the deed link, where purchase_measured is false on the lender’s profile. That null means not measured. Every row is dated. as_of is the slice date, and meta.dated[] on the response names the lenders and financing blocks.

Foreclosed

foreclosed (since 0.19.0) is on every dated row, tied to a deal or not. It is the earliest take-back deed on the parcel more than 90 days after the recording. The deed must come before any priced resale and before any later mortgage from another lender. A trustee’s deed recorded within 90 days of a loan is the buyer’s own auction purchase, not a foreclosure of it. The block is null when no such deed followed, and null on every row of a registry built before the take-back join. On a loan tied to a deal, the same deed makes outcome read FORECLOSED. The block carries the instrument, the deed_date and buyer_is_lender. The instrument is TRUSTEES_DEED, SHERIFFS_DEED or DEED_IN_LIEU. The flag is true when the grantee is this lender under any of its spellings. It is false when the grantee is the trustee, the servicer or another lender. A take-back deed is a deed, read from the county’s records. It says the loan ended at foreclosure, never when the borrower missed payments. foreclosed=true on the route keeps these rows. The lender’s takebacks block is the same deeds counted from the grantee’s side.

Contact data

borrowers[] is the borrowers of a RECORDED row as the recorded history names them. They are the same names the parcel’s Financing object carries on mortgage_history[].borrowers[] for that slot. An OPEN row names none, because the open-lien table carries no borrower. The field is a contact field, and this host does not serve it. The row carries no borrowers key and no contact_redacted flag, as the parcel products do. Lender names (lender_name_as_recorded, assigned_lender_name) are business records of the loan. The API serves them in full on every key, whatever the lender_class.

The CSV representation

With Accept: text/csv on GET /v1/lenders/{id}/loans, each row is one line of lender-<id>-loans.csv. The file has one column per field above, in the same order, under a header row. The header row names these columns, in this order:
  • Market, Property id, Address, City, ZIP, Source, Position, Loan key, In both
  • Lender id, Lender id (open), Lender disagrees, Lender as recorded, Lender class, Identity basis
  • Recording date, Due date, Loan amount, Amount outlier, Current balance, Balance outlier, On resold parcel
  • Interest rate, Term months, Term band, Loan type, Label, Label as recorded
  • Product, Product proxy, Product basis, Open position, Assigned lender, Blanket group id, Blanket parcels, County FIPS, Property type
  • Since 0.16.0: Purpose, Deed date, Deed price, Loan to price, Deal id, Deal kind, Purchase loan, Outcome, Investor id, Borrower keys, Borrower match
  • Since 0.19.0: Foreclosed on, Foreclosed instrument, Foreclosed by lender
  • As of, Dated
  • Borrowers, the last column
Borrower keys joins the keys with ;. Dates are YYYY-MM-DD, money is whole dollars, booleans are true / false and a null is an empty cell. Borrowers joins the names with ; . It is a contact column, absent on this host like the borrowers key of the JSON row. The file is the whole filtered window in the requested sort, at most 50,000 rows. See the CSV section of the route.

One loan of the lender. The row carries the parcel, which table the row comes from and if the other table has it too, and the lender as recorded. It carries the amount, balance, rate, term and maturity as the file carries them, and the product, term band and label read from them. It says if the loan financed a purchase and which deed, and names the investor deal linked to it and what became of it. It also carries the borrowers as keys and the investor they resolve to.

market
string
required

Market code, for example phx.

property_id
string
required

The parcel: the key to GET /v1/properties/{property_id} and its financing block.

Pattern: ^prop_[0-9a-f]{32}$
address_short
string | null
required

Street address without city, for example "7522 E Cholla St". Null when the parcel is not in the parcel table.

city
string | null
required

City, upper case. Null when the parcel is not in the parcel table.

zip
string | null
required

5-digit ZIP. Null when the parcel is not in the parcel table.

source
enum<string>
required

Which table the row comes from. OPEN: an open lien position at the slice date, 1 to 4 per parcel, with the balance, rate, term and maturity the open-lien table carries. RECORDED: a slot of the recorded mortgage history, the 5 newest per parcel, with older ones lost. The same instrument is in both tables when the dates and amounts match, and in_both says so.

Available options:
OPEN,
RECORDED
position
integer
required

The row's slot in its source table. For OPEN it is the lien position (1 is senior). For RECORDED it is the history slot: 1 is the oldest kept, the highest filled slot is the newest.

Required range: -9007199254740991 <= x <= 9007199254740991
loan_key
string
required

The instrument's key, 32 hex characters, from the parcel, the recording date and the amount. It is the same on an open row and its recorded twin, so you can join rows across source. Not an id to store across refreshes.

in_both
boolean
required

True when the instrument is in both tables. That is an open row and a recorded slot on the same parcel with the same recording date and amount.

lender_id
string
required

The lender of record: the recorded history's lender on an instrument in both tables, the row's own otherwise. Equals the path id on this route.

Pattern: ^len_[0-9a-f]{12}$
lender_id_open
string | null
required

The lender the open-lien table names for this instrument. It equals lender_id unless the two tables disagree (lender_disagrees). Null on a recorded row with no open twin, and when that lender is below the person gate.

Pattern: ^len_[0-9a-f]{12}$
lender_disagrees
boolean
required

True when the recorded history and the open table name different lenders for this instrument. That is the insurer (HUD, the VA) against the servicer, or a spelling the registry at as_of does not yet join. False when the instrument is in one table only.

lender_name_as_recorded
string | null
required

The lender name on this row as the file writes it, for example LENDINGHOME FUNDING CORP under Kiavi's id. This is the spelling the parcel's financing block serves. Null when the file left it blank.

lender_class
enum<string> | null
required

How that spelling reads. Null when the name is blank. How the lender name reads. BANK: a bank, credit union or thrift. NONBANK: a mortgage company or other lending business. PRIVATE: a trust, a seller carry-back or another private party, not the hard-money sense of private lender, which the Lender object carries as is_hard_money. INDIVIDUAL: a person's name. GOVERNMENT: an agency or a public body.

Available options:
BANK,
NONBANK,
PRIVATE,
INDIVIDUAL,
GOVERNMENT
identity_basis
enum<string> | null
required

How the registry tied that spelling to the lender. Null when the name is blank. How the registry ties the spelling to its lender: NAME_FOLD means the folded name alone joins them. The fold uses upper case, drops punctuation and entity suffixes and spells out abbreviations: WELLS FARGO BANK NA and WELLS FARGO BANK N.A. are one. TRUNCATED_PREFIX: the file cut the name at 30 or 40 characters, and the registry joined it to the one longer name that starts with it. ALIAS_DICTIONARY: a hand-kept row joined it, for a rename such as QUICKEN LOANS to ROCKET MORTGAGE, a trade name or a charter form. A row also covers a spelling the same instrument carries both ways. The registry never merges acquisitions.

Available options:
NAME_FOLD,
TRUNCATED_PREFIX,
ALIAS_DICTIONARY
recording_date
string | null
required

The recording date, YYYY-MM-DD. Null when the file carries none.

due_date
string | null
required

The maturity date, YYYY-MM-DD. Null when the file carries none, as on most hard-money rows.

loan_amount
integer | null
required

The original loan amount, whole dollars. Null when the file carries none.

Required range: -9007199254740991 <= x <= 9007199254740991
amount_outlier
boolean | null
required

True when loan_amount exceeds $5,000,000. Such an amount is a facility amount the file records on every parcel a commercial facility covers. The row keeps it, but the lender's volumes and amount quartiles leave it out, and n_amount_excluded_24m counts the excluded instruments. Null where loan_amount is null.

current_balance
integer | null
required

The estimated current balance at as_of, whole dollars. Open rows only: null on recorded rows and where the file carries none.

Required range: -9007199254740991 <= x <= 9007199254740991
balance_outlier
boolean | null
required

True when current_balance exceeds $5,000,000. The lender's open_balance leaves such a balance out. Null where current_balance is null.

on_resold_parcel
boolean | null
required

True when the deeds show a sale of the parcel more than 30 days after this open row's recording. The loan is probably paid off, so open_balance leaves the row out. Null on recorded rows and where the market has no deed table.

interest_rate
number | null
required

The interest rate, percent as the file writes it. On open rows it is an estimate at as_of. On history rows it is the rate at recording. Null when not on file.

term_months
integer | null
required

The term in months as the file writes it. Null when not on file.

Required range: -9007199254740991 <= x <= 9007199254740991
term_band
enum<string>
required

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 | null
required

The loan type as the file writes it, for example "New Conventional", "FHA" or "Credit Line (Revolving)". Null when blank or "Unknown (DEFAULT)".

label
enum<string> | null
required

Null when the file's label is blank or unmapped, which it is on most open rows. The file's transaction label, mapped to a closed list. REFI_OR_SECOND: refinance loans and second trust deeds, purchase and non-purchase money lumped together. RESALE_PURCHASE_MONEY: a purchase-money loan on a resale. NEW_PURCHASE_MONEY: a purchase-money loan on a new home. HELOC, CONSTRUCTION and NON_RESIDENTIAL: the file's label of that name. The purchase labels stop in January 2022, and a label never decides if a loan financed a purchase.

Available options:
REFI_OR_SECOND,
HELOC,
RESALE_PURCHASE_MONEY,
NEW_PURCHASE_MONEY,
CONSTRUCTION,
NON_RESIDENTIAL
label_as_recorded
string | null
required

The file's transaction label as written, for example "Resale purchase money loans". Null when blank.

product
enum<string>
required

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
product_proxy
enum<string> | null
required

Null when term_band is UNKNOWN. An inference from the term, not a fact the file states. BRIDGE: an OTHER product with a term of 24 months or less, a bridge or fix-and-flip loan. RENTAL_TERM: a term of 30 years or more from a hard-money lender, a DSCR rental loan. RETAIL: any other known term. Null when the term band is UNKNOWN.

Available options:
BRIDGE,
RENTAL_TERM,
RETAIL
product_basis
enum<string> | null
required

Null when term_band is UNKNOWN. Where the term behind term_band and product_proxy comes from. FILE: the file's own term in months. TERM: the registry computed it from the maturity date less the recording date. Null when the term band is UNKNOWN.

Available options:
FILE,
TERM
open_position
integer | null
required

The open lien position of the instrument. On an open row it is the row's own. On a recorded row in both tables it is the open twin's. Null on a recorded row with no open twin.

Required range: -9007199254740991 <= x <= 9007199254740991
assigned_lender_name
string | null
required

The lender the loan went to by assignment, as the file writes it. Open rows only. Null when the file records none.

blanket_group_id
string | null
required

32 hex characters that the open rows of one blanket loan share. A blanket loan has the same lender, date and amount on 5 or more parcels. The grouping leaves out credit lines and banks. Null outside a group.

blanket_n_parcels
integer | null
required

How many parcels the blanket group spans. Null outside a group.

Required range: -9007199254740991 <= x <= 9007199254740991
county_fips
string | null
required

The parcel's 5-digit county FIPS, for example 04013. Null when the parcel table carries none.

property_type_category
string | null
required

The parcel's property type category as the assessor feed writes it, for example "Residential". Null when not on file.

purpose
enum<string> | null
required

Null on a registry built before the deed link. 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
deed
object | null
required

The purchase deed the loan financed, on a PURCHASE row. Null on every other row.

deal
object | null
required

The investor deal linked to the loan. The deal's purchase date is within 45 days before the recording, or under LOOSE from 15 days after to 90 days before. The loan is its purchase loan or a secondary. Null when the loan ties to no deal, and while the market has no deal link.

outcome
enum<string> | null
required

Null when deal is null. 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
months_to_resolution
number | null
required

Months from the recording date to the event that resolved the loan, 1 decimal. The event is the resale deed, the refinancing mortgage or the take-back deed. Null unless outcome is RESOLVED_BY_RESALE, REFINANCED or FORECLOSED.

foreclosed
object | null
required

The earliest take-back deed on the parcel more than 90 days after the recording that precedes any resale or later mortgage. A take-back deed is a trustee's deed, a sheriff's deed or a deed in lieu. A shorter gap is the auction buyer's own deed, not a foreclosure of this loan. The flag buyer_is_lender is true when the grantee is this lender under any of its spellings. On a loan tied to a deal it is the FORECLOSED outcome. Null when none, and on a registry built before the take-back join: takebacks_measured false, or a registry built before the place rankings.

investor_id
string | null
required

The registered investor the borrowers resolve to, the key to GET /v1/investors/{id}. When the borrowers resolve to several investors, the field carries the one with the most deals. Null when no borrower resolves to one, and while the market has no borrower match.

Pattern: ^inv_[0-9a-f]{12}$
co_borrower_investor_ids
string[] | null
required

The other registered investors the borrowers resolve to, most deals first. Empty when none. Null with borrower_keys.

Investor id: inv_ followed by 12 hex characters, for example inv_abaf618f44a3. The id is stable across data refreshes within a market. Store it as the investor's identity.

Pattern: ^inv_[0-9a-f]{12}$
borrower_keys
string[] | null
required

The borrowers' keys, one per name the recorded mortgage carries, in the file's order. On an open lien that names none, one key for the owner of record. These are the keys to GET /v1/lenders/{id}/borrowers. They are not names, and the API serves them to every key. Null when the row has no borrower source, that is an open lien naming none whose owner does not qualify. Null also on a registry built before the borrower match.

Borrower key: 12 hex characters hashed from the borrower's folded name with the dataset salt. The same key appears on every lender's rows and in every market. It is not a name and not reversible, and it is stable across data refreshes. Use the key to compare borrowers across lenders.

Pattern: ^[0-9a-f]{12}$
borrower_match
enum<string> | null
required

Null with borrower_keys. How the registry resolved the borrower, by the first rule that applied. DEAL: the loan has a deal whose investor has a member with the borrower's key, or the deal's investor when no key matched. ENTITY_NAME: the key is an entity member of exactly one investor, and PERSON_NAME means a person member of exactly one investor. PARTY: the key is on a recorded deed but belongs to no investor, while MORTGAGE_ONLY means the key is on no deed. OWNER_OF_RECORD: an open lien that names no borrower resolves to the parcel's owner of record. The registry takes the owner only when the owner held the parcel on the recording date and no sale followed.

Available options:
DEAL,
ENTITY_NAME,
PERSON_NAME,
PARTY,
MORTGAGE_ONLY,
OWNER_OF_RECORD
as_of
string
required

The slice date, YYYY-MM-DD. The API reads the row at it. Dated: see meta.dated[].

dated
boolean
required

True while the datasets are not in the current delivery, so the row is a snapshot at as_of.