Migration v1 → v2
Guide de migration de l'API Stream Estate v1 vers v2
Changements incompatibles entre la v1 (docs.stream.estate) et la v2 (https://api-v2.stream.estate).
Cette migration change la plupart des URLs, le format de recherche (querystring → body structuré autour d'un arbre criteria), renomme Search en Alert, et introduit un vrai système de destinations (EventDestination). Prévoyez une refonte du client.
TL;DR
- Base URL —
api-v2.stream.estate - Auth — même en-tête
X-API-KEY, mais nouvelle clé à générer (les clés v1 ne fonctionnent pas en v2) - Recherche —
GET /documents/properties?...→POST /propertiesavec body JSON construit autour d'un arbrecriteriarécursif (Filters/and/or), paginationPAGEouCURSOR - Renommage —
Search→Alert(+AlertEventsdédiés) - Webhooks — système complet via
EventDestination+signingKey+EventNotification(journal de livraison) - Indicateurs —
/citiesremplacé par/geo/administrative-divisions/{uuid}(lookup par UUID uniquement, pas de collection) ; de nouveaux endpoints d'estimation (prix au m², POI, comparables) arrivent pour remplacer les anciens/indicators/*
Table de correspondance des endpoints
Propriétés
| v1 | v2 | Commentaire |
|---|---|---|
GET /documents/properties (70+ params querystring) | POST /properties (body JSON, arbre criteria) | Voir Filtrage |
GET /documents/properties/{id} | GET /properties/{uuid} | Path simplifié |
GET /documents/properties/{id}/similar-properties | 🆕 Nouveaux endpoints d'estimation à venir |
Searches → Alerts
| v1 | v2 | Commentaire |
|---|---|---|
GET /searches | GET /alerts | |
GET /searches/{id} | GET /alerts/{uuid} | |
POST /searches | POST /alerts | Body remanié autour de criteria + notificationDestination |
PUT /searches/{id} | PUT /alerts/{uuid} | |
DELETE /searches/{id} | DELETE /alerts/{uuid} | |
| (N/A) | GET /alerts/{alertUuid}/events | Historique des matches |
| (N/A) | GET /alerts/{alertUuid}/events/{uuid} | Détail d'un event |
Webhooks & notifications
| v1 | v2 | Commentaire |
|---|---|---|
| URL webhook dans le Search | EventDestination (GET/POST collection, GET/DELETE par UUID) + signingKey HMAC | Destinations réutilisables entre alertes (pas de mise à jour — recréez la destination si besoin) |
GET /webhook-tester | → intégré à EventDestination + EventNotification | Plus besoin d'endpoint dédié |
Événements ad.update.*, property.ad.* | Nouveaux types: NEW_MATCH, ADDITIONAL_LISTING, PRICE_CHANGED, ANY_ATTRIBUTE_CHANGED, LISTING_EXPIRED, LISTING_REACTIVATED | Voir Alert |
| (N/A) | GET /event-notifications | Journal complet des tentatives de livraison |
| (N/A) | POST /account/webhook-signing-key/rotate | Renouvellement de la clé de signature |
| (N/A) | POST /account/event-destinations/{uuid}/reactivate | Reprise après circuit breaker |
Cities / Géo
| v1 | v2 | Commentaire |
|---|---|---|
GET /cities | GET /geo/administrative-divisions/{uuid} (lookup par UUID) | Pas de collection pour l'instant |
GET /public/location-autocomplete | GET /geo/autocomplete |
Indicateurs & divers
| v1 | v2 | Commentaire |
|---|---|---|
GET /indicators/points_of_interest | 🆕 Nouveaux endpoints d'estimation à venir | |
GET /indicators/price_per_meter | 🆕 Nouveaux endpoints d'estimation à venir |
Nouveautés v2
| Endpoint | Description |
|---|---|
GET /account/api-usage | Agrégats d'usage facturable (totals, byApiKey, byRoute) sur une fenêtre startDate/endDate |
GET /analytics/listings | Statistiques agrégées sur les listings |
GET /favorite-properties, POST /favorite-properties, DELETE /favorite-properties/{uuid} | Favoris (liste et création sur la collection, suppression par UUID uniquement) |
GET /event-notifications[/{uuid}] | Journal de livraison des notifications |
Changements de modèle
Property
En v1, PropertyDocument contient adverts[] intégré directement avec tous les détails. En v2, POST /properties renvoie un PropertySearchResultDTO structuré : une vue canonique sous property, les publishers dédoublonnés et les variantes par listing :
{
"id": "019dedb1-fdf4-714c-8392-5b9cfd63cde3",
"property": {
"createdAt": "2025-01-15T10:30:00+00:00",
"updatedAt": "2025-06-15T12:00:00+00:00",
"propertyType": "FLAT",
"transaction": { "type": "SELL" /* + status, saleType, availableAt */ },
"area": { /* displayed, indoor, outdoor, land */ },
"unit": { /* rooms, bedrooms, floor, condition */ },
"building": { /* constructionYear, floors, condition */ }
},
"publishers": [/* PublisherSectionDTO[] dédoublonnés */],
"listings": [/* ListingSectionDTO[] : url, source, publishedAt, lastSeenAt et toutes les variantes qui diffèrent du canonique */]
}Les détails canoniques (surface, type, rooms, transaction, etc.) se trouvent dans property. listings[] ne contient que les variantes spécifiques à chaque annonce (titre, URL, dates de publication et tout champ qui s'écarte du canonique).
Alert (ex-Search)
Body remanié — un arbre criteria unique (plus de discriminant searchMode) et une destination déclarative via notificationDestination :
{
"name": "Appartements 3+ pièces à Paris",
"active": true,
"criteria": {
"property": {
"type": { "in": ["FLAT"] },
"transaction": { "type": "SELL" },
"unit": { "rooms": { "gte": 3 } },
"locations": { "countryCode": "FR", "in": { "uniqueCodes": ["75056"] } }
}
},
"notificationConfig": {
"rules": [
{ "eventType": "NEW_MATCH", "enabled": true },
{ "eventType": "PRICE_CHANGED", "thresholdPercentage": 5, "thresholdDirection": "DECREASE", "enabled": true }
]
},
"notificationDestination": {
"webhookUrl": "https://your.app/hook"
}
}La réponse POST /alerts renvoie un signingKey HMAC une seule fois (préfixé whsec_) — conservez-le.
Format de réponse
| v1 | v2 |
|---|---|
| Collection classique | JSON (application/json) ou JSON:API (application/vnd.api+json) via Accept |
Pagination query ?page=N | POST /properties avec paginationType: "PAGE" ou "CURSOR" (voir Pagination) |
Checklist de migration
- 🔑 Générer une nouvelle clé API v2 sur console.stream.estate/api-keys (les clés v1 sont incompatibles) et l'envoyer dans
X-API-KEY - 🔄 Remplacer
GET /documents/properties?...parPOST /propertiesavec body JSON construit autour d'un arbrecriteria(Filters/and/or) - 🔄 Adapter la pagination (choisir
PAGEouCURSORviapaginationType) - 🔄 Renommer
Search*→Alert*dans le code client - 🔄 Créer des
EventDestinationexplicites (POST /account/event-destinations, puisGET/DELETEpar UUID — pas de mise à jour, recréez la destination si besoin) plutôt que d'associer l'URL webhook à chaque Search, ou utilisernotificationDestination.webhookUrlà la création de l'Alert - 🔐 Stocker
signingKeyrenvoyé parPOST(alert ou event-destination) et vérifier la signature HMAC côté réception - 🔄 Migrer les consommateurs de
PropertyDocument.adverts[]versPropertySearchResult.listings[](au premier niveau de la réponse, à côté depropertyetpublishers) - 🔄 Remplacer les noms d'événements v1 par les enums v2 (
NEW_MATCH,ADDITIONAL_LISTING,PRICE_CHANGED,ANY_ATTRIBUTE_CHANGED,LISTING_EXPIRED,LISTING_REACTIVATED) - ⚠️ Retirer temporairement les appels à
/indicators/*— une nouvelle suite d'endpoints dédiée à l'estimation arrive - ✨ Optionnellement intégrer
/event-notifications(journal de livraison) et/analytics/listings