Loans and portfolio
8 tools. Generated from the MCP server: names, inputs and prices match the code.
Delete Loan
Delete a loan by id, for good, with its events; a follow-up that pointed at it loses its previous_loan_id. Only for a loan that should never have existed (a duplicate, a wrong entry). A loan that was really paid off keeps its history: set end_date with loans_patch instead.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| id | integer | yes | loan_id from portfolio_loans_list, or id in loans on properties_get. |
RESTDELETE /api/v1/loans/{id}
Record Loan Event
Record a change on a loan from the month of date (YYYY-MM-DD, not before the loan starts). type decides value: interest_rate_change = the new rate as a fraction 0..0.2 (the real Anschlusszins after a Zinsbindung, replacing the follow-up-rate assumption); remaining_debt_override = the Restschuld the bank states on that date, EUR; special_repayment = a Sondertilgung in EUR (> 0); new_target_repayment_costs = a new flat monthly Tilgung in EUR on top of the interest, so the payment falls as the debt does, ignored for bullet_loan, repayment_substitute and free months; a new annuity is a follow-up loan with properties_loans_create and previous_loan_id.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| type | string | yes | What changes; it decides the unit of value.Values:special_repaymentremaining_debt_overridenew_target_repayment_costsinterest_rate_change |
| value | number | yes | Unit depends on type. interest_rate_change: the new rate as a fraction, 0 to 0.2 (0.04 = 4 %). remaining_debt_override: the balance the bank states, EUR, 0 or more. special_repayment: the Sondertilgung, EUR, more than 0. new_target_repayment_costs: the new monthly Tilgung, EUR, 0 or more: a flat amount on top of the interest, so the payment falls as the debt does. Wins over repayment_rate and fixed_repayment_rate; ignored for bullet_loan, repayment_substitute and free months. Never the full rate; a new annuity is a follow-up loan with previous_loan_id. |
| date | string | yes | First month the event applies, YYYY-MM-DD; not before the loan starts. |
| loan_id | integer | yes | loan_id from portfolio_loans_list, or id in loans on properties_get. |
RESTPOST /api/v1/loans/{id}/events
Delete Loan Event
Delete one event of a loan (event_id from the loan events on properties_get or loans_patch). The loan is projected as if it never happened.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| loan_id | integer | yes | loan_id from portfolio_loans_list, or id in loans on properties_get. |
| event_id | integer | yes | Event id from the loan's events. |
RESTDELETE /api/v1/loans/{id}/events/{eventId}
Update Loan
Update a loan by id (loan_id from portfolio_loans_list, or loans on properties_get); partial body. Confirm an estimated Zinsbindung end with interest_commitment_end_date (YYYY-MM-DD from the contract, after start_date; null reverts to start + loan_commitment_years), name the bank with lender, or correct label, amounts and dates. Returns projection, as properties_loans_create does. Rates are fractions. Do not overwrite interest_rate with the new rate after a Zinsbindung: that rewrites the past. Record it with loans_events_create (interest_rate_change) or as a follow-up loan with properties_loans_create.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| label | string | no | Name of the loan, 1 to 50 characters. |
| start_date | string | no | First month of the loan, YYYY-MM-DD. |
| loan_amount | number | no | Loan amount in EUR. |
| interest_rate | number | no | Nominal interest rate p.a. as a fraction, 0 to 0.2 (0.035 = 3.5 %). |
| repayment_rate | number | no | Initial Tilgung p.a. as a 0-1 fraction (0.02 = 2 %). When a contract names only the monthly rate in EUR: that rate * 12 / loan_amount - interest_rate. |
| lender | string | null | no | Bank, at most 100 characters. |
| loan_commitment_years | integer | no | Zinsbindung in years; the end month is start + years unless interest_commitment_end_date is set. |
| interest_commitment_end_date | string | null | no | Zinsbindung end as written in the loan contract, after start_date; wins over start + years. |
| repayment_type | string | no | How the loan is repaid. On create, annuity_loan when omitted.Values:annuity_loanbullet_loaninitial_repayment_freerepayment_substitute |
| repayment_free_months | integer | null | no | Months with interest-only payments at the start (initial_repayment_free). |
| repayment_substitute_monthly | number | null | no | Monthly savings into the Tilgungsträger (repayment_substitute), EUR, more than 0. |
| repayment_substitute_expected_return | number | null | no | Expected annual return on the Tilgungsträger as a 0-1 fraction (0.04 = 4 %). |
| fixed_repayment_rate | number | null | no | Fixed monthly Tilgung in EUR, more than 0, on top of the interest (annuity_loan, and initial_repayment_free after its free months; ignored otherwise). An amount, not a rate. Wins over repayment_rate. Never the full monthly rate from a contract: for an annuity send repayment_rate with this field null. |
| end_date | string | null | no | Planned payoff date: the loan is repaid in full then, not refinanced. |
| previous_loan_id | integer | null | no | The loan this one refinances (Anschlussdarlehen); a loan of the same property. |
| processing_fee | number | no | One-time fee as a 0-1 fraction of the loan amount (0.01 = 1 %); 0 on create when omitted. Fix & flip only. |
| loan_duration_months | integer | no | Months the loan runs in a fix & flip calculation; 6 on create when omitted. |
| id | integer | yes | loan_id from portfolio_loans_list, or id in loans on properties_get. |
RESTPATCH /api/v1/loans/{id}
Export Portfolio PDF
Export the portfolio overview (Vermögensübersicht) of purchased properties as a PDF. Returns an embedded application/pdf resource (base64). Costs 2 API credits.
Inputs
No inputs.
RESTPOST /api/v1/portfolio/export
Get Portfolio
Portfolio-wide metrics for the authenticated user. Financial totals cover only owned (purchased) properties; counts for other lifecycles (new, in_progress, canceled) are reported separately under property_inventory. financing summarises the running loans: remaining_debt, monthly_debt_service (interest + Tilgung), weighted_interest_rate, loan_to_value, debt_service_coverage (Nettokaltmiete / Kapitaldienst, buy-and-hold), next_commitment_end (loan_id, property_id, property_name, lender, month, date YYYY-MM-DD, months_until, commitment_end_confirmed, is_repaid_at_end, has_follow_up, remaining_debt_at_commitment_end), loans_needing_attention and the Restschuld falling due per year (expiries_by_year). Loans past their Zinsbindung without a recorded follow-up are projected at financing.follow_up_interest_rate (account setting, default 0.0375); name that assumption when quoting a Restschuld. Rates are fractions, months YYYY-MM. external_assets lists what the user holds at connected providers such as Parqet (net_value in EUR, allocation by asset type, valuation_at); total_wealth adds those to the real-estate equity and is null when nothing is connected. Hosts with MCP Apps render a Portfolio card; the JSON is always returned as text too.
Inputs
No inputs.
RESTGET /api/v1/portfolio
List Portfolio Loans
List the loans running today on purchased, held properties (the Finanzierungen table), soonest Zinsbindung end first. Each item: loan_id, property_id, property_name, lender, repayment_type, remaining_debt_today, interest_rate and repayment_rate (fractions), monthly_payment (EUR), commitment_end_month (YYYY-MM), commitment_end_date (YYYY-MM-DD), remaining_debt_at_commitment_end, has_follow_up, issues. For a reminder or calendar entry use commitment_end_date as an all-day date: it is the contract date when commitment_end_confirmed is true, otherwise the last day of the estimated month, so say that it is an estimate. Skip loans with is_repaid_at_end or has_follow_up: nothing needs refinancing there. commitment_end_confirmed false means the end is estimated as start + loan_commitment_years, not taken from the contract: ask the user for the date and confirm it with loans_patch (interest_commitment_end_date). is_repaid_at_end true (bullet, repayment substitute, planned end) means the loan is paid off then, not refinanced. filter: all (default), ending_soon (Zinsbindung or planned payoff ends within 24 months), needs_attention (unconfirmed or passed Zinsbindung end). Paginated with limit/offset.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| filter | string | no | all (default). ending_soon: Zinsbindung or planned payoff ends within the next 24 months. needs_attention: an unconfirmed or already passed Zinsbindung end.Values:allending_soonneeds_attention |
| limit | integer | no | |
| offset | integer | no |
RESTGET /api/v1/portfolio/loans
Run Refinancing Scenario
Run a refinancing scenario. Computes only, writes nothing. mode "loan" (default) prices an Anschlussfinanzierung for one running loan (loan_id from portfolio_loans_list): an annuity on the Restschuld due at the end of its Zinsbindung, starting the month after. interest_rate and repayment_rate are fractions (0.0375 = 3.75 %, 0.02 = 2 % Tilgung), commitment_years the new Zinsbindung; all four are required. Returns scenario.monthly_payment, delta_per_month against today (positive = more per month), remaining_debt_after_commitment, interest_during_commitment, debt_free_month, and the property cashflow per month before and after. To plan it for real use properties_loans_create with previous_loan_id. Refused for a loan repaid at its end and for one without a Zinsbindung end. mode "stress_test" stress-tests the whole portfolio: does the rent still carry the loans once they have rolled over at a higher rate, and when part of the rent does not arrive? Every buy-and-hold loan is refinanced at the end of its own Zinsbindung at each stress rate plus stress_repayment_rate Tilgung (default 0.02); horizon_years limits that to Zinsbindungen ending within so many years. One row per rate, one cell per rent loss (rent_cut: vacancy and unpaid rent, not a lower rent): coverage = Nettokaltmiete x (1 - loss) / Kapitaldienst; rows come back in ascending order of rate and cells of loss, so each is worse than the one before; tone comfortable (>= comfort_threshold, default 1.2), tight (>= 1.0) or shortfall (the owner pays in). Its arguments are all optional: interest_rates (default 0.04, 0.06, 0.08), rent_cuts (default 0 to 0.25) and stress_repayment_rate are fractions. In each row, last_carried_rent_cut is the largest rent loss the loans still carry at that rate, the figure to report first. Each mode refuses the other mode's arguments. Pro plan or higher.
Needs the plan feature refinancing_planner.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| mode | string | no | loan: one follow-up loan (default). stress_test: the whole portfolio.Values:loanstress_test |
| loan_id | integer | no | A running loan of the portfolio. |
| interest_rate | number | no | Anschlusszins p.a. as a fraction, 0 to 0.2 (0.0375 = 3.75 %). |
| repayment_rate | number | no | Initial Tilgung of the follow-up loan p.a. as a fraction, 0 to 0.1 (0.02 = 2 %). |
| commitment_years | integer | no | New Zinsbindung in years. |
| interest_rates | array<number> | no | Rates the loans are refinanced at after their Zinsbindung, as fractions (0.04 = 4 %). Default 0.04, 0.06, 0.08. |
| rent_cuts | array<number> | no | Rent loss (vacancy, unpaid rent) as fractions (0.1 = 10 % of the rent does not arrive). Default 0, 0.05, 0.1, 0.15, 0.2, 0.25. |
| horizon_years | integer | no | Reprice only Zinsbindungen ending within this many years. Omit (default) to reprice every loan at its own end. |
| stress_repayment_rate | number | no | Tilgung p.a. assumed for the repriced loans, as a fraction (0.02 = 2 %). Default 0.02. |
| comfort_threshold | number | no | Coverage ratio (not a fraction of 1) at or above which a cell is comfortable. Default 1.2. |
RESTPOST /api/v1/portfolio/refinancing-scenario