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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes |
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
| Name | Type | Required | Description |
|---|---|---|---|
| deal_id | string | no | |
| calculation_strategy | string | no | Values:buy_and_holdfix_and_flipown_usespecial_rental |
| property_type | string | no | Values:multi_family_househouseapartment |
| purchase_price | number | no | |
| living_area | number | no | |
| address | object | no | |
| interest_rate | number | no | |
| repayment_rate | number | no | |
| loan_amount_percentage | number | no | |
| search_profile_id | integer | no | One 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_new | boolean | no | |
| allow_incomplete | boolean | no | |
| placeholder_address | boolean | no | |
| created_via | string | no | Values:humannora_agentroutineleverageddsales_push |
| external_ref | string | null | no | |
| unit_number | string | null | no | |
| floor_number | integer | null | no | |
| building_year | integer | null | no | |
| number_of_indoor_parking_spaces | integer | null | no | |
| number_of_outdoor_parking_spaces | integer | null | no | |
| number_of_rooms | number | null | no | |
| number_of_units | integer | null | no | |
| number_of_bathrooms | integer | null | no | |
| energy_label | string | null | no | Values:a_plus_plus_plusa_plus_plusa_plusabcdefgh |
| is_leasehold | boolean | null | no | |
| land_registry_court | string | null | no | |
| land_registry_district | string | null | no | |
| land_registry_sheet | string | null | no | |
| cadastral_sector | string | null | no | |
| cadastral_parcel | string | null | no | |
| co_ownership_share | number | null | no | |
| co_ownership_share_total | number | null | no |
RESTPOST /api/v1/properties
Delete Property
Delete a property (calculation) by id.
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | yes |
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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes | |
| document_id | string | yes | |
| keys | array<string> | no | Values: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_keys | array<string> | no | |
| create_tenancy | boolean | no | |
| unit_id | string | no | |
| acknowledge_unit_mismatch | boolean | no |
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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes |
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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes | |
| document_ids | array<string> | yes | |
| is_pinned | boolean | no | |
| paths | object | no | |
| unit_ids | array<string> | no | Unit 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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes | |
| document_type | string | no | Only 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 |
| limit | integer | no | |
| offset | integer | no |
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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes | |
| document_ids | array<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
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | yes |
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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes | |
| content_base64 | string | yes |
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
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | yes | |
| range | string | yes | Values:fullyear1year10 |
| date_unit | string | no | Values: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
| Name | Type | Required | Description |
|---|---|---|---|
| property_lifecycle | string | no | |
| property_stage_id | string | no | |
| created_via | string | no | |
| external_ref | string | no | |
| limit | integer | no | |
| offset | integer | no |
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
| Name | Type | Required | Description |
|---|---|---|---|
| label | string | yes | Name of the loan, 1 to 50 characters. |
| start_date | string | yes | First month of the loan, YYYY-MM-DD. |
| loan_amount | number | yes | Loan amount in EUR. |
| interest_rate | number | yes | Nominal interest rate p.a. as a fraction, 0 to 0.2 (0.035 = 3.5 %). |
| repayment_rate | number | yes | 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. |
| property_id | string | yes | Property id from properties_list. |
RESTPOST /api/v1/properties/{id}/loans
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
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | yes | |
| name | string | null | no | |
| property_stage_id | string | no | |
| notes | string | null | no | |
| listing_link | string | null | no | |
| description | string | null | no | |
| purchase_price | number | no | |
| living_area | number | no | |
| purchase_date | string | no | |
| sale_date | string | null | no | |
| sale_price | number | null | no | |
| strategy | string | no | Values:buy_and_holdfix_and_flipown_usespecial_rental |
| property_type | string | no | Values:multi_family_househouseapartment |
| fixflip_project_duration_in_months | integer | no | |
| fixflip_target_sqm_price | number | no | |
| renovation_detail | string | null | no | Values:simpledetailedcomplete |
| estimated_renovation_costs_per_square_meter | number | no | |
| board_order_index | integer | no | |
| image | string | null | no | |
| images | array<string> | no | |
| links | any | no | |
| external_ref | string | null | no | |
| unit_number | string | null | no | |
| floor_number | integer | null | no | |
| building_year | integer | null | no | |
| number_of_indoor_parking_spaces | integer | null | no | |
| number_of_outdoor_parking_spaces | integer | null | no | |
| number_of_rooms | number | null | no | |
| number_of_units | integer | null | no | |
| number_of_bathrooms | integer | null | no | |
| operating_costs_non_transferable | number | null | no | |
| operating_costs_reserve | number | null | no | |
| rent_net | number | no | |
| purchase_price_discount | number | null | no | |
| buyhold_building_share | number | null | no | Building 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_rate | number | no | AfA rate per year as a fraction: 0.02 = 2 %, 0.03 = 3 %, 0.05 = 5 % degressive. |
| buyhold_amortization_method | string | no | linear (§ 7 Abs. 4 EStG) or degressive (§ 7 Abs. 5a EStG). Requires buyhold_amortization_rate in the same call (refused otherwise).Values:lineardegressive |
| depreciation_basis_status | string | null | no | Where 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_id | string | null | no | Id 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_label | string | null | no | Values:a_plus_plus_plusa_plus_plusa_plusabcdefgh |
| is_leasehold | boolean | null | no | |
| leasehold_end_date | string | null | no | |
| land_registry_court | string | null | no | |
| land_registry_district | string | null | no | |
| land_registry_sheet | string | null | no | |
| cadastral_sector | string | null | no | |
| cadastral_parcel | string | null | no | |
| co_ownership_share | number | null | no | |
| co_ownership_share_total | number | null | no |
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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes |
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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes | |
| document_id | string | no | |
| rent_roll | object | no |
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
| Name | Type | Required | Description |
|---|---|---|---|
| tenants | array<object> | yes | |
| property_id | string | yes |
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
| Name | Type | Required | Description |
|---|---|---|---|
| property_id | string | yes | |
| limit | integer | no | |
| offset | integer | no |
RESTGET /api/v1/properties/{id}/units
Create Property Stage
Create a custom property stage under a property lifecycle. Requires lifecycle, name, color (#RRGGBB).
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| lifecycle | string | yes | Values:newin_progresspurchasedcanceled |
| name | string | yes | |
| description | string | null | no | |
| color | string | yes |
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
| Name | Type | Required | Description |
|---|---|---|---|
| replacement_stage_id | string | yes | |
| id | string | yes |
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
| Name | Type | Required | Description |
|---|---|---|---|
| lifecycle | string | no | |
| limit | integer | no | |
| offset | integer | no |
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
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | no | |
| description | string | null | no | |
| color | string | no | |
| sort_order | integer | no | |
| is_default | boolean | no | |
| id | string | yes |
RESTPATCH /api/v1/property-stages/{id}