Für Agenturen und CRM-Anbieter
API & CRM-Integration
Eine einzige JSON-API, um Ihre Inserate aus Ihrem CRM (ImmoBridge, Immomig, Rexx, Flowfact …) zu steuern, Anfragen von Interessenten in Echtzeit zu erhalten und die Statistiken jeder Immobilie abzurufen. Die Immobilien folgen dem Standard SwissRETS JSON.
- Authentifizierung
- Immobilien
- Schaufenster (Website)
- Anfragen
- Statistiken
- Webhooks
- Fehler & Limiten
- OpenAPI (JSON)
1. Authentifizierung
Erstellen Sie unter Agenturbereich → Integrationen einen Schlüssel (Tab CRM). Er wird nur einmal angezeigt; wir speichern lediglich seinen SHA-256-Fingerabdruck. Ein Schlüssel gewährt ausschliesslich Zugriff auf die Daten der eigenen Agentur und kann jederzeit widerrufen werden.
curl https://myimmobilier.ch/api/v1/me \
-H "Authorization: Bearer mi_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"Berechtigungen eines Schlüssels: listings:read, listings:write, leads:read, leads:write, stats:read.
2. Immobilien senden und verwalten
Die Immobilie ist ein SwissRETS-Objekt property. Seine id ist die Kennung aus Ihrem CRM: Sie macht die Übermittlung idempotent (gleiche id = Aktualisierung, nie ein Duplikat). Fügen Sie den Header X-CRM: immobridge hinzu, um die Quelle zu kennzeichnen. Die Fotos (attachments.images[].url, https) werden heruntergeladen und bei uns gehostet (max. 30, je 8 MB).
| GET | /api/v1/listings | Liste (status, updatedSince, limit, cursor). |
| PUT | /api/v1/listings/{externalId} | Erstellt oder aktualisiert eine SwissRETS-Immobilie (upsert). |
| POST | /api/v1/listings | Dasselbe, die id stammt aus dem Body (property.id). |
| GET | /api/v1/listings/{ref} | Detail. {ref} = CRM-id, Referenz MY-xxxxx oder uuid. |
| POST | /api/v1/listings/{ref}/publish | Veröffentlicht (60 Tage). Die Agentur muss freigegeben sein. |
| POST | /api/v1/listings/{ref}/unpublish | Setzt auf Entwurf zurück. |
| POST | /api/v1/listings/{ref}/renew | Verlängert um 60 Tage. |
| DELETE | /api/v1/listings/{ref} | Archiviert (entfernt vom Portal, behält den Verlauf). |
| POST | /api/v1/imports | Massenimport: { crm, properties: [≤ 50] }, Ergebnis pro Immobilie (207 bei teilweisen Fehlern). |
availability.state steuert den Status: active/reserved → veröffentlicht, private → Entwurf, reference/taken → archiviert. Dank dieser Zuordnung können Sie einfach «aus dem CRM veröffentlichen», indem Sie die Immobilie erneut senden.
Zusätzliche Dokumente (Reglement, Dossier …): attachments.documents[] kann mehrere Einträge enthalten, die alle auf der Objektseite angezeigt werden – nicht nur eine einzelne Broschüre. 3D-Plan / immersive Besichtigung (Matterport, iGuide …): attachments.virtualTourLinks[], wie bei einer klassischen virtuellen Besichtigung.
Verborgene Adresse: Manche Agenturen veröffentlichen die genaue Adresse nicht (bewohnte Immobilie, diskreter Eigentümer …). Fügen Sie den Header X-Hide-Address: true bei PUT/POST /listings hinzu (oder {"hideAddress": true} im Body von /imports): Strasse, Hausnummer und genaue Koordinaten werden dann nie veröffentlicht – auf der Karte, in der Strassenansicht und auf der Katasterkarte erscheinen nur der Ort und ein ungefährer Umkreis (300 bis 450 m, dessen Mittelpunkt bewusst nicht die reale Adresse ist). Lassen Sie den Header weg, um diese Einstellung bei einer Aktualisierung unverändert zu lassen; senden Sie X-Hide-Address: false, um sie zu deaktivieren.
Angezeigte Blöcke: Standardmässig zeigt ein veröffentlichtes Inserat die Karte, die Strassenansicht, die Solarsimulation und die Katasterkarte, sobald die Daten es erlauben (Koordinaten, Immobilientyp). Um einige davon auszublenden, ohne die Adresse zu ändern, fügen Sie den Header X-Hide-Features mit einer kommagetrennten Liste aus map, streetview, solar, cadastre hinzu – zum Beispiel X-Hide-Features: streetview,solar. Wie bei der Adresse lässt das Weglassen des Headers die bestehende Einstellung unverändert; wird er mit einer leeren Liste gesendet (X-Hide-Features:), wird wieder alles angezeigt. Die Antwort liefert den aktuellen Zustand in hiddenFeatures (Array) und hiddenAddress (Boolean).
curl -X PUT https://myimmobilier.ch/api/v1/listings/CRM-4711 \
-H "Authorization: Bearer mi_live_…" -H "X-CRM: immobridge" \
-H "Content-Type: application/json" -d '{
"id": "CRM-4711", "referenceId": "R-4711", "type": "buy",
"categories": ["apartment"],
"availability": { "state": "active", "start": "2026-11-01" },
"address": { "countryCode": "CH", "locality": "Lausanne", "region": "VD", "postalCode": "1003", "street": "Rue du Lac", "streetNumber": "4" },
"characteristics": { "numberOfRooms": 3.5, "areaBwf": 82 },
"prices": { "currency": "CHF", "buy": { "price": 895000 } },
"localizations": [{ "languageCode": "fr", "title": "Appartement 3.5 pièces", "description": "…",
"attachments": { "images": [{ "url": "https://…/1.jpg" }], "documents": [{ "url": "https://…/brochure.pdf" }] } }]
}'3. Ihre Immobilien auf Ihrer Website anzeigen (Schaufenster)
Sie möchten die Darstellung nicht selbst programmieren? Ein schlüsselfertiges <iframe>-Widget, anpassbar (Farbe, Karte, Filter) und ohne API-Schlüssel, lässt sich unter Integrationen → Website erzeugen. Für eine individuell programmierte Website, die die Darstellung selbst übernimmt, verwenden Sie stattdessen diese Route: Sie liefert ausschliesslich veröffentlichte Immobilien im Anzeigeformat (Fotos, bei Bedarf bereits entschärfte Koordinaten, Medien, Badges) – im Gegensatz zu /listings oben, die auf die CRM-Synchronisierung ausgerichtet ist.
| GET | /api/v1/vitrine | Veröffentlichte Immobilien (Scope listings:read, bereits ausreichend – kein eigener Schlüssel). |
Dieselben Filter wie die Portalsuche: types (wiederholbar), prixMin, prixMax, piecesMin, surfaceMin, q (Freitext), sort (pertinence, prix_asc, prix_desc, surface_desc, recent), page. Seitenweise Antwort { data, total, totalPages, page }, 60 s zwischengespeichert (Cache-Control: public, max-age=60), im Gegensatz zu den übrigen /api/v1-Routen.
curl "https://myimmobilier.ch/api/v1/vitrine?types=appartement&prixMax=900000&sort=recent" \
-H "Authorization: Bearer mi_live_…"
{
"data": [{
"id": "…", "reference": "MY-01012", "slug": "lausanne-appartement-…",
"url": "https://myimmobilier.ch/bien/lausanne-appartement-…",
"type": "appartement", "offre": "vente", "titre": "Appartement 3.5 pièces",
"prix": 895000, "pieces": 3.5, "surface": 82, "npa": "1003", "ville": "Lausanne",
"latitude": 46.52, "longitude": 6.63,
"photoPrincipale": "https://…/1.jpg", "photos": ["https://…/1.jpg"],
"medias": { "visiteVirtuelle": null, "video": null, "plan": null, "brochure": null },
"badges": ["nouveau"], "agenceNom": "Mon Agence", "publishedAt": "2026-09-20T08:00:00Z"
}],
"total": 12, "totalPages": 1, "page": 1
}4. Anfragen empfangen
Kontakt-, Broschüren-, Besichtigungs- oder Rückrufanfrage: Jede Anfrage ist per lead.created-Webhook (sofort) und per Polling über GET /api/v1/leads?since=…&unprocessed=1 verfügbar. Bestätigen Sie den Empfang mit PATCH /api/v1/leads/{id} {"acknowledged": true, "status": "traitee"}, damit sie nicht erneut verarbeitet wird.
{
"id": "evt_…", "type": "lead.created", "created": "2026-09-26T10:12:00Z",
"data": {
"id": "…", "type": "brochure", "status": "nouvelle",
"contact": { "firstName": "Anna", "lastName": "Muller", "email": "anna@…", "phone": "+41 79 …" },
"message": "…",
"source": "site", "stage": "nouveau",
"budget": { "amount": 850000, "currency": "CHF", "verified": false },
"visit": { "startsAt": "2026-10-12T14:00:00Z", "endsAt": "2026-10-12T14:30:00Z" },
"broker": { "id": "…", "name": "Marie Dupont", "email": "marie@…", "title": "Courtière" },
"listing": { "id": "…", "reference": "MY-01012", "externalId": "CRM-4711", "title": "…", "city": "Lausanne", "price": 895000, "offer": "vente", "type": "appartement", "url": "https://myimmobilier.ch/bien/…" }
}
}source: site (Formular von myimmobilier.ch) oder widget (Formular des in Ihre Website eingebetteten iframe). budget ist das vom Interessenten angegebene geschätzte Budget: von ihm selbst berechnet, nie von einer Bank überprüft. visit existiert nur bei einer Besichtigungsbuchung; broker ist der für die Immobilie zuständige Makler, falls vorhanden. stage: nouveau, contacte, visite, offre, conclu, perdu.
Die listing.*-Ereignisse enthalten die Immobilie so, wie sie von GET /listings/{ref} zurückgegeben wird: status (brouillon, publie, expire, archive), exclusive, featured («Auswahl»), boostedUntil (bezahlte Hervorhebung), contactDisplay (agence, courtier, les_deux), broker, outcome ({ "type": "vendu" | "loue", "at": … }) sowie Preis, Flächen, Adresse (auf Wunsch verborgen), Veröffentlichungs- und Ablaufdatum.
5. Statistiken
Anonyme Zähler, aggregiert pro Tag und pro Immobilie: views, contacts, phoneReveals, brochureDownloads, virtualTours, videoPlays, favorites, shares. Keine personenbezogenen Daten der Besucher.
| GET | /api/v1/stats?from=&to= | Die ganze Agentur: Summen, pro Immobilie, pro Tag (standardmässig 30 Tage). |
| GET | /api/v1/listings/{ref}/stats | Eine Immobilie. |
6. Webhooks
Ereignisse: lead.created, lead.updated (von der Agentur geänderte Phase), listing.published (Veröffentlichung oder Verlängerung), listing.updated, listing.expired (Ablaufdatum erreicht, täglich geprüft), listing.archived (archiviert oder auf Entwurf zurückgesetzt), listing.concluded (verkauft / vermietet), listing.featured (bezahlte Hervorhebung angewendet), webhook.test. Aktionen aus dem Agenturbereich von MyImmobilier.ch werden wie jene über die API gesendet (mit einigen Sekunden Verzögerung); Aktionen, die Ihr CRM selbst über die API auslöst, werden nicht als Echo an es zurückgesendet, ausser listing.published/listing.updated. Nur HTTPS-URLs. Antwortzeit: 5 s; andernfalls erfolgt ein neuer Versuch nach 1 Min., 5 Min., 30 Min., 2 Std. und schliesslich 12 Std. (manuelle Wiederholung im Agenturbereich möglich). Entdoppeln Sie anhand des Headers X-MyImmobilier-Delivery / id.
Überprüfen Sie die Signatur: X-MyImmobilier-Signature: t=<timestamp>,v1=<hex>, wobei v1 = HMAC_SHA256(secret, t + "." + corps_brut). Lehnen Sie die Anfrage ab, wenn t älter als 5 Minuten ist.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifier(secret, enteteSignature, corpsBrut) {
const { t, v1 } = Object.fromEntries(enteteSignature.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
const attendu = createHmac("sha256", secret).update(t + "." + corpsBrut).digest("hex");
return attendu.length === v1.length && timingSafeEqual(Buffer.from(attendu), Buffer.from(v1));
}7. Fehler und Limiten
{ "error": { "code": "validation_failed", "message": "…", "details": [{ "chemin": "/characteristics/areaBwf", "message": "must be number" }] } }Codes: 400 invalid_request, 401 unauthorized, 403 forbidden / agency_not_approved, 404 not_found, 409 invalid_state, 413 payload_too_large, 422 validation_failed. Body max. 2 MB (8 MB für Importe). Eine veröffentlichte Immobilie läuft nach 60 Tagen ab: Rufen Sie renew auf oder empfangen Sie listing.expired, um sie automatisch zu verlängern.
CRM-Anbieter? Schreiben Sie uns für eine Unterstützung bei der Integration: Kontakt.