{"openapi":"3.1.0","info":{"title":"Previzio API","description":"API météo privée : prévisions horaires et par tranche de journée (nuit/matin/après-midi/soir) pour les communes de France métropolitaine, vigilance météo et restrictions d'eau par département, qualité de l'air et pollens par commune. Usage réservé aux sites clients munis d'une clé API.","version":"0.1.0"},"paths":{"/health":{"get":{"tags":["Monitoring"],"summary":"Statut d'ingestion","description":"Dernier run et dernière ingestion réussie par modèle source (AROME, ARPEGE). Public, sans authentification — destiné au monitoring externe (UptimeRobot, Better Stack, ...).","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/forecast":{"get":{"tags":["Prévisions"],"summary":"Prévisions météo par commune","description":"Renvoie les conditions actuelles, les prévisions horaires et les prévisions par jour (min/max, lever/coucher, tranches nuit/matin/après-midi/soir) pour une ou plusieurs communes. Fournir exactement un des deux paramètres `codes_insee` ou `postal_code`.","operationId":"forecast_v1_forecast_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"codes_insee","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Un ou plusieurs codes INSEE séparés par des virgules.","examples":["75056,69123"],"title":"Codes Insee"},"description":"Un ou plusieurs codes INSEE séparés par des virgules."},{"name":"postal_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Un code postal (peut correspondre à plusieurs communes).","examples":["75001"],"title":"Postal Code"},"description":"Un code postal (peut correspondre à plusieurs communes)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LocationForecast"},"title":"Response Forecast V1 Forecast Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/vigilance":{"get":{"tags":["Vigilance"],"summary":"Vigilance météo par département","description":"Renvoie les niveaux de vigilance Météo-France (vent, pluie-inondation, orages, inondation, neige-verglas, canicule, grand froid, avalanches, vagues-submersion) pour un ou plusieurs domaines, pour les échéances J (aujourd'hui) et J1 (demain). Sans paramètre, renvoie tous les domaines.","operationId":"vigilance_v1_vigilance_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"departements","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Un ou plusieurs codes de domaine séparés par des virgules : département ('2A'/'2B' pour la Corse) ou zone littorale (ex. '8310') pour vagues_submersion. Omis : tous les domaines.","examples":["75,69"],"title":"Departements"},"description":"Un ou plusieurs codes de domaine séparés par des virgules : département ('2A'/'2B' pour la Corse) ou zone littorale (ex. '8310') pour vagues_submersion. Omis : tous les domaines."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DomainVigilance"},"title":"Response Vigilance V1 Vigilance Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/air-quality":{"get":{"tags":["Qualité de l'air"],"summary":"Qualité de l'air et pollens par commune","description":"Renvoie l'indice ATMO de qualité de l'air (global et par polluant) et l'indice pollinique (global et par taxon) pour une ou plusieurs communes, pour J et J+1 (source Atmo France). Les communes non couvertes par leur AASQA ont une liste `air` vide.","operationId":"air_quality_v1_air_quality_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"codes_insee","in":"query","required":true,"schema":{"type":"string","description":"Un ou plusieurs codes INSEE séparés par des virgules.","examples":["75056,69123"],"title":"Codes Insee"},"description":"Un ou plusieurs codes INSEE séparés par des virgules."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AirQuality"},"title":"Response Air Quality V1 Air Quality Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/water-restrictions":{"get":{"tags":["Restrictions d'eau"],"summary":"Restrictions d'eau / sécheresse par département","description":"Renvoie le niveau de gravité des restrictions d'eau en vigueur (source VigiEau) pour un ou plusieurs départements : vigilance, alerte, alerte_renforcee, crise — un niveau global et un niveau par type d'eau (superficielle, souterraine, potable). Sans paramètre, renvoie tous les départements.","operationId":"water_restrictions_v1_water_restrictions_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"departements","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Un ou plusieurs codes département séparés par des virgules. Omis : tous les départements.","examples":["75,69"],"title":"Departements"},"description":"Un ou plusieurs codes département séparés par des virgules. Omis : tous les départements."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WaterRestriction"},"title":"Response Water Restrictions V1 Water Restrictions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AirQuality":{"properties":{"code_insee":{"type":"string","title":"Code Insee","description":"Code INSEE de la commune.","examples":["75056"]},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At","description":"Horodatage UTC de la dernière mise à jour (ISO 8601).","examples":["2026-10-08T15:39:18Z"]},"air":{"items":{"$ref":"#/components/schemas/AirQualityDay"},"type":"array","title":"Air","description":"Indice de qualité de l'air pour J et J+1. Vide si ni la commune ni son EPCI ne sont couverts."},"pollen":{"items":{"$ref":"#/components/schemas/PollenDay"},"type":"array","title":"Pollen","description":"Indice pollinique pour J et J+1. Vide si la commune n'est pas couverte."}},"type":"object","required":["code_insee","air","pollen"],"title":"AirQuality"},"AirQualityDay":{"properties":{"date":{"type":"string","title":"Date","description":"Jour concerné (YYYY-MM-DD, heure locale).","examples":["2026-10-08"]},"indice":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Indice","description":"Indice ATMO global : 1 bon, 2 moyen, 3 dégradé, 4 mauvais, 5 très mauvais, 6 extrêmement mauvais.","examples":[2]},"libelle":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Libelle","description":"Libellé de l'indice.","examples":["Moyen"]},"polluants":{"additionalProperties":{"anyOf":[{"type":"integer"},{"type":"null"}]},"type":"object","title":"Polluants","description":"Sous-indice (même échelle) par polluant : no2, o3, pm10, pm25, so2.","examples":[{"no2":2,"o3":2,"pm10":1,"pm25":1,"so2":1}]},"zone":{"type":"string","enum":["commune","epci"],"title":"Zone","description":"'commune' : valeur propre à la commune ; 'epci' : valeur de l'intercommunalité de la commune (repli, moins précis).","default":"commune"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","description":"Association agréée de surveillance de la qualité de l'air (AASQA) source.","examples":["Airparif"]}},"type":"object","required":["date","polluants"],"title":"AirQualityDay"},"DailyForecast":{"properties":{"date":{"type":"string","title":"Date","description":"Date locale (fuseau de la commune), ISO 8601.","examples":["2026-10-06"]},"temperature_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature Min","description":"Température minimale du jour, en °C (sur les heures prévues ce jour-là : partielle pour le jour en cours).","examples":[9.1]},"temperature_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature Max","description":"Température maximale du jour, en °C (sur les heures prévues ce jour-là : partielle pour le jour en cours).","examples":[16.4]},"apparent_temperature_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Apparent Temperature Min","description":"Température ressentie minimale du jour, en °C (mêmes heures que `temperature_min`).","examples":[7.4]},"apparent_temperature_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Apparent Temperature Max","description":"Température ressentie maximale du jour, en °C (mêmes heures que `temperature_max`).","examples":[16.4]},"sunrise":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sunrise","description":"Lever du soleil, horodatage UTC (ISO 8601).","examples":["2026-10-06T05:57:00Z"]},"sunset":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sunset","description":"Coucher du soleil, horodatage UTC (ISO 8601).","examples":["2026-10-06T17:20:00Z"]},"tranches":{"items":{"$ref":"#/components/schemas/TranchePeriode"},"type":"array","title":"Tranches","description":"Prévisions du jour agrégées par tranche (nuit/matin/après-midi/soir), chronologiques."}},"type":"object","required":["date","tranches"],"title":"DailyForecast"},"DomainVigilance":{"properties":{"domain_id":{"type":"string","title":"Domain Id","description":"Code du domaine de vigilance : département (ex. '75', '2A'/'2B' pour la Corse) ou zone littorale (ex. '8310') pour le phénomène vagues-submersion.","examples":["75"]},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At","description":"Horodatage UTC de la dernière mise à jour de la vigilance (ISO 8601).","examples":["2026-10-07T08:03:00Z"]},"vigilance":{"items":{"$ref":"#/components/schemas/VigilancePhenomene"},"type":"array","title":"Vigilance","description":"Niveaux de vigilance par phénomène et échéance."}},"type":"object","required":["domain_id","vigilance"],"title":"DomainVigilance"},"ForecastPoint":{"properties":{"timestamp":{"type":"string","title":"Timestamp","description":"Horodatage UTC du point de prévision (ISO 8601).","examples":["2026-10-06T15:00:00Z"]},"is_day":{"type":"boolean","title":"Is Day","description":"Vrai si le soleil est levé à cet instant (entre lever et coucher du jour local de la commune)."},"temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature","description":"Température à 2m, en °C.","examples":[14.2]},"apparent_temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Apparent Temperature","description":"Température ressentie, en °C : refroidissement éolien si T ≤ 10 °C (et vent > 4,8 km/h), indice de chaleur si T ≥ 27 °C, sinon la température.","examples":[11.3]},"precipitation":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Precipitation","description":"Cumul de précipitations sur l'heure, en mm.","examples":[0.0]},"wind_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Wind Speed","description":"Vitesse du vent à 10m, en km/h.","examples":[18.5]},"wind_direction":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Wind Direction","description":"Direction du vent, en degrés (0-360, 0 = nord).","examples":[270]},"wind_gust":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Wind Gust","description":"Rafales de vent à 10m, en km/h.","examples":[42.0]},"cloud_cover":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cloud Cover","description":"Couverture nuageuse, en %.","examples":[40.0]},"humidity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Humidity","description":"Humidité relative, en %.","examples":[72.0]},"pressure":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pressure","description":"Pression réduite au niveau de la mer, en hPa.","examples":[1015.3]},"visibility":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Visibility","description":"Visibilité minimale sur l'heure, en mètres (plafonnée à 20 000). Null au-delà de ~+48h (non fournie par ARPEGE).","examples":[20000]},"weather_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weather Code","description":"Code météo WMO (seuils adaptés d'Open-Meteo, cf. _docs/weather-api-architecture.md).","examples":[61]},"weather_icons":{"anyOf":[{"$ref":"#/components/schemas/WeatherIcons"},{"type":"null"}],"description":"Nom d'icône par jeu d'icônes, dérivé de weather_code et de l'heure locale (jour/nuit) de la commune.","examples":[{"meteocons":"rain","metno":"lightrain"}]}},"type":"object","required":["timestamp","is_day"],"title":"ForecastPoint"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthResponse":{"properties":{"status":{"type":"string","enum":["ok","degraded"],"title":"Status","description":"'ok' si tous les modèles sont à jour, 'degraded' sinon."},"models":{"additionalProperties":{"$ref":"#/components/schemas/ModelStatus"},"type":"object","title":"Models","description":"Statut d'ingestion par source (arome, arpege, vigilance)."}},"type":"object","required":["status","models"],"title":"HealthResponse","examples":[{"models":{"arome":{"last_run_timestamp":"2026-10-06T21:00:00Z","last_success_at":"2026-10-06T21:04:00Z","stale":false},"arpege":{"last_run_timestamp":"2026-10-06T18:00:00Z","last_success_at":"2026-10-06T18:11:00Z","stale":false},"vigilance":{"last_run_timestamp":"2026-10-06T21:04:00Z","last_success_at":"2026-10-06T21:04:00Z","stale":false}},"status":"ok"}]},"LocationForecast":{"properties":{"code_insee":{"type":"string","title":"Code Insee","description":"Code INSEE de la commune.","examples":["75056"]},"nom":{"type":"string","title":"Nom","description":"Nom de la commune.","examples":["Paris"]},"current":{"anyOf":[{"$ref":"#/components/schemas/ForecastPoint"},{"type":"null"}],"description":"Conditions actuelles : point horaire de l'heure en cours (identique à `hourly[0]`). Null si aucune prévision."},"hourly":{"items":{"$ref":"#/components/schemas/ForecastPoint"},"type":"array","title":"Hourly","description":"Prévisions horaires, triées chronologiquement, jusqu'à J+4/J+5."},"daily":{"items":{"$ref":"#/components/schemas/DailyForecast"},"type":"array","title":"Daily","description":"Les mêmes prévisions regroupées par jour local, avec températures min/max, lever/coucher et tranches."}},"type":"object","required":["code_insee","nom","hourly","daily"],"title":"LocationForecast"},"ModelStatus":{"properties":{"last_run_timestamp":{"type":"string","title":"Last Run Timestamp","description":"Horodatage du dernier run ingéré pour ce modèle (UTC, ISO 8601)."},"last_success_at":{"type":"string","title":"Last Success At","description":"Horodatage de la dernière ingestion réussie pour ce modèle (UTC, ISO 8601)."},"stale":{"type":"boolean","title":"Stale","description":"Vrai si la dernière ingestion réussie date de plus de 6h."}},"type":"object","required":["last_run_timestamp","last_success_at","stale"],"title":"ModelStatus"},"PollenDay":{"properties":{"date":{"type":"string","title":"Date","description":"Jour concerné (YYYY-MM-DD, heure locale).","examples":["2026-10-08"]},"indice":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Indice","description":"Indice pollinique global : 1 = très faible, croissant avec le niveau (se fier au `libelle`).","examples":[1]},"libelle":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Libelle","description":"Libellé de l'indice.","examples":["Très faible"]},"alerte":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Alerte","description":"Vrai si une alerte pollen est en cours."},"taxons":{"additionalProperties":{"anyOf":[{"type":"integer"},{"type":"null"}]},"type":"object","title":"Taxons","description":"Indice par taxon : ambroisie, armoise, aulne, bouleau, graminees, olivier.","examples":[{"ambroisie":1,"graminees":1}]},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","description":"Source régionale des données.","examples":["Airparif"]}},"type":"object","required":["date","taxons"],"title":"PollenDay"},"TranchePeriode":{"properties":{"periode":{"type":"string","enum":["nuit","matin","apres_midi","soir"],"title":"Periode","description":"Tranche de journée à quarts égaux : nuit (0-6h), matin (6-12h), apres_midi (12-18h), soir (18-24h)."},"temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature","description":"Température au milieu de la tranche, en °C.","examples":[13.8]},"apparent_temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Apparent Temperature","description":"Température ressentie au milieu de la tranche, en °C.","examples":[12.1]},"wind_direction":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Wind Direction","description":"Direction du vent au milieu de la tranche, en degrés.","examples":[260]},"weather_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weather Code","description":"Code météo WMO le plus sévère de la tranche.","examples":[61]},"weather_icons":{"anyOf":[{"$ref":"#/components/schemas/WeatherIcons"},{"type":"null"}],"description":"Nom d'icône par jeu d'icônes, dérivé de weather_code et de l'heure locale (jour/nuit) du milieu de la tranche.","examples":[{"meteocons":"rain","metno":"lightrain"}]},"precipitation":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Precipitation","description":"Cumul de précipitations sur la tranche, en mm.","examples":[1.2]},"humidity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Humidity","description":"Humidité relative moyenne sur la tranche, en %.","examples":[68.0]},"cloud_cover":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cloud Cover","description":"Couverture nuageuse moyenne sur la tranche, en %.","examples":[55.0]},"wind_speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Wind Speed","description":"Vitesse de vent maximale sur la tranche, en km/h.","examples":[22.0]},"wind_gust":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Wind Gust","description":"Rafales maximales sur la tranche, en km/h.","examples":[45.0]},"pressure":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pressure","description":"Pression au niveau de la mer au milieu de la tranche, en hPa.","examples":[1015.3]},"visibility":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Visibility","description":"Visibilité minimale sur la tranche, en mètres.","examples":[8000]}},"type":"object","required":["periode"],"title":"TranchePeriode"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VigilancePhenomene":{"properties":{"phenomene":{"type":"string","title":"Phenomene","description":"Type de phénomène : vent, pluie_inondation, orages, inondation, neige_verglas, canicule, grand_froid, avalanches, vagues_submersion.","examples":["orages"]},"echeance":{"type":"string","enum":["J","J1"],"title":"Echeance","description":"Échéance : J (aujourd'hui) ou J1 (demain)."},"couleur":{"type":"integer","title":"Couleur","description":"Niveau de vigilance : 1 (vert), 2 (jaune), 3 (orange), 4 (rouge).","examples":[2]},"couleur_libelle":{"type":"string","title":"Couleur Libelle","description":"Libellé du niveau de vigilance.","examples":["jaune"]}},"type":"object","required":["phenomene","echeance","couleur","couleur_libelle"],"title":"VigilancePhenomene"},"WaterRestriction":{"properties":{"departement":{"type":"string","title":"Departement","description":"Code département.","examples":["75"]},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At","description":"Horodatage UTC de la dernière mise à jour (ISO 8601).","examples":["2026-10-07T08:38:00Z"]},"niveau_gravite_max":{"anyOf":[{"type":"string","enum":["vigilance","alerte","alerte_renforcee","crise"]},{"type":"null"}],"title":"Niveau Gravite Max","description":"Niveau de gravité maximum, tous types d'eau confondus. Absent pour certains départements non couverts par VigiEau (ex. une partie des DOM-TOM).","examples":["alerte"]},"niveau_gravite_sup_max":{"anyOf":[{"type":"string","enum":["vigilance","alerte","alerte_renforcee","crise"]},{"type":"null"}],"title":"Niveau Gravite Sup Max","description":"Niveau de gravité max pour l'eau superficielle (rivières, cours d'eau).","examples":["alerte"]},"niveau_gravite_sou_max":{"anyOf":[{"type":"string","enum":["vigilance","alerte","alerte_renforcee","crise"]},{"type":"null"}],"title":"Niveau Gravite Sou Max","description":"Niveau de gravité max pour l'eau souterraine (nappes).","examples":["vigilance"]},"niveau_gravite_aep_max":{"anyOf":[{"type":"string","enum":["vigilance","alerte","alerte_renforcee","crise"]},{"type":"null"}],"title":"Niveau Gravite Aep Max","description":"Niveau de gravité max pour l'eau potable (alimentation en eau potable).","examples":["vigilance"]}},"type":"object","required":["departement"],"title":"WaterRestriction"},"WeatherIcons":{"properties":{"meteocons":{"type":"string","title":"Meteocons","description":"Nom d'icône dans le jeu meteocons (basmilius/meteocons).","examples":["rain"]},"metno":{"type":"string","title":"Metno","description":"Nom d'icône dans le jeu metno (MET Norway weathericons).","examples":["lightrain"]}},"type":"object","required":["meteocons","metno"],"title":"WeatherIcons"}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","description":"Clé API du site client, fournie par l'administrateur via /admin/clients.","in":"header","name":"X-API-Key"}}}}