Heimster API

OpenAPI 3.2

Version 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.

API-Key zum Ausprobieren

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.

GET /api/v1/contacts

List contacts

contacts:read

Your CRM contacts, most recent first.

Parameter

q string

Query. Search name / email / company.

limit integer

Query. Page size, max 100 (default 50).

cursor string

Query. 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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…"
}
POST /api/v1/contacts

Create a contact

contacts:write

Creates a contact, or updates the existing one with the same email. Triggers the HubSpot sync when connected.

Body

email string

Primary email — the dedupe key within your org.

firstName string
lastName string
phone string
company string
role string
website string
city string
canton string
postalCode string
country string

ISO country code (default CH).

tags string[]
internalNotes string

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 -X POST https://heimster.ch/api/v1/contacts \
  -H "Authorization: Bearer hm_…" \
  -H "Content-Type: application/json" \
  -d '{"…":"…"}'
Response Beispiel
{
  "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"
  }
}
GET /api/v1/contacts/{id}

Get a contact

contacts:read

Parameter

id uuid · required

Pfad. 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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"
  }
}
PATCH /api/v1/contacts/{id}

Update a contact

contacts:write

Updates the given fields. Triggers the HubSpot sync (loop-guarded).

Parameter

id uuid · required

Pfad. Contact id.

Body

email string

Primary email — the dedupe key within your org.

firstName string
lastName string
phone string
company string
role string
website string
city string
canton string
postalCode string
country string

ISO country code (default CH).

tags string[]
internalNotes string

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 -X PATCH https://heimster.ch/api/v1/contacts/{id} \
  -H "Authorization: Bearer hm_…" \
  -H "Content-Type: application/json" \
  -d '{"…":"…"}'
Response Beispiel
{
  "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"
  }
}
GET /api/v1/contacts/{id}/activities

List a contact's activities

activities:read

The contact's timeline (notes, tasks, calls, emails).

Parameter

id uuid · required

Pfad. Contact id.

limit integer

Query. Page size, max 100 (default 50).

cursor string

Query. 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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…"
}
POST /api/v1/contacts/{id}/activities

Add a note / activity

activities:write

Adds an entry to the contact's timeline.

Parameter

id uuid · required

Pfad. Contact id.

Body

title string · required
body string
activityType string

One 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":"…"}'
Response Beispiel
{
  "data": {
    "id": "…",
    "activityType": "note",
    "title": "Erstkontakt",
    "body": null,
    "occurredAt": "…",
    "refs": {},
    "createdAt": "…"
  }
}
GET /api/v1/objects

List objects

objects:read

The 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 string

Query. Filter by status.

q string

Query. Search address (street/city/postal code) + internal reference.

limit integer

Query. Page size, max 100 (default 50).

cursor string

Query. The previous response's `nextCursor`.

Response · data

id string
project object | null
projectId string | null
propertyType string
status string enum
vacantlistedoccupiedfor_salesoldrenovationarchived
statusLabel string
intendedUse string enum
rentsaleboth
intendedUseLabel 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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…"
}
GET /api/v1/objects/{id}

Get an object

objects:read

Parameter

id uuid · required

Pfad. Object id.

Response · data

id string
project object | null
projectId string | null
propertyType string
status string enum
vacantlistedoccupiedfor_salesoldrenovationarchived
statusLabel string
intendedUse string enum
rentsaleboth
intendedUseLabel 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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"
  }
}
PATCH /api/v1/objects/{id}

Edit an object

objects:write

Updates the given fields. intendedUse can't be changed here (it can desync active listings).

Parameter

id uuid · required

Pfad. Object id.

Body

status string
price integer

CHF

rooms number
livingSpaceSqm number
yearBuilt integer
notes string
description string

Response · data

id string
project object | null
projectId string | null
propertyType string
status string enum
vacantlistedoccupiedfor_salesoldrenovationarchived
statusLabel string
intendedUse string enum
rentsaleboth
intendedUseLabel 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 '{"…":"…"}'
Response Beispiel
{
  "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"
  }
}
GET /api/v1/objects/{id}/interested-parties

Ranked buyers for an object

pipeline:read

The 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 · required

