Contents
View as Markdown

Properties

22 tools. Generated from the MCP server: names, inputs and prices match the code.

Check Property Completeness

Advisory data-room completeness for a property: which required/recommended documents are fulfilled, missing, outdated, or too few (status insufficient_count), plus a score and per-tenancy rental-contract checks. Each requirement carries the evidence for its status (matched_dates, newest_date, counted_in_window) and the top-level document_labels maps document ids to file names, so say why a row is not fulfilled. Advisory; never blocks.

Inputs

NameTypeRequiredDescription
property_idstringyes

RESTGET /api/v1/properties/{id}/completeness

Create Property

Create a property (calculation): a deal the user can evaluate. With deal_id alone it promotes that imported listing: calculation_strategy/property_type are derived when omitted, repeat calls safely reuse the existing property (reused=true) unless force_create_new is set, and allow_incomplete (+ placeholder_address) promotes deals still missing price, area, or address; gaps come back in fields_needing_review with screening_ready=false. Without deal_id, send calculation_strategy, property_type, address, purchase_price, living_area. Financing and assumptions come from search_profile_id when set (its overrides on the defaults), else from the calculation defaults of its strategy (calculation_defaults_get). interest_rate, repayment_rate and loan_amount_percentage are decimal fractions (0.04 = 4 % per year, 0.8 = 80 % of the purchase price), never percentage points. Costs 1 API credit when it creates a property, 0 when reused=true. The Free plan caps new properties per calendar month (403 calculation_limit_reached); a reused property never counts.

Price

  • 1 API creditwhen it creates a property
  • 0 API creditsreturns an existing property (reused: true)

Inputs

NameTypeRequiredDescription
deal_idstringno
calculation_strategystringnoValues:buy_and_holdfix_and_flipown_usespecial_rental
property_typestringnoValues:multi_family_househouseapartment
purchase_pricenumberno
living_areanumberno
addressobjectno
interest_ratenumberno
repayment_ratenumberno
loan_amount_percentagenumberno
search_profile_idintegernoOne of your search profiles: its calculation assumptions (else your calculation defaults) seed the numbers. Its strategy, when it has one, must match calculation_strategy.
force_create_newbooleanno
allow_incompletebooleanno
placeholder_addressbooleanno
created_viastringnoValues:humannora_agentroutineleverageddsales_push
external_refstring | nullno
unit_numberstring | nullno
floor_numberinteger | nullno
building_yearinteger | nullno
number_of_indoor_parking_spacesinteger | nullno
number_of_outdoor_parking_spacesinteger | nullno
number_of_roomsnumber | nullno
number_of_unitsinteger | nullno
number_of_bathroomsinteger | nullno
energy_labelstring | nullnoValues:a_plus_plus_plusa_plus_plusa_plusabcdefgh
is_leaseholdboolean | nullno
land_registry_courtstring | nullno
land_registry_districtstring | nullno
land_registry_sheetstring | nullno
cadastral_sectorstring | nullno
cadastral_parcelstring | nullno
co_ownership_sharenumber | nullno
co_ownership_share_totalnumber | nullno

RESTPOST /api/v1/properties

properties_delete

WriteDestructiveFree

Delete Property

Delete a property (calculation) by id.

Inputs

NameTypeRequiredDescription
idstringyes

RESTDELETE /api/v1/properties/{id}

Apply Document Matches

Adopt values a document asserts onto the property. Pass document_id plus the keys[] the user accepted (from properties_document_matches_get), and/or contact_keys[] from contact_suggestions to create the named Verwalter/Notar/Handwerker as a contact and link it to the property in that role, and/or create_tenancy to create the tenancy a rental contract describes, with a tenant contact for every tenant it names (a couple or a WG is one tenancy). Nothing is adopted automatically: show the user the value-vs-value rows and get their explicit confirmation before calling this. Safe to retry: keys already satisfied come back in unchanged_keys and tenancy creation is idempotent per tenant name. A key that is no longer offered (the document was re-extracted, or the property changed) is rejected rather than overwriting newer data. If properties_document_matches_get flagged the document with a unit_mismatch warning (a lease for another flat), nothing is written until you pass acknowledge_unit_mismatch: true, which you may only do after the user confirmed the document belongs to this property; usually the right fix is properties_documents_unlink.

Inputs

