Extracting Loan Terms From a Promissory Note
11 min read · updated August 11, 2026
A promissory note states a principal, a rate, a term and a payment. Those four numbers are over-determined: any three of them imply the fourth. That gives you something rare in document extraction — a way to test whether you read the page correctly using only the page.
The fields, and the ones that are conditional
The core set is short: principal amount, date of the note, maker (borrower) and payee (lender), interest rate, payment amount, payment frequency, first payment date, maturity date. Then a set of fields that exist only sometimes and change the meaning of the core ones.
- Rate type. Fixed, or variable as an index plus a margin (“Prime plus 2.00%”), with an adjustment frequency, a first adjustment date, and periodic and lifetime caps. A variable-rate note has no single
interest_rateand forcing one into the schema loses the index. - Default rate. A higher rate applying after default, distinct from the note rate. Extracting it into the same field is a material error.
- Late charge. Usually a percentage of the overdue payment after a grace period in days. Two numbers, not one.
- Prepayment. Permitted freely, permitted with a penalty, or locked out for a period. A note silent on prepayment is different from one prohibiting it, so use a nullable enum rather than a boolean.
- Security. Whether the note is secured, and by what. A secured note references a deed of trust or a security agreement by date, which is the join to the rest of the file.
- Balloon. A final payment materially larger than the others, often called out in a separate bolded paragraph because disclosure rules require it.
Note that this page is about parsing the document. Whether a given term is enforceable, or permitted where the note was made, is a legal question and not one an extraction pipeline should be answering.
The payment arithmetic
For a fully amortising loan with a fixed rate and level payments, the payment is:
PMT = PV * r / (1 - (1 + r)^-n) PV = principal r = periodic rate = annual rate / payments per year n = number of payments = years * payments per year
Work it against a note stating $250,000 principal, 6.50% per annum, monthly payments over 30 years. These three inputs are assumptions taken from the hypothetical note, not from any market data:
r = 0.065 / 12 = 0.00541666...
n = 30 * 12 = 360
(1 + r)^n = 6.99181...
PMT = 250000 * 0.00541667 / (1 - 1/6.99181)
= 1354.1667 / 0.856975
= 1580.17If the note says the monthly payment is $1,580.17, the four numbers agree and you have read all four correctly. Allow a tolerance of a dollar or two: lenders round to the cent in different directions and some compute from a rate carried to more decimal places than they print.
The interest-only case is simpler and worth testing first, because it is common on short-term and commercial notes:
interest-only payment = PV * r
= 250000 * 0.00541667
= 1354.17A stated payment matching that exactly, with the full principal due at maturity, tells you the note is interest-only regardless of whether the document uses the phrase.
When the payment does not match the term
Most of the time it will not match, and the reason is usually structural rather than an OCR error. Test the alternatives in order before you flag anything.
- Solve for n instead. Take the stated payment, principal and rate, and find the number of payments that amortises it. If that comes out at 360 while the note’s maturity is 60 months away, the note is a balloon: payments calculated on a thirty-year schedule, principal due in five years. That is the single most common explanation and the one an extractor most often mislabels as an error.
- Solve for r. If principal, payment and term agree at a rate close to but not equal to the stated one, you have probably misread a digit of the rate, or the note compounds on a basis you have not accounted for.
- Check whether the payment includes escrow. On a note used in a residential transaction the payment quoted elsewhere in the file may include taxes and insurance. The note itself normally states principal and interest only, but a summary sheet in the same PDF may not, and mixing them up produces a payment that is too high by a consistent margin.
- Check the frequency. Bi-weekly, semi-monthly and monthly are all in use, and semi-monthly (24 per year) and bi-weekly (26 per year) are not the same thing. Extract
payments_per_yearas an integer derived from an explicit enum, never from the word alone.
When you detect a balloon, derive its size and record it as a derived field labelled as derived. The remaining balance after k payments is:
Balance = PV*(1+r)^k - PMT*((1+r)^k - 1)/r with PV=250000, r=0.00541667, PMT=1580.17, k=60: (1+r)^60 = 1.38285 250000 * 1.38285 = 345,713 1580.17 * (0.38285/0.00541667) = 111,688 Balance ~ 234,026
So a five-year balloon on that note leaves roughly $234,000 due at maturity, from a $250,000 loan on which the borrower has paid nearly $95,000. That figure is derived from the assumed inputs above and from nothing else; it is arithmetic, not a market claim. Presenting it next to the extracted terms is often the most useful single output of the whole extraction, and it is available with no additional reading of the page.
Day counts and the rate that is not the rate
The arithmetic above assumes a periodic rate of annual divided by twelve. Notes say otherwise more often than you would expect, and the phrase that governs it is easy to skim past.
“Interest shall be computed on the basis of a 360-day year and the actual number of days elapsed” is the common commercial formulation, and it is not 30/360. Charging a daily rate of annual/360 across 365 actual days collects more than the nominal annual rate — about 1.4% more interest than a 365-day basis, since 365 divided by 360 is roughly 1.0139. That is a real difference and it is entirely contained in one sentence of boilerplate. Extract day_count_convention as an enum with values such as 30/360, actual/360, actual/365 and actual/actual, defaulting to null rather than to a guess.
Two related fields. Compounding frequency may differ from payment frequency, and where it does the effective rate differs from the nominal. And the note rate is not an APR: an APR incorporates certain costs of credit and is disclosed elsewhere, so a note rate and an APR in the same file legitimately differ and should never be reconciled to each other by a validator.
Where it breaks
The amounts are written twice. Notes state the principal in words and in figures — “Two Hundred Fifty Thousand and 00/100 Dollars ($250,000.00)”. Extract both and compare them. A words-versus-figures disagreement is a genuine document defect, not an extraction artefact, and it is one of the few places where a contradiction on the page is the finding.
Negative and parenthesised numbers. Financial documents in the same file will use parentheses for negatives, so (1,250.00) is minus one thousand two hundred and fifty. A parser that treats parentheses as decoration inverts the sign of every credit.
Amendments and allonges. A note modified after execution is amended by a separate instrument, and the operative terms are the original as modified. Extracting only the note gives you superseded terms, in the same way that extracting an original set of escrow instructions without its amendments gives you instructions nobody is following.
Blanks that were never filled. Notes are prepared from templates and go out with an unfilled first payment date or an empty late-charge percentage more often than anyone likes. A model asked for a date will frequently supply a plausible one derived from the note date. Ask explicitly for null on an unfilled blank, and check for it — this is the failure mode discussed in testing for unfilled placeholders, arriving from the document side rather than the prompt side.