Pfad. Object id.

Response · data

id string
status string enum
vorgemerktprospectexpose_sentinteresse_bekundetkaufinteresse_angemeldetviewingapplication_receivedshortlistedzusagecontract_sentcontract_signedwaitlistofferreservationnotarywonlostwithdrawn

Deckt Miet- und Kaufprozess ab – nicht jeder Wert tritt in beiden Zweigen auf.

statusLabel string
track string | null enum
rentsale
trackLabel string | null
channel string | null enum
platformemailphonemanualimport
curationScore 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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
}
GET /api/v1/projects

List projects

projects:read

New-build projects.

Parameter

limit integer

Query. Page size, max 100 (default 50).

cursor string

Query. The previous response's `nextCursor`.

Response · data

id string
slug string
name string
projectType string enum
rentsalemixed
projectTypeLabel string
status string enum
planningmarketingin_progresscompleted
statusLabel string
address object
summary string
createdAt string (ISO-8601)
updatedAt string (ISO-8601)
curl https://heimster.ch/api/v1/projects \
  -H "Authorization: Bearer hm_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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…"
}
GET /api/v1/projects/{id}

Get a project

projects:read

Parameter

id uuid · required

Pfad. Project id.

Response · data

id string
slug string
name string
projectType string enum
rentsalemixed
projectTypeLabel string
status string enum
planningmarketingin_progresscompleted
statusLabel 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "data": {
    "id": "…",
    "slug": "haus-morosani",
    "name": "Haus Morosani",
    "projectType": "rent",
    "projectTypeLabel": "Miete",
    "status": "marketing",
    "statusLabel": "Vermarktung",
    "address": {},
    "summary": "…",
    "createdAt": "…",
    "updatedAt": "…"
  }
}
GET /api/v1/anlageobjekte

List investment properties

anlageobjekte:read

Parameter

limit integer

Query. Page size, max 100 (default 50).

cursor string

Query. 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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…"
}
GET /api/v1/anlageobjekte/{id}

Get an investment property

anlageobjekte:read

Parameter

id uuid · required

Pfad. 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "data": {
    "id": "…",
    "slug": "mfh-potenzial",
    "name": "…",
    "address": {},
    "zone": "W2",
    "yearBuilt": 1975,
    "parcelSqm": 820,
    "purchasePrice": 3200000,
    "soldAt": null,
    "archivedAt": null,
    "createdAt": "…",
    "updatedAt": "…"
  }
}
GET /api/v1/listings

List listings

listings:read

Your published/draft listings.

Parameter

status string

Query. Filter by status.

limit integer

Query. Page size, max 100 (default 50).

cursor string

Query. The previous response's `nextCursor`.

Response · data

id string
objectId string | null
title string
status string enum
draftactiveinactiverentedsoldarchived
statusLabel 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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…"
}
POST /api/v1/listings

Create a listing

listings:write

Creates a draft, attributed to your org owner. Use POST /listings/{id}/publish to take it live.

Body

category string · required
propertyType string · required
title string · required
description string · required
price integer · required

CHF

city string · required
canton string
postalCode string
street string

Response · data

id string
objectId string | null
title string
status string enum
draftactiveinactiverentedsoldarchived
statusLabel 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":"…"}'
Response Beispiel
{
  "data": {
    "id": "…",
    "objectId": null,
    "title": "…",
    "status": "draft",
    "statusLabel": "Entwurf",
    "price": 850000,
    "address": {},
    "summary": "… · Zürich · Entwurf",
    "publishedAt": null,
    "createdAt": "…"
  }
}
GET /api/v1/listings/{id}

Get a listing

listings:read

Parameter

id uuid · required

Pfad. Listing id.

Response · data

id string
objectId string | null
title string
status string enum
draftactiveinactiverentedsoldarchived
statusLabel 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "data": {
    "id": "…",
    "objectId": "…",
    "title": "…",
    "status": "active",
    "statusLabel": "Aktiv / publiziert",
    "price": 850000,
    "address": {},
    "summary": "…",
    "publishedAt": "…",
    "createdAt": "…"
  }
}
PATCH /api/v1/listings/{id}