NameTypeRequiredDescription
property_idstringyes
document_idstringyes
keysarray<string>noValues:addresspurchase_priceliving_areabuilding_yearnumber_of_roomsnumber_of_unitsunit_numberenergy_classis_leaseholdco_ownership_shareco_ownership_share_totalland_registry_courtland_registry_districtland_registry_sheetcadastral_sectorcadastral_parcelrent_net
contact_keysarray<string>no
create_tenancybooleanno
unit_idstringno
acknowledge_unit_mismatchbooleanno

RESTPOST /api/v1/properties/{id}/document-matches/apply

Compare Documents with Property

Compare what a property’s documents assert against the property’s own fields; run it after properties_completeness_get. Returns per-document field matches (status match | mismatch | property_missing | document_missing, both values, and the value an adopt action would write) plus tenancy reconciliation for rent rolls and leases. Also returns contact_suggestions: the people and companies the documents name (the Verwalter from a Verwaltervertrag or ETV protocol, the notary from a purchase contract, the contractor from an invoice), each with the role it would hold and whether it is already on file or already linked. Advisory only; adopt accepted rows with properties_document_matches_apply.

Inputs

NameTypeRequiredDescription
property_idstringyes

RESTGET /api/v1/properties/{id}/document-matches

Link Documents to Property

Link existing document UUIDs to a property. Optional paths map document_id → data-room path (includes filename). Optional unit_ids says which units of this property the documents are about (a floor plan of WE 8 and WE 13).

Inputs

NameTypeRequiredDescription
property_idstringyes
document_idsarray<string>yes
is_pinnedbooleanno
pathsobjectno
unit_idsarray<string>noUnit ids of this property (properties_units_list). Replaces the unit set of every listed document; [] means the whole building; omitted leaves it as it is. A unit of another property fails the call with 404 before anything is written.

RESTPOST /api/v1/properties/{id}/documents

List Property Documents

List documents linked to a property. Each item carries unit_ids: the units of this property the document is about (from properties_units_list); empty means the whole building.

Inputs

NameTypeRequiredDescription
property_idstringyes
document_typestringnoOnly documents of this type, e.g. floor_plan.Values:tenant_operating_costs_statementexposeowners_association_meeting_minutesowners_association_operating_costs_statementcondominium_declarationenergy_certificateland_registerrental_contractpurchase_contracteconomic_planrent_rollbank_statementcadastral_mapfloor_planbuilding_permitloan_agreementinsurance_policyproperty_tax_noticeproperty_management_contractinspection_reportrenovation_invoicevaluation_reportliving_area_calculationother
limitintegerno
offsetintegerno

RESTGET /api/v1/properties/{id}/documents

Unlink Documents from Property

Remove the link between a property and documents (e.g. a Mietvertrag of another unit linked here by mistake). The documents stay, and so do their links to other properties: use this, never documents_delete, to fix a wrong link. Completeness and document matches stop counting them right away; values already adopted from them stay. Ids that were not linked come back in not_linked, so a retry is safe.

Inputs

NameTypeRequiredDescription
property_idstringyes
document_idsarray<string>yes

RESTDELETE /api/v1/properties/{id}/documents/{documentId}REST unlinks one document per call; the tool takes a list.

Get Property

Get one property by UUID. The id is the calculation id in the app. Address fields are flat (no nested address object); rates are decimal fractions. Each tenancy lists its tenants in contacts (lease order) and contact_ids. Hosts with MCP Apps render a Property card; the JSON is always returned as text too.

Inputs

NameTypeRequiredDescription
idstringyes

RESTGET /api/v1/properties/{id}

Upload Property Image

Upload a property image from base64 content and append it to the property’s images. JPEG, PNG or WebP, at most 10 MB decoded; the type is read from the bytes. Returns the stored reference (blob_path) and the updated images list.

Inputs

NameTypeRequiredDescription
property_idstringyes
content_base64stringyes

RESTPOST /api/v1/properties/{id}/imagesREST takes the image as multipart/form-data, not content_base64.

Get Property Key Figures

Key figures for a property. range: full | year1 | year10 (required). date_unit: month | year (default year). Buy-and-hold vs fix-and-flip shapes differ; property must have an address. When present, deal_score holds the 0-100 score, its factors, caps and open items: explain a score from these, never from memory.

