{"openapi":"3.0.3","info":{"title":"Chalet-Montagne.com \u2014 API publique (public-front)","description":"Surface publique consomm\u00e9e par le site www.chalet-montagne.com et, \u00e0 terme, par la passerelle MCP mcp.chalet-montagne.com. Recherche de locations de vacances \u00e0 la montagne (France), d\u00e9tail des fiches, disponibilit\u00e9s\/prix et demande de contact au propri\u00e9taire (mise en relation directe, sans commission). Les IDs de filtres (options, domaines skiables, types d\u0027h\u00e9bergement) ne sont PAS des constantes stables : les d\u00e9couvrir via GET \/api\/public-front\/search\/filters ou \/api\/public-front\/destinations. Rate limit : 120 GET\/min par IP (r\u00e9ponse 429 + Retry-After).","version":"1.0.0","contact":{"email":"equipe@alpium.com"}},"servers":[{"url":"https:\/\/mcp.chalet-montagne.com","description":"Passerelle publique"}],"paths":{"\/api\/public-front\/search":{"get":{"operationId":"searchRentals","summary":"Recherche de locations (pagination, filtres, dates, tri)","description":"Endpoint unique de recherche. R\u00e8gle m\u00e9tier prix : SANS dates, le prix affich\u00e9 est un tarif SEMAINE (7 nuits) ; AVEC dates, le prix est le total du s\u00e9jour demand\u00e9 (le nombre de nuits d\u00e9termine semaine vs court s\u00e9jour). Dates au format ISO YYYY-MM-DD. Les param\u00e8tres tableau utilisent la syntaxe param[]=v1\u0026param[]=v2.","parameters":[{"name":"stationSlug","in":"query","schema":{"type":"string"},"description":"Slug de station (voir \/destinations)"},{"name":"massif","in":"query","schema":{"type":"string"},"description":"Slug de massif"},{"name":"department","in":"query","schema":{"type":"string"},"description":"Nom\/slug de d\u00e9partement"},{"name":"skiDomainSlug","in":"query","schema":{"type":"string"},"description":"Slug de domaine skiable"},{"name":"secteur","in":"query","schema":{"type":"string"},"description":"Slug de secteur d\u0027une station"},{"name":"dateStart","in":"query","schema":{"type":"string","format":"date"},"description":"Arriv\u00e9e (YYYY-MM-DD)"},{"name":"dateEnd","in":"query","schema":{"type":"string","format":"date"},"description":"D\u00e9part (YYYY-MM-DD)"},{"name":"flexDays","in":"query","schema":{"type":"integer","minimum":0,"maximum":7},"description":"Souplesse \u00b1 jours autour des dates"},{"name":"moisRecherche","in":"query","schema":{"type":"string"},"description":"Recherche par mois entier (YYYY-MM), alternative aux dates pr\u00e9cises"},{"name":"adults","in":"query","schema":{"type":"integer","minimum":1,"default":1},"description":"Nombre d\u0027adultes (enfants compt\u00e9s comme adultes en couchage)"},{"name":"babies","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Nombre de b\u00e9b\u00e9s"},{"name":"animals","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Nombre d\u0027animaux"},{"name":"nbPlacesMin","in":"query","schema":{"type":"integer"},"description":"Capacit\u00e9 minimale (couchages)"},{"name":"nbPlacesMax","in":"query","schema":{"type":"integer"}},{"name":"nbRoomsMin","in":"query","schema":{"type":"integer"},"description":"Nombre de chambres minimum"},{"name":"nbRoomsMax","in":"query","schema":{"type":"integer"}},{"name":"surfaceMin","in":"query","schema":{"type":"integer"},"description":"Surface minimale (m\u00b2)"},{"name":"surfaceMax","in":"query","schema":{"type":"integer"}},{"name":"priceMin","in":"query","schema":{"type":"integer"},"description":"Fourchette de prix (\u20ac) \u2014 s\u0027applique au prix affich\u00e9 : semaine sans dates, total du s\u00e9jour avec dates"},{"name":"priceMax","in":"query","schema":{"type":"integer"}},{"name":"hostingTypeIds[]","in":"query","schema":{"type":"array","items":{"type":"integer"}},"style":"form","explode":true,"description":"IDs de types d\u0027h\u00e9bergement (chalet, appartement\u2026) \u2014 IDs dynamiques via \/search\/filters"},{"name":"optionIds[]","in":"query","schema":{"type":"array","items":{"type":"integer"}},"style":"form","explode":true,"description":"IDs d\u0027\u00e9quipements\/options \u2014 IDs dynamiques via \/search\/filters"},{"name":"annonceTypes[]","in":"query","schema":{"type":"array","items":{"type":"string","enum":["par","pro","cv","cs","lc","new","hist","saisonhiver","saisonete","di"]}},"style":"form","explode":true,"description":"Types d\u0027annonce : par=particulier, pro=professionnel, cs=court s\u00e9jour, lc=location-chalet, new=nouveaut\u00e9\u2026 Un s\u00e9jour dat\u00e9 \u003C 7 nuits force automatiquement \u0027cs\u0027."},{"name":"classificationLevels[]","in":"query","schema":{"type":"array","items":{"type":"integer","minimum":0,"maximum":5}},"style":"form","explode":true,"description":"Niveaux d\u0027\u00e9toiles (0 = non class\u00e9)"},{"name":"lastMinuteOnly","in":"query","schema":{"type":"boolean"},"description":"Uniquement les offres derni\u00e8re minute"},{"name":"includeLastMinute","in":"query","schema":{"type":"boolean"},"description":"Ajoute un bandeau derni\u00e8res minutes \u00e0 la r\u00e9ponse (recherche unifi\u00e9e)"},{"name":"maxDistanceStation","in":"query","schema":{"type":"integer"},"description":"Distance max au centre station (m\u00e8tres)"},{"name":"maxDistanceLift","in":"query","schema":{"type":"integer"},"description":"Distance max aux pistes\/remont\u00e9es (m\u00e8tres)"},{"name":"sortBy","in":"query","schema":{"type":"string","enum":["points","price","surface","capacity","rooms","classification","distance-station","distance-piste","planning-a-jour"],"default":"points"}},{"name":"sortDirection","in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"maximum":1000,"default":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":30}},{"name":"locale","in":"query","schema":{"type":"string","enum":["fr","en","de","es","it","nl"],"default":"fr"}}],"responses":{"200":{"description":"R\u00e9sultats pagin\u00e9s (Cache-Control public 60 s). Chaque hosting expose id, name, station, capacit\u00e9, surface, prix affich\u00e9, photos, badges.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/SearchResponse"}}}},"429":{"$ref":"#\/components\/responses\/TooManyRequests"}}}},"\/api\/public-front\/search\/filters":{"get":{"operationId":"getSearchFilters","summary":"R\u00e9f\u00e9rentiel des filtres dynamiques (bootstrap)","description":"Retourne les IDs valides du moment : types d\u0027h\u00e9bergement, options\/\u00e9quipements, conditions d\u0027annulation, niveaux de classement. \u00c0 appeler avant d\u0027utiliser hostingTypeIds\/optionIds \u2014 ces IDs ne sont pas des constantes stables.","parameters":[{"name":"locale","in":"query","schema":{"type":"string","enum":["fr","en","de","es","it","nl"],"default":"fr"}}],"responses":{"200":{"description":"Filtres disponibles avec IDs et libell\u00e9s localis\u00e9s","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Envelope"}}}},"429":{"$ref":"#\/components\/responses\/TooManyRequests"}}}},"\/api\/public-front\/destinations":{"get":{"operationId":"getDestinations","summary":"R\u00e9f\u00e9rentiel des destinations (stations, massifs, d\u00e9partements)","description":"Destinations avec leurs slugs \u2014 \u00e0 utiliser pour r\u00e9soudre une destination en texte libre vers stationSlug\/massif\/department.","responses":{"200":{"description":"Arbre des destinations","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Envelope"}}}},"429":{"$ref":"#\/components\/responses\/TooManyRequests"}}}},"\/api\/public-front\/hostings\/{hostingId}\/home":{"get":{"operationId":"getRentalDetails","summary":"D\u00e9tail complet d\u0027une fiche de location","description":"Description, capacit\u00e9, surface, chambres, \u00e9quipements, tarifs, avis, station. Les coordonn\u00e9es directes du propri\u00e9taire ne sont JAMAIS incluses (mise en relation via POST \/contact-owner). Page publique correspondante : https:\/\/www.chalet-montagne.com\/locations-vacances-montagne\/{hostingId}-{slug}","parameters":[{"name":"hostingId","in":"path","required":true,"schema":{"type":"integer"}},{"name":"locale","in":"query","schema":{"type":"string","enum":["fr","en","de","es","it","nl"],"default":"fr"}}],"responses":{"200":{"description":"Fiche compl\u00e8te","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Envelope"}}}},"404":{"description":"Lot inconnu ou inactif"},"429":{"$ref":"#\/components\/responses\/TooManyRequests"}}}},"\/api\/public-front\/hostings\/{hostingId}\/availability":{"get":{"operationId":"getAvailabilityCalendar","summary":"Calendrier de disponibilit\u00e9s d\u0027un lot (par mois)","parameters":[{"name":"hostingId","in":"path","required":true,"schema":{"type":"integer"}},{"name":"from","in":"query","schema":{"type":"string"},"description":"Mois de d\u00e9part (YYYY-MM) \u2014 d\u00e9faut : mois courant"},{"name":"count","in":"query","schema":{"type":"integer","minimum":1,"maximum":24,"default":4},"description":"Nombre de mois \u00e0 retourner"}],"responses":{"200":{"description":"Statut jour par jour (libre\/occup\u00e9\/arriv\u00e9e\/d\u00e9part)","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Envelope"}}}},"404":{"description":"Lot inconnu"},"429":{"$ref":"#\/components\/responses\/TooManyRequests"}}}},"\/api\/public-front\/calculate-price":{"get":{"operationId":"calculateStayPrice","summary":"Prix d\u0027un s\u00e9jour dat\u00e9 pour un lot","description":"Calcule le prix total du s\u00e9jour \u00e0 partir des p\u00e9riodes tarifaires r\u00e9elles (semaine, court s\u00e9jour, nuits suppl\u00e9mentaires). V\u00e9rifier la disponibilit\u00e9 s\u00e9par\u00e9ment via \/availability ou \/planning-coverage.","parameters":[{"name":"hostingId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"checkin","in":"query","required":true,"schema":{"type":"string","format":"date"},"description":"Arriv\u00e9e (YYYY-MM-DD)"},{"name":"checkout","in":"query","required":true,"schema":{"type":"string","format":"date"},"description":"D\u00e9part (YYYY-MM-DD)"},{"name":"pricingScheduleId","in":"query","schema":{"type":"integer"},"description":"Optionnel : forcer une grille tarifaire pr\u00e9cise"}],"responses":{"200":{"description":"Prix calcul\u00e9, ou motif d\u0027impossibilit\u00e9 dans l\u0027enveloppe","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Envelope"}}}},"429":{"$ref":"#\/components\/responses\/TooManyRequests"}}}},"\/api\/public-front\/planning-coverage":{"get":{"operationId":"checkPlanningCoverage","summary":"Le planning du lot couvre-t-il une plage de dates ?","parameters":[{"name":"hostingId","in":"query","required":true,"schema":{"type":"integer"}},{"name":"checkin","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"checkout","in":"query","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Couverture et disponibilit\u00e9 de la plage","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Envelope"}}}},"429":{"$ref":"#\/components\/responses\/TooManyRequests"}}}},"\/api\/public-front\/contact-owner":{"post":{"operationId":"sendRentalInquiry","summary":"Demande de contact au propri\u00e9taire (la conversion)","description":"Transmet la demande du vacancier au propri\u00e9taire du lot. Anti-spam, v\u00e9rification de disponibilit\u00e9, contr\u00f4les de conformit\u00e9 (capacit\u00e9, animaux, tarifs) et d\u00e9duplication appliqu\u00e9s c\u00f4t\u00e9 serveur. Ne JAMAIS envoyer sans l\u0027accord explicite de l\u0027utilisateur final. Accepte JSON ou form-data. Le champ MailVerification est un pot de miel anti-spam : le laisser vide.","requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["locationId","nom","prenom","email","arrivee","depart","adulte"],"properties":{"locationId":{"type":"integer","description":"ID du lot (hosting)"},"nom":{"type":"string"},"prenom":{"type":"string"},"email":{"type":"string","format":"email"},"tel":{"type":"string"},"arrivee":{"type":"string","format":"date","description":"Arriv\u00e9e (YYYY-MM-DD)"},"depart":{"type":"string","format":"date","description":"D\u00e9part (YYYY-MM-DD)"},"adulte":{"type":"integer","minimum":1},"enfant":{"type":"integer","default":0},"bebe":{"type":"integer","default":0},"animaux":{"type":"integer","default":0},"commentaire":{"type":"string","description":"Message libre au propri\u00e9taire"},"MailVerification":{"type":"string","description":"Pot de miel anti-spam \u2014 laisser vide"}}}}}},"responses":{"200":{"description":"Demande transmise : {status: \u0027success\u0027, message, tenant_exists}","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/ContactOwnerResponse"}}}},"400":{"description":"Validation \u00e9chou\u00e9e : {status: \u0027echec\u0027, message}"},"404":{"description":"Refus m\u00e9tier (indisponibilit\u00e9, capacit\u00e9 d\u00e9pass\u00e9e\u2026) : {status: \u0027echec\u0027, message}"}}}}},"components":{"schemas":{"Envelope":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"description":"Charge utile (forme selon l\u0027endpoint)"},"error":{"type":"string"}}},"SearchResponse":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"hostings":{"type":"array","items":{"type":"object"}},"total":{"type":"integer"},"page":{"type":"integer"},"limit":{"type":"integer"},"totalPages":{"type":"integer"}}}}},"ContactOwnerResponse":{"type":"object","properties":{"status":{"type":"string","enum":["success","echec"]},"message":{"type":"string"},"tenant_exists":{"type":"boolean","description":"true si un compte locataire existe d\u00e9j\u00e0 pour cet email"}}}},"responses":{"TooManyRequests":{"description":"Rate limit d\u00e9pass\u00e9 (120 GET\/min par IP) \u2014 respecter l\u0027en-t\u00eate Retry-After","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Secondes \u00e0 attendre"}}}}}}