Update a listing

listings:write

Parameter

id uuid · required

Pfad. Listing id.

Response · data

id string
objectId string | null
title string
status string enum
draftactiveinactiverentedsoldarchived
statusLabel 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_…"
Response Beispiel
{
  "data": {
    "id": "…",
    "status": "active",
    "statusLabel": "Aktiv / publiziert",
    "summary": "…"
  }
}
POST /api/v1/listings/{id}/publish

Publish a draft listing

listings:write

Takes 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 · required

Pfad. Listing id.

Response · data

id string
objectId string | null
title string
status string enum
draftactiveinactiverentedsoldarchived
statusLabel 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_…"
Response Beispiel
{
  "data": {
    "id": "…",
    "status": "active",
    "statusLabel": "Aktiv / publiziert",
    "published": true,
    "summary": "…"
  }
}
DELETE /api/v1/listings/{id}

Deactivate a listing

listings:write

Soft delete — sets the listing to inactive (keeps audit-trail links). Does not hard-delete.

Parameter

id uuid · required

Pfad. Listing id.

curl -X DELETE https://heimster.ch/api/v1/listings/{id} \
  -H "Authorization: Bearer hm_…"
Response Beispiel
{
  "data": {
    "id": "…",
    "status": "inactive",
    "deactivated": true
  }
}
GET /api/v1/applications

List applications

applications:read

Applications across your listings — with the applicant's name and the listing resolved.

Parameter

listingId uuid

Query. Filter to one listing.

status string

Query. Filter by status.

limit integer

Query. Page size, max 100 (default 50).

cursor string

Query. The previous response's `nextCursor`.

Response · data

id string
status string enum
interestedpendingshortlistedzusagecontract_sentcontract_signedwaitlistrejectedacceptedwithdrawn
statusLabel 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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…"
}
GET /api/v1/applications/{id}

Get an application (with dossier)

applications:read

The enriched application plus the full dossier (name, verification badges, compatibility breakdown, shared documents). Email is consent-gated.

Parameter

id uuid · required

Pfad. Application id.

Response · data

id string
status string enum
interestedpendingshortlistedzusagecontract_sentcontract_signedwaitlistrejectedacceptedwithdrawn
statusLabel 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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
    }
  }
}
PATCH /api/v1/applications/{id}

Change application status

applications:write

Shortlist / 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 · required

Pfad. Application id.

Body

status string · required

New status.

rejectionReason string

For a rejection.

rejectionNote string

Internal note.

messageSubject string

Override the rejection e-mail subject.

messageBody string

Override the rejection e-mail body.

Response · data

id string
status string enum
interestedpendingshortlistedzusagecontract_sentcontract_signedwaitlistrejectedacceptedwithdrawn
statusLabel 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":"…"}'
Response Beispiel
{
  "data": {
    "id": "…",
    "status": "rejected",
    "statusLabel": "Abgelehnt",
    "applicant": {
      "id": "…",
      "name": "Anna Muster"
    },
    "listing": {},
    "summary": "…"
  }
}
PATCH /api/v1/interested-parties/{id}

Move an interested party's status

pipeline:write

Returns { before, after } so the caller can confirm the change.

Parameter

id uuid · required

Pfad. Interested-party id.

Body

status string · required

The new status.

curl -X PATCH https://heimster.ch/api/v1/interested-parties/{id} \
  -H "Authorization: Bearer hm_…" \
  -H "Content-Type: application/json" \
  -d '{"status":"…"}'
Response Beispiel
{
  "data": {
    "before": {
      "status": "prospect"
    },
    "after": {
      "status": "contacted"
    }
  }
}
GET /api/v1/viewings

List viewing slots

viewings:read

Viewing slots across your listings, with the listing resolved.

Parameter

limit integer

Query. Page size, max 100 (default 50).

cursor string

Query. 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 enum
openinvite_only
visibilityLabel string
summary string
createdAt string (ISO-8601)
curl https://heimster.ch/api/v1/viewings \
  -H "Authorization: Bearer hm_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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…"
}
POST /api/v1/viewings

Create a viewing slot

viewings:write

Adds a viewing slot to one of your listings.

Body