Inputs

NameTypeRequiredDescription
idstringyes
rangestringyesValues:fullyear1year10
date_unitstringnoValues:monthyear

RESTGET /api/v1/properties/{id}/keyfigures

List Properties

List the user’s properties (paginated: limit 1–200 default 50, offset). Optional filters, each accepting comma-separated values: property_lifecycle (new,in_progress,purchased,canceled), property_stage_id (UUIDs), created_via (human,nora_agent,routine), external_ref (exact match). Items carry flattened address fields and key metrics.

Inputs

NameTypeRequiredDescription
property_lifecyclestringno
property_stage_idstringno
created_viastringno
external_refstringno
limitintegerno
offsetintegerno

RESTGET /api/v1/properties

Add Loan to Property

Add a loan (Darlehen) to a property. Required: property_id, label, start_date (YYYY-MM-DD), loan_amount (EUR), interest_rate and repayment_rate as fractions (0.035 = 3.5 %, 0.02 = 2 % Tilgung). A contract that names only the monthly rate in EUR (Annuität): repayment_rate = that rate * 12 / loan_amount - interest_rate. fixed_repayment_rate is a fixed Tilgung on top of the interest, never that rate; it wins over repayment_rate, so null it when correcting a loan. The Zinsbindung ends after loan_commitment_years (default 10) unless interest_commitment_end_date, the date in the contract, is set: send it when the user knows it, the end then counts as confirmed instead of estimated. An Anschlussdarlehen is a new loan with previous_loan_id = the loan it refinances (same property), start_date the month after the old Zinsbindung ends and loan_amount the Restschuld then (remaining_debt_at_commitment_end in portfolio_loans_list). end_date is a planned payoff, not a Zinsbindung end. Confirm the figures with the user before writing. Returns projection, to check against the contract: monthly_rate is the rate a contract names (interest + Tilgung after any free months, without savings into a Tilgungsträger). remaining_debt_at_commitment_end is the Restschuld at the Zinsbindung end, unless end_date is set: then both end fields describe the planned payoff, so do not compare them with the contract. On a real mismatch fix the loan with loans_patch.

Inputs

NameTypeRequiredDescription
labelstringyesName of the loan, 1 to 50 characters.
start_datestringyesFirst month of the loan, YYYY-MM-DD.
loan_amountnumberyesLoan amount in EUR.
interest_ratenumberyesNominal interest rate p.a. as a fraction, 0 to 0.2 (0.035 = 3.5 %).
repayment_ratenumberyesInitial 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.
lenderstring | nullnoBank, at most 100 characters.
loan_commitment_yearsintegernoZinsbindung in years; the end month is start + years unless interest_commitment_end_date is set.
interest_commitment_end_datestring | nullnoZinsbindung end as written in the loan contract, after start_date; wins over start + years.
repayment_typestringnoHow the loan is repaid. On create, annuity_loan when omitted.Values:annuity_loanbullet_loaninitial_repayment_freerepayment_substitute
repayment_free_monthsinteger | nullnoMonths with interest-only payments at the start (initial_repayment_free).
repayment_substitute_monthlynumber | nullnoMonthly savings into the Tilgungsträger (repayment_substitute), EUR, more than 0.
repayment_substitute_expected_returnnumber | nullnoExpected annual return on the Tilgungsträger as a 0-1 fraction (0.04 = 4 %).
fixed_repayment_ratenumber | nullnoFixed 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_datestring | nullnoPlanned payoff date: the loan is repaid in full then, not refinanced.
previous_loan_idinteger | nullnoThe loan this one refinances (Anschlussdarlehen); a loan of the same property.
processing_feenumbernoOne-time fee as a 0-1 fraction of the loan amount (0.01 = 1 %); 0 on create when omitted. Fix & flip only.
loan_duration_monthsintegernoMonths the loan runs in a fix & flip calculation; 6 on create when omitted.
property_idstringyesProperty id from properties_list.

RESTPOST /api/v1/properties/{id}/loans

properties_patch

WriteDestructiveFree

Update Property

