Heimster API
OpenAPI 3.2Version 1.0.0 · Basis-URL https://heimster.ch/api/v1
Lieber ohne Code? Heimster direkt im KI-Tool nutzen
Verbinden Sie Claude, Cursor, ChatGPT & Co. über den MCP-Server – zur Anleitung.
Den vollständigen Key einfügen — Sie finden ihn in Ihren API-Einstellungen (bei jedem Key über „Anzeigen“), nicht die gekürzte Vorschau. Wird lokal im Browser gespeichert, füllt alle Beispiele und aktiviert „Senden“ bei Lese-Endpunkten.
Authentifizierung
Bearer API key in the Authorization header: Authorization: Bearer hm_…. Create a key under Einstellungen → API, choosing the scopes it needs. Each endpoint lists its required scope.
Pagination
List endpoints are cursor-paged and return { data: [...], nextCursor: string | null }. Pass ?limit= (max 100) and ?cursor= (the previous response's nextCursor). When nextCursor is null there are no more pages.
Format
Single items return { data: {...} }; lists return { data: [...], nextCursor }. Money is integer CHF; timestamps are ISO-8601.
Fehler
Errors return the appropriate status with { message }: 401 (no/invalid key), 403 (key missing the scope), 404 (not found or not yours), 422 (validation), 429 (rate limit).
Rate Limits
Requests are limited per key: 120/min by default, with tighter buckets on heavy endpoints (export 15/min, email 30/min). Every response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds); a 429 adds Retry-After. Back off when remaining hits 0.
/api/v1/contactsList contacts
contacts:readYour CRM contacts, most recent first.
Parameter
q stringQuery. Search name / email / company.
limit integerQuery. Page size, max 100 (default 50).
cursor stringQuery. The previous response's `nextCursor`.
Response · data
id string name string | null firstName string | null lastName string | null email string phone string | null company string | null role string | null city string | null canton string | null postalCode string | null country string status string source string | null tags string[] summary string createdAt string (ISO-8601) updatedAt string (ISO-8601) curl https://heimster.ch/api/v1/contacts \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "21321f20-…",
"name": "Lukas Test",
"firstName": "Lukas",
"lastName": "Test",
"email": "demo@demo.com",
"phone": null,
"company": null,
"role": "Käufer",
"city": "Zürich",
"canton": null,
"postalCode": null,
"country": "CH",
"status": "active",
"source": "buyer",
"tags": [],
"summary": "Lukas Test · Käufer · Zürich",
"createdAt": "2026-08-07T18:19:24.111Z",
"updatedAt": "2026-08-07T18:19:24.111Z"
}
],
"nextCursor": "eyJ0Ijoi…"
}/api/v1/contactsCreate a contact
contacts:writeCreates a contact, or updates the existing one with the same email. Triggers the HubSpot sync when connected.
Body
email stringPrimary email — the dedupe key within your org.
firstName stringlastName stringphone stringcompany stringrole stringwebsite stringcity stringcanton stringpostalCode stringcountry stringISO country code (default CH).
tags string[]internalNotes stringResponse · data
id string name string | null firstName string | null lastName string | null email string phone string | null company string | null role string | null city string | null canton string | null postalCode string | null country string status string source string | null tags string[] summary string createdAt string (ISO-8601) updatedAt string (ISO-8601) curl -X POST https://heimster.ch/api/v1/contacts \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"…":"…"}' {
"data": {
"id": "21321f20-…",
"name": "Lukas Test",
"firstName": "Lukas",
"lastName": "Test",
"email": "demo@demo.com",
"phone": null,
"company": null,
"role": "Käufer",
"city": "Zürich",
"canton": null,
"postalCode": null,
"country": "CH",
"status": "active",
"source": "buyer",
"tags": [],
"summary": "Lukas Test · Käufer · Zürich",
"createdAt": "2026-08-07T18:19:24.111Z",
"updatedAt": "2026-08-07T18:19:24.111Z"
}
}/api/v1/contacts/{id}Get a contact
contacts:readParameter
id uuid · requiredPfad. Contact id.
Response · data
id string name string | null firstName string | null lastName string | null email string phone string | null company string | null role string | null city string | null canton string | null postalCode string | null country string status string source string | null tags string[] summary string createdAt string (ISO-8601) updatedAt string (ISO-8601) curl https://heimster.ch/api/v1/contacts/{id} \
-H "Authorization: Bearer hm_…" {
"data": {
"id": "21321f20-…",
"name": "Lukas Test",
"firstName": "Lukas",
"lastName": "Test",
"email": "demo@demo.com",
"phone": null,
"company": null,
"role": "Käufer",
"city": "Zürich",
"canton": null,
"postalCode": null,
"country": "CH",
"status": "active",
"source": "buyer",
"tags": [],
"summary": "Lukas Test · Käufer · Zürich",
"createdAt": "2026-08-07T18:19:24.111Z",
"updatedAt": "2026-08-07T18:19:24.111Z"
}
}/api/v1/contacts/{id}Update a contact
contacts:writeUpdates the given fields. Triggers the HubSpot sync (loop-guarded).
Parameter
id uuid · requiredPfad. Contact id.
Body
email stringPrimary email — the dedupe key within your org.
firstName stringlastName stringphone stringcompany stringrole stringwebsite stringcity stringcanton stringpostalCode stringcountry stringISO country code (default CH).
tags string[]internalNotes stringResponse · data
id string name string | null firstName string | null lastName string | null email string phone string | null company string | null role string | null city string | null canton string | null postalCode string | null country string status string source string | null tags string[] summary string createdAt string (ISO-8601) updatedAt string (ISO-8601) curl -X PATCH https://heimster.ch/api/v1/contacts/{id} \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"…":"…"}' {
"data": {
"id": "21321f20-…",
"name": "Lukas Test",
"firstName": "Lukas",
"lastName": "Test",
"email": "demo@demo.com",
"phone": null,
"company": null,
"role": "Käufer",
"city": "Zürich",
"canton": null,
"postalCode": null,
"country": "CH",
"status": "active",
"source": "buyer",
"tags": [],
"summary": "Lukas Test · Käufer · Zürich",
"createdAt": "2026-08-07T18:19:24.111Z",
"updatedAt": "2026-08-07T18:19:24.111Z"
}
}/api/v1/contacts/{id}/activitiesList a contact's activities
activities:readThe contact's timeline (notes, tasks, calls, emails).
Parameter
id uuid · requiredPfad. Contact id.
limit integerQuery. Page size, max 100 (default 50).
cursor stringQuery. The previous response's `nextCursor`.
Response · data
id string activityType string title string body string | null summary string occurredAt string (ISO-8601) refs object createdAt string (ISO-8601) curl https://heimster.ch/api/v1/contacts/{id}/activities \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "…",
"activityType": "note",
"title": "Erstkontakt",
"body": null,
"occurredAt": "2026-08-26T09:00:00.000Z",
"refs": {
"objectId": null,
"listingId": null,
"applicationId": null,
"projectId": null,
"anlageobjektId": null,
"appointmentId": null
},
"createdAt": "2026-08-26T09:00:00.000Z"
}
],
"nextCursor": "eyJ0Ijoi…"
}/api/v1/contacts/{id}/activitiesAdd a note / activity
activities:writeAdds an entry to the contact's timeline.
Parameter
id uuid · requiredPfad. Contact id.
Body
title string · requiredbody stringactivityType stringOne of note, task, meeting, phone_outgoing, phone_incoming, email (default note).
Response · data
id string activityType string title string body string | null summary string occurredAt string (ISO-8601) refs object createdAt string (ISO-8601) curl -X POST https://heimster.ch/api/v1/contacts/{id}/activities \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"title":"…"}' {
"data": {
"id": "…",
"activityType": "note",
"title": "Erstkontakt",
"body": null,
"occurredAt": "…",
"refs": {},
"createdAt": "…"
}
}/api/v1/objectsList objects
objects:readThe source-of-truth properties, including unpublished. q searches the address (street / city / postal code) and internal reference — e.g. find an object by street.
Parameter
status stringQuery. Filter by status.
q stringQuery. Search address (street/city/postal code) + internal reference.
limit integerQuery. Page size, max 100 (default 50).
cursor stringQuery. The previous response's `nextCursor`.
Response · data
id string project object | null projectId string | null propertyType string status string enumvacantlistedoccupiedfor_salesoldrenovationarchivedstatusLabel string intendedUse string enumrentsalebothintendedUseLabel string address object summary string rooms number | null livingSpaceSqm number | null plotSqm number | null price number | null floorNumber number | null totalFloors number | null yearBuilt number | null availableFrom string | null internalReference string | null createdAt string (ISO-8601) updatedAt string (ISO-8601) curl https://heimster.ch/api/v1/objects \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "26aeb002-…",
"project": null,
"projectId": null,
"propertyType": "apartment",
"status": "vacant",
"statusLabel": "Leerstehend",
"intendedUse": "rent",
"intendedUseLabel": "Vermietung",
"address": {
"street": "Schösslerstrasse 14",
"city": "Rudolfstetten",
"canton": "AG",
"postalCode": "8964"
},
"summary": "apartment · Schösslerstrasse 14, 8964 Rudolfstetten · Leerstehend",
"rooms": 3.5,
"livingSpaceSqm": 92,
"plotSqm": null,
"price": 850000,
"floorNumber": 1,
"totalFloors": 3,
"yearBuilt": 2003,
"availableFrom": null,
"internalReference": null,
"createdAt": "2026-08-01T10:00:00.000Z",
"updatedAt": "2026-08-01T10:00:00.000Z"
}
],
"nextCursor": "eyJ0Ijoi…"
}/api/v1/objects/{id}Get an object
objects:readParameter
id uuid · requiredPfad. Object id.
Response · data
id string project object | null projectId string | null propertyType string status string enumvacantlistedoccupiedfor_salesoldrenovationarchivedstatusLabel string intendedUse string enumrentsalebothintendedUseLabel string address object summary string rooms number | null livingSpaceSqm number | null plotSqm number | null price number | null floorNumber number | null totalFloors number | null yearBuilt number | null availableFrom string | null internalReference string | null createdAt string (ISO-8601) updatedAt string (ISO-8601) curl https://heimster.ch/api/v1/objects/{id} \
-H "Authorization: Bearer hm_…" {
"data": {
"id": "26aeb002-…",
"project": null,
"projectId": null,
"propertyType": "apartment",
"status": "vacant",
"statusLabel": "Leerstehend",
"intendedUse": "rent",
"intendedUseLabel": "Vermietung",
"address": {
"street": "Schösslerstrasse 14",
"city": "Rudolfstetten",
"canton": "AG",
"postalCode": "8964"
},
"summary": "apartment · Schösslerstrasse 14, 8964 Rudolfstetten · Leerstehend",
"rooms": 3.5,
"livingSpaceSqm": 92,
"plotSqm": null,
"price": 850000,
"floorNumber": 1,
"totalFloors": 3,
"yearBuilt": 2003,
"availableFrom": null,
"internalReference": null,
"createdAt": "2026-08-01T10:00:00.000Z",
"updatedAt": "2026-08-01T10:00:00.000Z"
}
}/api/v1/objects/{id}Edit an object
objects:writeUpdates the given fields. intendedUse can't be changed here (it can desync active listings).
Parameter
id uuid · requiredPfad. Object id.
Body
status stringprice integerCHF
rooms numberlivingSpaceSqm numberyearBuilt integernotes stringdescription stringResponse · data
id string project object | null projectId string | null propertyType string status string enumvacantlistedoccupiedfor_salesoldrenovationarchivedstatusLabel string intendedUse string enumrentsalebothintendedUseLabel string address object summary string rooms number | null livingSpaceSqm number | null plotSqm number | null price number | null floorNumber number | null totalFloors number | null yearBuilt number | null availableFrom string | null internalReference string | null createdAt string (ISO-8601) updatedAt string (ISO-8601) curl -X PATCH https://heimster.ch/api/v1/objects/{id} \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"…":"…"}' {
"data": {
"id": "26aeb002-…",
"project": null,
"projectId": null,
"propertyType": "apartment",
"status": "vacant",
"statusLabel": "Leerstehend",
"intendedUse": "rent",
"intendedUseLabel": "Vermietung",
"address": {
"street": "Schösslerstrasse 14",
"city": "Rudolfstetten",
"canton": "AG",
"postalCode": "8964"
},
"summary": "apartment · Schösslerstrasse 14, 8964 Rudolfstetten · Leerstehend",
"rooms": 3.5,
"livingSpaceSqm": 92,
"plotSqm": null,
"price": 850000,
"floorNumber": 1,
"totalFloors": 3,
"yearBuilt": 2003,
"availableFrom": null,
"internalReference": null,
"createdAt": "2026-08-01T10:00:00.000Z",
"updatedAt": "2026-08-01T10:00:00.000Z"
}
}/api/v1/objects/{id}/interested-partiesRanked buyers for an object
pipeline:readThe prospects on an object, ranked by curation score then recency. exposeReceived tells you who has already been sent the exposé/dossier — so you can email only those who haven't.
Parameter
id uuid · requiredPfad. Object id.
Response · data
id string status string enumvorgemerktprospectexpose_sentinteresse_bekundetkaufinteresse_angemeldetviewingapplication_receivedshortlistedzusagecontract_sentcontract_signedwaitlistofferreservationnotarywonlostwithdrawnDeckt Miet- und Kaufprozess ab – nicht jeder Wert tritt in beiden Zweigen auf.
statusLabel string track string | null enumrentsaletrackLabel string | null channel string | null enumplatformemailphonemanualimportcurationScore number | null contact object | null summary string createdAt string (ISO-8601) curl https://heimster.ch/api/v1/objects/{id}/interested-parties \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "…",
"status": "prospect",
"statusLabel": "Erstkontakt",
"track": "sale",
"trackLabel": "Verkauf",
"channel": "manual",
"curationScore": 88,
"contact": {
"id": "…",
"name": "Lukas Test",
"email": "demo@demo.com",
"phone": null
},
"exposeReceived": false,
"exposeSentAt": null,
"summary": "Lukas Test · Erstkontakt · Verkauf",
"createdAt": "…"
}
],
"nextCursor": null
}/api/v1/projectsList projects
projects:readNew-build projects.
Parameter
limit integerQuery. Page size, max 100 (default 50).
cursor stringQuery. The previous response's `nextCursor`.
Response · data
id string slug string name string projectType string enumrentsalemixedprojectTypeLabel string status string enumplanningmarketingin_progresscompletedstatusLabel string address object summary string createdAt string (ISO-8601) updatedAt string (ISO-8601) curl https://heimster.ch/api/v1/projects \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "…",
"slug": "haus-morosani",
"name": "Haus Morosani",
"projectType": "rent",
"projectTypeLabel": "Miete",
"status": "marketing",
"statusLabel": "Vermarktung",
"address": {
"street": "…",
"city": "Zürich",
"canton": "ZH",
"postalCode": "8001"
},
"summary": "Haus Morosani · …, Zürich · Vermarktung",
"createdAt": "…",
"updatedAt": "…"
}
],
"nextCursor": "eyJ0Ijoi…"
}/api/v1/projects/{id}Get a project
projects:readParameter
id uuid · requiredPfad. Project id.
Response · data
id string slug string name string projectType string enumrentsalemixedprojectTypeLabel string status string enumplanningmarketingin_progresscompletedstatusLabel string address object summary string createdAt string (ISO-8601) updatedAt string (ISO-8601) curl https://heimster.ch/api/v1/projects/{id} \
-H "Authorization: Bearer hm_…" {
"data": {
"id": "…",
"slug": "haus-morosani",
"name": "Haus Morosani",
"projectType": "rent",
"projectTypeLabel": "Miete",
"status": "marketing",
"statusLabel": "Vermarktung",
"address": {},
"summary": "…",
"createdAt": "…",
"updatedAt": "…"
}
}/api/v1/anlageobjekteList investment properties
anlageobjekte:readParameter
limit integerQuery. Page size, max 100 (default 50).
cursor stringQuery. The previous response's `nextCursor`.
Response · data
id string slug string name string address object zone string | null yearBuilt number | null parcelSqm number | null purchasePrice number | null soldAt string | null archivedAt string | null summary string createdAt string (ISO-8601) updatedAt string (ISO-8601) curl https://heimster.ch/api/v1/anlageobjekte \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "…",
"slug": "mfh-potenzial",
"name": "Mehrfamilienhaus mit Potenzial",
"address": {},
"zone": "W2",
"yearBuilt": 1975,
"parcelSqm": 820,
"purchasePrice": 3200000,
"soldAt": null,
"archivedAt": null,
"createdAt": "…",
"updatedAt": "…"
}
],
"nextCursor": "eyJ0Ijoi…"
}/api/v1/anlageobjekte/{id}Get an investment property
anlageobjekte:readParameter
id uuid · requiredPfad. Anlageobjekt id.
Response · data
id string slug string name string address object zone string | null yearBuilt number | null parcelSqm number | null purchasePrice number | null soldAt string | null archivedAt string | null summary string createdAt string (ISO-8601) updatedAt string (ISO-8601) curl https://heimster.ch/api/v1/anlageobjekte/{id} \
-H "Authorization: Bearer hm_…" {
"data": {
"id": "…",
"slug": "mfh-potenzial",
"name": "…",
"address": {},
"zone": "W2",
"yearBuilt": 1975,
"parcelSqm": 820,
"purchasePrice": 3200000,
"soldAt": null,
"archivedAt": null,
"createdAt": "…",
"updatedAt": "…"
}
}/api/v1/listingsList listings
listings:readYour published/draft listings.
Parameter
status stringQuery. Filter by status.
limit integerQuery. Page size, max 100 (default 50).
cursor stringQuery. The previous response's `nextCursor`.
Response · data
id string objectId string | null title string status string enumdraftactiveinactiverentedsoldarchivedstatusLabel string price number | null address object summary string publishedAt string | null createdAt string (ISO-8601) curl https://heimster.ch/api/v1/listings \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "…",
"objectId": "…",
"title": "3.5-Zi Wohnung – Schösslerstrasse 14",
"status": "active",
"statusLabel": "Aktiv / publiziert",
"price": 850000,
"address": {
"street": "Schösslerstrasse 14",
"city": "Rudolfstetten"
},
"summary": "3.5-Zi Wohnung – Schösslerstrasse 14 · Rudolfstetten · Aktiv / publiziert",
"publishedAt": "…",
"createdAt": "…"
}
],
"nextCursor": "eyJ0Ijoi…"
}/api/v1/listingsCreate a listing
listings:writeCreates a draft, attributed to your org owner. Use POST /listings/{id}/publish to take it live.
Body
category string · requiredpropertyType string · requiredtitle string · requireddescription string · requiredprice integer · requiredCHF
city string · requiredcanton stringpostalCode stringstreet stringResponse · data
id string objectId string | null title string status string enumdraftactiveinactiverentedsoldarchivedstatusLabel string price number | null address object summary string publishedAt string | null createdAt string (ISO-8601) curl -X POST https://heimster.ch/api/v1/listings \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"category":"…","propertyType":"…","title":"…","description":"…","price":0,"city":"…"}' {
"data": {
"id": "…",
"objectId": null,
"title": "…",
"status": "draft",
"statusLabel": "Entwurf",
"price": 850000,
"address": {},
"summary": "… · Zürich · Entwurf",
"publishedAt": null,
"createdAt": "…"
}
}/api/v1/listings/{id}Get a listing
listings:readParameter
id uuid · requiredPfad. Listing id.
Response · data
id string objectId string | null title string status string enumdraftactiveinactiverentedsoldarchivedstatusLabel string price number | null address object summary string publishedAt string | null createdAt string (ISO-8601) curl https://heimster.ch/api/v1/listings/{id} \
-H "Authorization: Bearer hm_…" {
"data": {
"id": "…",
"objectId": "…",
"title": "…",
"status": "active",
"statusLabel": "Aktiv / publiziert",
"price": 850000,
"address": {},
"summary": "…",
"publishedAt": "…",
"createdAt": "…"
}
}/api/v1/listings/{id}Update a listing
listings:writeParameter
id uuid · requiredPfad. Listing id.
Response · data
id string objectId string | null title string status string enumdraftactiveinactiverentedsoldarchivedstatusLabel string price number | null address object summary string publishedAt string | null createdAt string (ISO-8601) curl -X PATCH https://heimster.ch/api/v1/listings/{id} \
-H "Authorization: Bearer hm_…" {
"data": {
"id": "…",
"status": "active",
"statusLabel": "Aktiv / publiziert",
"summary": "…"
}
}/api/v1/listings/{id}/publishPublish a draft listing
listings:writeTakes a draft live with the full go-live side-effects (object status, marketing cycle, price history, matching alerts). No-op (published:false) if it isn't a draft.
Parameter
id uuid · requiredPfad. Listing id.
Response · data
id string objectId string | null title string status string enumdraftactiveinactiverentedsoldarchivedstatusLabel string price number | null address object summary string publishedAt string | null createdAt string (ISO-8601) curl -X POST https://heimster.ch/api/v1/listings/{id}/publish \
-H "Authorization: Bearer hm_…" {
"data": {
"id": "…",
"status": "active",
"statusLabel": "Aktiv / publiziert",
"published": true,
"summary": "…"
}
}/api/v1/listings/{id}Deactivate a listing
listings:writeSoft delete — sets the listing to inactive (keeps audit-trail links). Does not hard-delete.
Parameter
id uuid · requiredPfad. Listing id.
curl -X DELETE https://heimster.ch/api/v1/listings/{id} \
-H "Authorization: Bearer hm_…" {
"data": {
"id": "…",
"status": "inactive",
"deactivated": true
}
}/api/v1/applicationsList applications
applications:readApplications across your listings — with the applicant's name and the listing resolved.
Parameter
listingId uuidQuery. Filter to one listing.
status stringQuery. Filter by status.
limit integerQuery. Page size, max 100 (default 50).
cursor stringQuery. The previous response's `nextCursor`.
Response · data
id string status string enuminterestedpendingshortlistedzusagecontract_sentcontract_signedwaitlistrejectedacceptedwithdrawnstatusLabel string score number | null applicant object | null listing object listingId string summary string createdAt string (ISO-8601) curl https://heimster.ch/api/v1/applications \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "…",
"status": "shortlisted",
"statusLabel": "Vorgemerkt",
"score": 88,
"applicant": {
"id": "…",
"name": "Anna Muster"
},
"listing": {
"id": "…",
"title": "3.5-Zi Wohnung Zürich",
"address": "Bahnhofstrasse 1, 8001 Zürich"
},
"listingId": "…",
"summary": "Anna Muster · 3.5-Zi Wohnung Zürich · Vorgemerkt · Score 88",
"createdAt": "…"
}
],
"nextCursor": "eyJ0Ijoi…"
}/api/v1/applications/{id}Get an application (with dossier)
applications:readThe enriched application plus the full dossier (name, verification badges, compatibility breakdown, shared documents). Email is consent-gated.
Parameter
id uuid · requiredPfad. Application id.
Response · data
id string status string enuminterestedpendingshortlistedzusagecontract_sentcontract_signedwaitlistrejectedacceptedwithdrawnstatusLabel string score number | null applicant object | null listing object listingId string summary string createdAt string (ISO-8601) curl https://heimster.ch/api/v1/applications/{id} \
-H "Authorization: Bearer hm_…" {
"data": {
"id": "…",
"status": "shortlisted",
"statusLabel": "Vorgemerkt",
"score": 88,
"applicant": {
"id": "…",
"name": "Anna Muster"
},
"listing": {
"id": "…",
"title": "…",
"address": "…"
},
"summary": "Anna Muster · … · Vorgemerkt · Score 88",
"dossier": {
"name": "Anna Muster",
"email": "anna@…",
"badges": [
{
"type": "email",
"verifiedAt": "…"
}
],
"compatibility": {
"score": 88,
"level": "excellent"
},
"documents": [],
"consentActive": true
}
}
}/api/v1/applications/{id}Change application status
applications:writeShortlist / reject / waitlist an applicant. Runs the full notify fan-out (timeline event, in-app message, e-mail, webhook) — the applicant IS notified. Closing statuses (zusage, contract_sent, contract_signed) have their own flows and are rejected.
Parameter
id uuid · requiredPfad. Application id.
Body
status string · requiredNew status.
rejectionReason stringFor a rejection.
rejectionNote stringInternal note.
messageSubject stringOverride the rejection e-mail subject.
messageBody stringOverride the rejection e-mail body.
Response · data
id string status string enuminterestedpendingshortlistedzusagecontract_sentcontract_signedwaitlistrejectedacceptedwithdrawnstatusLabel string score number | null applicant object | null listing object listingId string summary string createdAt string (ISO-8601) curl -X PATCH https://heimster.ch/api/v1/applications/{id} \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"status":"…"}' {
"data": {
"id": "…",
"status": "rejected",
"statusLabel": "Abgelehnt",
"applicant": {
"id": "…",
"name": "Anna Muster"
},
"listing": {},
"summary": "…"
}
}/api/v1/interested-parties/{id}Move an interested party's status
pipeline:writeReturns { before, after } so the caller can confirm the change.
Parameter
id uuid · requiredPfad. Interested-party id.
Body
status string · requiredThe new status.
curl -X PATCH https://heimster.ch/api/v1/interested-parties/{id} \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"status":"…"}' {
"data": {
"before": {
"status": "prospect"
},
"after": {
"status": "contacted"
}
}
}/api/v1/viewingsList viewing slots
viewings:readViewing slots across your listings, with the listing resolved.
Parameter
limit integerQuery. Page size, max 100 (default 50).
cursor stringQuery. The previous response's `nextCursor`.
Response · data
id string listing object listingId string date string (YYYY-MM-DD) startTime string endTime string maxAttendees number visibility string enumopeninvite_onlyvisibilityLabel string summary string createdAt string (ISO-8601) curl https://heimster.ch/api/v1/viewings \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "…",
"listing": {
"id": "…",
"title": "3.5-Zi Wohnung Limmatquai",
"address": "Limmatquai 1, 8001 Zürich"
},
"listingId": "…",
"date": "2026-06-18",
"startTime": "16:30:00",
"endTime": "18:00:00",
"maxAttendees": 8,
"visibility": "open",
"visibilityLabel": "Offen buchbar",
"summary": "3.5-Zi Wohnung Limmatquai · 2026-06-18 16:30–18:00 · Offen buchbar",
"createdAt": "…"
}
],
"nextCursor": "eyJ0Ijoi…"
}/api/v1/viewingsCreate a viewing slot
viewings:writeAdds a viewing slot to one of your listings.
Body
listingId uuid · requireddate string · requiredYYYY-MM-DD
startTime string · requiredHH:MM
endTime string · requiredHH:MM
maxAttendees integerDefault 1.
visibility stringResponse · data
id string listing object listingId string date string (YYYY-MM-DD) startTime string endTime string maxAttendees number visibility string enumopeninvite_onlyvisibilityLabel string summary string createdAt string (ISO-8601) curl -X POST https://heimster.ch/api/v1/viewings \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"listingId":"…","date":"…","startTime":"…","endTime":"…"}' {
"data": {
"id": "…",
"listing": {},
"listingId": "…",
"date": "2026-12-01",
"startTime": "14:00",
"endTime": "14:30",
"maxAttendees": 1,
"visibility": "open",
"visibilityLabel": "Offen buchbar",
"summary": "…"
}
}/api/v1/leadsList acquisition leads
leads:readYour tracked acquisition leads: a triage action plus the underlying signal.
Parameter
limit integerQuery. Page size, max 100 (default 50).
cursor stringQuery. The previous response's `nextCursor`.
Response · data
id string status string | null wiedervorlageAt string | null note string | null signal object | null summary string createdAt string (ISO-8601) curl https://heimster.ch/api/v1/leads \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "…",
"status": "pruefung",
"wiedervorlageAt": null,
"note": null,
"signal": {
"title": "Erbschaft Musterstrasse 5",
"category": "erbschaft",
"tier": "high",
"score": 82,
"leadKind": "verkauf",
"canton": "ZH",
"municipality": "Zürich",
"street": "Musterstrasse 5",
"ownerName": "Erbengemeinschaft Muster",
"ownerType": "private"
},
"summary": "Erbschaft Musterstrasse 5 · Musterstrasse 5, Zürich · Erbengemeinschaft Muster · pruefung",
"createdAt": "…"
}
],
"nextCursor": "eyJ0Ijoi…"
}/api/v1/analytics/listing/{id}Listing demand snapshots
analytics:readRecent demand snapshots for a listing — counts only, never identities.
Parameter
id uuid · requiredPfad. Listing id.
Response · data
id string listing object listingId string objectId string | null capturedAt string (ISO-8601) trigger string searches number profiles number strongDossiers number summary string curl https://heimster.ch/api/v1/analytics/listing/{id} \
-H "Authorization: Bearer hm_…" {
"data": [
{
"id": "…",
"listing": {
"id": "…",
"title": "3.5-Zi Wohnung Zürich"
},
"listingId": "…",
"objectId": "…",
"capturedAt": "…",
"trigger": "publish",
"searches": 214,
"profiles": 37,
"strongDossiers": 6,
"summary": "3.5-Zi Wohnung Zürich · 214 Suchen · 37 passende Profile · 6 starke Dossiers"
}
],
"nextCursor": null
}/api/v1/follow-upsCreate a follow-up
followups:writeA task on a contact/object timeline, due at dueAt.
Body
contactId uuidobjectId uuidtitle string · requiredbody stringdueAt ISO-8601Due date (defaults to now).
Response · data
id string activityType string title string body string | null summary string occurredAt string (ISO-8601) refs object createdAt string (ISO-8601) curl -X POST https://heimster.ch/api/v1/follow-ups \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"title":"…"}' {
"data": {
"id": "…",
"activityType": "task",
"title": "Rückruf nächste Woche",
"body": null,
"occurredAt": "2026-09-05T09:00:00.000Z",
"refs": {},
"createdAt": "…"
}
}/api/v1/email/draftDraft an email into your Outlook
email:draftComposes an email and leaves it as a draft in your connected Outlook mailbox (folder «Entwürfe») — never sends. You review, edit and send it yourself from Outlook. Needs a Microsoft mailbox connected (as the logged-in agent); without one, the composed text is returned unsaved.
Body
contactId uuidResolve the recipient from a contact.
to stringOr an explicit recipient.
subject string · requiredbody string · requiredcurl -X POST https://heimster.ch/api/v1/email/draft \
-H "Authorization: Bearer hm_…" \
-H "Content-Type: application/json" \
-d '{"subject":"…","body":"…"}' {
"data": {
"draft": {
"to": "demo@demo.com",
"toName": "Lukas Test",
"subject": "Ihre Anfrage",
"saved": true,
"location": "outlook",
"mailbox": "agent@makler.ch",
"webLink": "https://outlook.office.com/mail/…"
}
},
"note": "Entwurf liegt im Ordner «Entwürfe» Ihres Outlook-Postfachs, bereit zum Prüfen und Senden."
}/api/v1/exportExport
export:readBulk export of your data.
curl https://heimster.ch/api/v1/export \
-H "Authorization: Bearer hm_…" {
"data": {}
}Webhooks & Signaturen
Statt zu pollen können Sie Webhooks abonnieren: Heimster sendet bei jedem Ereignis einen signierten POST an Ihre HTTPS-URL. Webhooks richten Sie in den API-Einstellungen ein.
Ereignisse & data-Felder
application.created Eine neue Bewerbung ist eingegangen.
application.status_changed Der Status einer Bewerbung hat sich geändert.
application.withdrawn Eine Bewerbung wurde zurückgezogen.
offer.sent Eine Zusage/ein Angebot wurde an den Bewerber gesendet.
offer.accepted Der Bewerber hat die Zusage angenommen.
offer.rejected Der Bewerber hat die Zusage abgelehnt.
lease.signed Der Mietvertrag wurde von beiden Seiten unterschrieben.
viewing.booked Ein Besichtigungstermin wurde gebucht.
document.uploaded Dokument(e) wurden zur Bewerbung geteilt.
handover.completed Ein Übergabeprotokoll wurde abgeschlossen.
Alle IDs sind Strings. ? = kann fehlen / null sein.
Header
X-Heimster-EventName des Ereignisses, z. B. offer.accepted.
X-Heimster-Signaturesha256=<HMAC> des rohen Bodies mit Ihrem Signing-Secret.
X-Heimster-DeliveryEindeutige ID dieser Zustellung (identisch über Retries).
Zustellung & Retries
Antworten Sie mit 2xx, um den Empfang zu bestätigen. Bei Fehlern versucht Heimster es bis zu 5 Mal erneut (30 s, 2 min, 15 min, 1 h, 4 h). Nach 50 aufeinanderfolgenden Fehlern wird der Webhook automatisch deaktiviert.
{
"event": "offer.accepted",
"data": {
"offerId": "…",
"applicationId": "…",
"listingId": "…",
"tenantUserId": "…"
},
"timestamp": "2026-08-26T10:00:00.000Z"
}Die Hülle ist immer gleich; der data-Block variiert je Ereignis – die Felder stehen links.
import crypto from "crypto";
// rawBody = the exact bytes Heimster POSTed (not the parsed JSON)
function verify(rawBody, header, secret) {
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(header ?? "");
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
// Express example:
app.post("/heimster-webhook",
express.raw({ type: "application/json" }), (req, res) => {
const ok = verify(
req.body, // Buffer, thanks to express.raw
req.header("X-Heimster-Signature"),
process.env.HEIMSTER_SIGNING_SECRET,
);
if (!ok) return res.sendStatus(401);
const { event, data } = JSON.parse(req.body.toString());
// … handle event …
res.sendStatus(200);
});