listingId uuid · required
date string · required

YYYY-MM-DD

startTime string · required

HH:MM

endTime string · required

HH:MM

maxAttendees integer

Default 1.

visibility string

Response · data

id string
listing object
listingId string
date string (YYYY-MM-DD)
startTime string
endTime string
maxAttendees number
visibility string enum
openinvite_only
visibilityLabel 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":"…"}'
Response Beispiel
{
  "data": {
    "id": "…",
    "listing": {},
    "listingId": "…",
    "date": "2026-12-01",
    "startTime": "14:00",
    "endTime": "14:30",
    "maxAttendees": 1,
    "visibility": "open",
    "visibilityLabel": "Offen buchbar",
    "summary": "…"
  }
}
GET /api/v1/leads

List acquisition leads

leads:read

Your tracked acquisition leads: a triage action plus the underlying signal.

Parameter

limit integer

Query. Page size, max 100 (default 50).

cursor string

Query. 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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…"
}
GET /api/v1/analytics/listing/{id}

Listing demand snapshots

analytics:read

Recent demand snapshots for a listing — counts only, never identities.

Parameter

id uuid · required

Pfad. 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_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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
}
POST /api/v1/follow-ups

Create a follow-up

followups:write

A task on a contact/object timeline, due at dueAt.

Body

contactId uuid
objectId uuid
title string · required
body string
dueAt ISO-8601

Due 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":"…"}'
Response Beispiel
{
  "data": {
    "id": "…",
    "activityType": "task",
    "title": "Rückruf nächste Woche",
    "body": null,
    "occurredAt": "2026-09-05T09:00:00.000Z",
    "refs": {},
    "createdAt": "…"
  }
}
POST /api/v1/email/draft

Draft an email into your Outlook

email:draft

Composes 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 uuid

Resolve the recipient from a contact.

to string

Or an explicit recipient.

subject string · required
body string · required
curl -X POST https://heimster.ch/api/v1/email/draft \
  -H "Authorization: Bearer hm_…" \
  -H "Content-Type: application/json" \
  -d '{"subject":"…","body":"…"}'
Response Beispiel
{
  "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."
}
GET /api/v1/export

Export

export:read

Bulk export of your data.

curl https://heimster.ch/api/v1/export \
  -H "Authorization: Bearer hm_…"
Key oben einfügen zum Ausprobieren
Response Beispiel
{
  "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.

applicationIdlistingIdtenantProfileIdapplicantUserId
application.status_changed

Der Status einer Bewerbung hat sich geändert.

applicationIdlistingIdoldStatusnewStatusrejectionReason?
application.withdrawn

Eine Bewerbung wurde zurückgezogen.

applicationIdlistingIdoldStatusreason?
offer.sent

Eine Zusage/ein Angebot wurde an den Bewerber gesendet.

offerIdapplicationIdlistingIdtenantUserIdmonthlyRentexpiresAt
offer.accepted

Der Bewerber hat die Zusage angenommen.

offerIdapplicationIdlistingIdtenantUserId
offer.rejected

Der Bewerber hat die Zusage abgelehnt.

offerIdapplicationIdlistingIdtenantUserId
lease.signed

Der Mietvertrag wurde von beiden Seiten unterschrieben.

contractIdlistingIdtenantUserIdofferId?
viewing.booked

Ein Besichtigungstermin wurde gebucht.

slotIdlistingIdattendeeUserIdbookingId?applicationId?viaInvitation?
document.uploaded

Dokument(e) wurden zur Bewerbung geteilt.

applicationIdlistingIddocumentIdscountsharedByUserId
handover.completed

Ein Übergabeprotokoll wurde abgeschlossen.

protocolIdlistingIdobjectId?

Alle IDs sind Strings. ? = kann fehlen / null sein.

Header

X-Heimster-Event

Name des Ereignisses, z. B. offer.accepted.

X-Heimster-Signature

sha256=<HMAC> des rohen Bodies mit Ihrem Signing-Secret.

X-Heimster-Delivery

Eindeutige 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.

Payload · Beispiel (offer.accepted)
{
  "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.

Signatur prüfen (Node.js)
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);
  });