Update a property by id (partial; unknown fields are rejected). Move between pipeline stages with property_stage_id (from property_stages_list). Mark a property as sold by setting sale_date + sale_price (null both to undo). Fix & flip assumptions: fixflip_project_duration_in_months, fixflip_target_sqm_price, renovation_detail + estimated_renovation_costs_per_square_meter. The Hausgeld share the owner carries per Wirtschaftsplan is operating_costs_non_transferable (at most the Hausgeld; null derives it as Hausgeld minus prepayment), and operating_costs_reserve the WEG reserve inside it (a cost, not tax-deductible until the WEG spends it). AfA from the Kaufpreisaufteilung or the tax assessment: buyhold_building_share is the building AfA basis in EUR (an amount, not a share; land is the rest), buyhold_amortization_rate a fraction (0.02 = 2 %), buyhold_amortization_method linear or degressive, always sent with its rate. Record where that split stands with depreciation_basis_status (declared or assessed for tax-office values) and its source with depreciation_basis_document_id. Other writable fields include living_area, purchase_price, purchase_date, strategy, unit/floor numbers, building_year, number_of_indoor_parking_spaces / number_of_outdoor_parking_spaces (parking_spaces on the response is their sum and is not writable), rooms/units/bathrooms, external_ref, and images (an https URL on an allowed image host, or the stored references properties_images_upload returns; upload raw bytes with it first).

Inputs

NameTypeRequiredDescription
idstringyes
namestring | nullno
property_stage_idstringno
notesstring | nullno
listing_linkstring | nullno
descriptionstring | nullno
purchase_pricenumberno
living_areanumberno
purchase_datestringno
sale_datestring | nullno
sale_pricenumber | nullno
strategystringnoValues:buy_and_holdfix_and_flipown_usespecial_rental
property_typestringnoValues:multi_family_househouseapartment
fixflip_project_duration_in_monthsintegerno
fixflip_target_sqm_pricenumberno
renovation_detailstring | nullnoValues:simpledetailedcomplete
estimated_renovation_costs_per_square_meternumberno
board_order_indexintegerno
imagestring | nullno
imagesarray<string>no
linksanyno
external_refstring | nullno
unit_numberstring | nullno
floor_numberinteger | nullno
building_yearinteger | nullno
number_of_indoor_parking_spacesinteger | nullno
number_of_outdoor_parking_spacesinteger | nullno
number_of_roomsnumber | nullno
number_of_unitsinteger | nullno
number_of_bathroomsinteger | nullno
operating_costs_non_transferablenumber | nullno
operating_costs_reservenumber | nullno
rent_netnumberno
purchase_price_discountnumber | nullno
buyhold_building_sharenumber | nullnoBuilding AfA basis in EUR (Gebäudeanteil as an amount, not a share): the building part of purchase price plus ancillary costs, e.g. 200000. Land is the rest. 0 or at least 100.
buyhold_amortization_ratenumbernoAfA rate per year as a fraction: 0.02 = 2 %, 0.03 = 3 %, 0.05 = 5 % degressive.
buyhold_amortization_methodstringnolinear (§ 7 Abs. 4 EStG) or degressive (§ 7 Abs. 5a EStG). Requires buyhold_amortization_rate in the same call (refused otherwise).Values:lineardegressive
depreciation_basis_statusstring | nullnoWhere the AfA split stands: proposed (an estimate), declared (in the tax return), assessed (confirmed by the tax office), disputed (objection filed). declared, assessed and disputed keep buyhold_building_share as an amount when the price changes. null: not stated.Values:proposeddeclaredassesseddisputed
depreciation_basis_document_idstring | nullnoId of the document the AfA split comes from (Kaufvertrag, Kaufpreisaufteilung, Steuerbescheid), from documents_upload or properties_documents_list. Any of your own documents; null clears it.
energy_labelstring | nullnoValues:a_plus_plus_plusa_plus_plusa_plusabcdefgh
is_leaseholdboolean | nullno
leasehold_end_datestring | nullno
land_registry_courtstring | nullno
land_registry_districtstring | nullno
land_registry_sheetstring | nullno
cadastral_sectorstring | nullno
cadastral_parcelstring | nullno
co_ownership_sharenumber | nullno
co_ownership_share_totalnumber | nullno

RESTPATCH /api/v1/properties/{id}

Export Property PDF

Export a property’s calculation as a PDF. Returns an embedded application/pdf resource (base64). The PDF carries the account’s referral link in the footer and as a QR code on the last page; a paid plan can switch it off in the app. Costs 2 API credits.

Inputs

NameTypeRequiredDescription
property_idstringyes

RESTPOST /api/v1/properties/{id}/export

Apply Rent Roll

Apply a rent roll (Mieterliste) to a property: creates units, tenancies and tenant contacts from a completed rent_roll extraction (pass document_id) or an inline rent_roll (units[].unit_label is required, plus living_area_sqm for a unit that does not exist yet; lease_end_date records an ended lease). Per unit, operating_costs_monthly is the Nebenkostenvorauszahlung the tenant pays (tenancy operating_costs_transferable) and owner_costs_monthly the Hausgeld the owner pays (tenancy operating_costs, at least the prepayment); without owner_costs_monthly the prepayment stands in as Hausgeld and the unit is listed in owner_costs_defaulted: ask the user for the Hausgeld and set it with tenancies_patch (operating_costs). non_transferable_monthly is the share of the Hausgeld the owner carries per Wirtschaftsplan (tenancy operating_costs_non_transferable, at most the Hausgeld); missing, it is derived. reserve_monthly is the WEG reserve inside that share (tenancy operating_costs_reserve). A row the database would refuse fails the whole apply with a 422 naming the unit, before anything is written. Units are matched by name; an existing unit gets the tenancy unless it already holds that tenant or another tenant still occupies it (occupied_units: end that tenancy with tenancies_patch, then re-apply). A tenant the property already has is reused. Safe to retry. Units listed in start_date_defaulted got today as lease start: confirm the real dates with the user and correct them with tenancies_patch. Show the user the parsed units (documents_get with include ["extraction"]) and get their confirmation before calling this. To correct a tenancy afterwards, use tenancies_patch.

Inputs

NameTypeRequiredDescription
property_idstringyes
document_idstringno
rent_rollobjectno

RESTPOST /api/v1/properties/{id}/rent-roll/apply

Import Tenancies

Bulk-create tenancies for a property, optionally assigned to existing units via unit_id (from properties_units_list). start_date (YYYY-MM-DD) is required: ask the user when the list has none. A tenant the property already has is reused by name instead of duplicated. Safe to retry: a row whose tenant already has a tenancy on that unit with that start date is skipped. To correct a tenancy afterwards, use tenancies_patch.

Inputs

NameTypeRequiredDescription
tenantsarray<object>yes
property_idstringyes

RESTPOST /api/v1/properties/{id}/tenancies/import

List Property Units

List units of a property with their tenancies (tenant contacts in lease order, rent_net at the lease start, rent_net_target, and events: the dated changes such as rent increases, each applying from its month on), paginated. Use to inspect the unit/tenant structure, e.g. before or after applying a rent roll, and to find tenancy_id and event_id for tenancies_events_create / _delete.

Inputs

NameTypeRequiredDescription
property_idstringyes
limitintegerno
offsetintegerno

RESTGET /api/v1/properties/{id}/units

Create Property Stage

Create a custom property stage under a property lifecycle. Requires lifecycle, name, color (#RRGGBB).

Inputs

NameTypeRequiredDescription
lifecyclestringyesValues:newin_progresspurchasedcanceled
namestringyes
descriptionstring | nullno
colorstringyes

RESTPOST /api/v1/property-stages

Delete Property Stage

Delete a property stage and reassign its properties to replacement_stage_id (same property lifecycle). Cannot delete archived, last stage in a lifecycle, or creation-default new stage.

Inputs

NameTypeRequiredDescription
replacement_stage_idstringyes
idstringyes

RESTDELETE /api/v1/property-stages/{id}

List Property Stages

List property stages (pipeline steps under property lifecycles new|in_progress|purchased|canceled). Optional lifecycle filter (comma-separated). Each item includes property_count. Prefer this before filtering properties_list by property_stage_id.

Inputs

NameTypeRequiredDescription
lifecyclestringno
limitintegerno
offsetintegerno

RESTGET /api/v1/property-stages

Update Property Stage

Patch a property stage by id (name, description, color, sort_order, is_default). is_default only for lifecycle=new. Cannot rename archived.

Inputs

NameTypeRequiredDescription
namestringno
descriptionstring | nullno
colorstringno
sort_orderintegerno
is_defaultbooleanno
idstringyes

RESTPATCH /api/v1/property-stages/{id}