{
  "openapi": "3.1.0",
  "info": {
    "title": "Données climatologiques Infoclimat (préfiguration CHOM)",
    "version": "0.1.0",
    "description": "API REST ouverte (sans clé) des données climatologiques : séries journalières et mensuelles, records, normales, indice thermique national, indicateurs canicule. Preview sans SLA. Plafond de 20 000 lignes par requête sur toutes les familles de série : la réponse porte tronque, fenetre et suite — si tronque vaut true, réémettez la même URL avec from = suite.from pour la page suivante (aucune ligne perdue ni dupliquée). Pour un dataset entier, passez au bulk Parquet/Iceberg (voir /llms-full.txt). Démarrage : ~1,5 s de chauffe (503 + Retry-After pendant), puis 0,1 à 1 s par requête ; sondes /health et /ready. Timeout client conseillé : 15 s. Cache HTTP (ETag) sur les référentiels. from inclus, to exclu. Guide agent : /llms.txt.",
    "contact": {
      "url": "https://portail.chom.engineering"
    }
  },
  "servers": [
    {
      "url": "https://climato.chom.engineering",
      "description": "API climato (ouverte)"
    },
    {
      "url": "https://portail.chom.engineering/api",
      "description": "miroir même origine que le portail"
    }
  ],
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem detail. Every error response of this API uses this shape, whatever the route. `request_id` correlates the response with the server-side logs and traces — quote it when reporting an incident.",
        "required": [
          "type",
          "title",
          "status",
          "code",
          "request_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Documentation anchor, always `https://portail.chom.engineering/errors#<code>`."
          },
          "title": {
            "type": "string",
            "description": "Short, stable, human-readable summary."
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code, repeated in the body."
          },
          "detail": {
            "type": "string",
            "description": "Explanation for this occurrence. Truncated to 200 characters."
          },
          "instance": {
            "type": "string",
            "description": "Requested path and query. Truncated to 200 characters."
          },
          "code": {
            "type": "string",
            "enum": [
              "coverage-unavailable",
              "dataset-not-found",
              "document-not-found",
              "internal-error",
              "invalid-parameter",
              "licence-reference-unavailable",
              "malformed-request",
              "method-not-supported",
              "missing-parameter",
              "no-current-value",
              "route-not-found",
              "schema-not-ready",
              "service-saturated",
              "service-warming-up",
              "station-not-found",
              "territory-not-found",
              "upstream-licence-restricted",
              "weather-ai-catalog-unavailable",
              "weather-ai-history-invalid",
              "weather-ai-history-run-not-found",
              "weather-ai-history-unavailable",
              "weather-ai-product-integrity-failed",
              "weather-ai-product-invalid",
              "weather-ai-product-not-found",
              "weather-ai-product-unavailable"
            ],
            "description": "Stable machine-readable identifier — branch on this."
          },
          "details": {
            "type": "object",
            "additionalProperties": true,
            "description": "Structured context: offending parameter, accepted values, level."
          },
          "request_id": {
            "type": "string",
            "description": "Correlator, 32 hex characters. Also returned as the X-Request-Id header."
          }
        },
        "additionalProperties": false
      },
      "WeatherAiGridProduct": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": "https://weather-ai.invalid/schema/carto-grid-product.schema.json",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "product_id",
          "run_id",
          "valid_time",
          "snapshot_id",
          "experimental",
          "grid",
          "variable"
        ],
        "properties": {
          "schema_version": {
            "enum": [
              "carto-grid-product/1.0.0",
              "carto-grid-product/1.1.0",
              "carto-grid-product/1.2.0",
              "carto-grid-product/1.3.0",
              "carto-grid-product/1.4.0"
            ]
          },
          "product_id": {
            "enum": [
              "global-mslp-1deg",
              "global-cyclone-existence-1deg"
            ]
          },
          "run_id": {
            "type": "string",
            "minLength": 1
          },
          "valid_time": {
            "type": "string",
            "format": "date-time"
          },
          "snapshot_id": {
            "type": "string",
            "pattern": "^(official-example-snapshot|wn2-input-set)-sha256-[0-9a-f]{64}$"
          },
          "experimental": {
            "const": true
          },
          "grid": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "latitude_start",
              "latitude_step",
              "latitude_count",
              "longitude_start",
              "longitude_step",
              "longitude_count",
              "order"
            ],
            "properties": {
              "latitude_start": {
                "const": -90
              },
              "latitude_step": {
                "const": 1
              },
              "latitude_count": {
                "const": 181
              },
              "longitude_start": {
                "const": 0
              },
              "longitude_step": {
                "const": 1
              },
              "longitude_count": {
                "const": 360
              },
              "order": {
                "const": "latitude-major"
              }
            }
          },
          "variable": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "name",
              "unit",
              "values"
            ],
            "properties": {
              "name": {
                "enum": [
                  "mean_sea_level_pressure",
                  "cyclone_exists_gaussian_unit_mode"
                ]
              },
              "unit": {
                "enum": [
                  "Pa",
                  "1"
                ]
              },
              "values": {
                "type": "array",
                "minItems": 65160,
                "maxItems": 65160,
                "items": {
                  "type": "number"
                }
              }
            }
          },
          "source": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "uri",
              "version_id",
              "sha256",
              "extraction"
            ],
            "properties": {
              "uri": {
                "type": "string",
                "pattern": "^s3://wai-silver/global-fields-tmp/"
              },
              "version_id": {
                "type": "string",
                "minLength": 1
              },
              "sha256": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "extraction": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "batch_index",
                  "time_index",
                  "level_index",
                  "latitude_rows_reversed"
                ],
                "properties": {
                  "batch_index": {
                    "const": 0
                  },
                  "time_index": {
                    "enum": [
                      0,
                      1,
                      2,
                      3,
                      4,
                      5,
                      6,
                      7
                    ]
                  },
                  "level_index": {
                    "const": 0
                  },
                  "latitude_rows_reversed": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "oneOf": [
          {
            "properties": {
              "schema_version": {
                "const": "carto-grid-product/1.0.0"
              },
              "product_id": {
                "const": "global-mslp-1deg"
              },
              "source": {
                "type": "null"
              },
              "variable": {
                "properties": {
                  "name": {
                    "const": "mean_sea_level_pressure"
                  },
                  "unit": {
                    "const": "Pa"
                  }
                }
              }
            }
          },
          {
            "required": [
              "source"
            ],
            "properties": {
              "schema_version": {
                "const": "carto-grid-product/1.1.0"
              },
              "product_id": {
                "const": "global-cyclone-existence-1deg"
              },
              "source": {
                "properties": {
                  "extraction": {
                    "properties": {
                      "time_index": {
                        "const": 1
                      }
                    }
                  }
                }
              },
              "variable": {
                "properties": {
                  "name": {
                    "const": "cyclone_exists_gaussian_unit_mode"
                  },
                  "unit": {
                    "const": "1"
                  },
                  "values": {
                    "items": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1
                    }
                  }
                }
              }
            }
          },
          {
            "required": [
              "source"
            ],
            "properties": {
              "schema_version": {
                "const": "carto-grid-product/1.2.0"
              },
              "product_id": {
                "const": "global-cyclone-existence-1deg"
              },
              "source": {
                "properties": {
                  "extraction": {
                    "properties": {
                      "time_index": {
                        "const": 0
                      }
                    }
                  }
                }
              },
              "variable": {
                "properties": {
                  "name": {
                    "const": "cyclone_exists_gaussian_unit_mode"
                  },
                  "unit": {
                    "const": "1"
                  },
                  "values": {
                    "items": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1
                    }
                  }
                }
              }
            }
          },
          {
            "required": [
              "source"
            ],
            "properties": {
              "schema_version": {
                "const": "carto-grid-product/1.3.0"
              },
              "product_id": {
                "const": "global-cyclone-existence-1deg"
              },
              "source": {
                "properties": {
                  "extraction": {
                    "properties": {
                      "time_index": {
                        "enum": [
                          0,
                          1,
                          2
                        ]
                      }
                    }
                  }
                }
              },
              "variable": {
                "properties": {
                  "name": {
                    "const": "cyclone_exists_gaussian_unit_mode"
                  },
                  "unit": {
                    "const": "1"
                  },
                  "values": {
                    "items": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1
                    }
                  }
                }
              }
            }
          },
          {
            "required": [
              "source"
            ],
            "properties": {
              "schema_version": {
                "const": "carto-grid-product/1.4.0"
              },
              "product_id": {
                "const": "global-cyclone-existence-1deg"
              },
              "source": {
                "properties": {
                  "extraction": {
                    "properties": {
                      "time_index": {
                        "enum": [
                          0,
                          1,
                          2,
                          3,
                          4,
                          5,
                          6,
                          7
                        ]
                      }
                    }
                  }
                }
              },
              "variable": {
                "properties": {
                  "name": {
                    "const": "cyclone_exists_gaussian_unit_mode"
                  },
                  "unit": {
                    "const": "1"
                  },
                  "values": {
                    "items": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "WeatherAiCycloneTracksProduct": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": "cyclone-tracks-product/1.0.0",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "product_id",
          "run_id",
          "init_time",
          "valid_time",
          "snapshot_id",
          "experimental",
          "qualification",
          "tracker",
          "sources",
          "tracks"
        ],
        "properties": {
          "schema_version": {
            "const": "cyclone-tracks-product/1.0.0"
          },
          "product_id": {
            "const": "global-cyclone-tracks-1deg"
          },
          "run_id": {
            "type": "string",
            "minLength": 1
          },
          "init_time": {
            "type": "string",
            "format": "date-time"
          },
          "valid_time": {
            "type": "string",
            "format": "date-time"
          },
          "snapshot_id": {
            "type": "string",
            "minLength": 1
          },
          "experimental": {
            "const": true
          },
          "qualification": {
            "$ref": "#/$defs/qualification"
          },
          "tracker": {
            "$ref": "#/$defs/tracker"
          },
          "sources": {
            "type": "array",
            "minItems": 1,
            "maxItems": 32,
            "items": {
              "$ref": "#/$defs/source"
            }
          },
          "tracks": {
            "type": "array",
            "maxItems": 2592,
            "items": {
              "$ref": "#/$defs/point"
            }
          }
        },
        "$defs": {
          "hash": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "qualification": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "kind",
              "alert_authority",
              "persistence_filter_applied"
            ],
            "properties": {
              "kind": {
                "const": "model_cyclogenesis_candidates"
              },
              "alert_authority": {
                "const": false
              },
              "persistence_filter_applied": {
                "const": false
              }
            }
          },
          "reference": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "uri",
              "version_id",
              "sha256"
            ],
            "properties": {
              "uri": {
                "type": "string",
                "format": "uri"
              },
              "version_id": {
                "type": "string",
                "minLength": 1
              },
              "sha256": {
                "$ref": "#/$defs/hash"
              }
            }
          },
          "source": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "member",
              "raw_forecast",
              "telemetry",
              "extraction"
            ],
            "properties": {
              "member": {
                "type": "integer",
                "minimum": 0,
                "maximum": 31
              },
              "raw_forecast": {
                "$ref": "#/$defs/reference"
              },
              "telemetry": {
                "$ref": "#/$defs/reference"
              },
              "extraction": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "time_index",
                  "lead_hours",
                  "latitude_rows_reversed"
                ],
                "properties": {
                  "time_index": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 7
                  },
                  "lead_hours": {
                    "type": "integer",
                    "minimum": 6,
                    "maximum": 48
                  },
                  "latitude_rows_reversed": {
                    "type": "boolean"
                  }
                }
              }
            }
          },
          "source_file": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "path",
              "sha256"
            ],
            "properties": {
              "path": {
                "type": "string",
                "minLength": 1
              },
              "sha256": {
                "$ref": "#/$defs/hash"
              }
            }
          },
          "config": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "constructor",
              "constructor_parameters",
              "call_parameters"
            ],
            "properties": {
              "constructor": {
                "const": "weathernext.cyclones.direct_tracker.DirectTracker"
              },
              "constructor_parameters": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "cyclogenesis_box_side_degrees",
                  "cyclogenesis_min_max_probability_threshold",
                  "cyclogenesis_min_mean_probability_threshold",
                  "cyclogenesis_minimum_duration",
                  "cyclone_prob_exists_scale_factor",
                  "disc_radius_cyclogenesis_refinement_km",
                  "disc_radius_mean_latlon_km",
                  "disc_radius_mean_probability_of_existence_km",
                  "disc_radius_mode_latlon_km",
                  "disc_radius_scalar_variables_km",
                  "dissipation_min_mean_probability_threshold",
                  "distance_for_pruning_nearby_cyclones_km",
                  "drop_track_merge_indicator",
                  "enforce_physically_consistent_quadrants_and_winds",
                  "min_disc_radius_between_cyclogenesis_candidates_km",
                  "momentum_constant",
                  "probability_cyclone_exists_variable_name",
                  "prune_nearby_cyclones",
                  "rmw_and_quad_clipping_mode",
                  "temporal_resolution_hours",
                  "tracking_mode"
                ],
                "properties": {
                  "cyclogenesis_box_side_degrees": {
                    "const": 5
                  },
                  "cyclogenesis_min_max_probability_threshold": {
                    "const": 0.3
                  },
                  "cyclogenesis_min_mean_probability_threshold": {
                    "const": 0.00001
                  },
                  "cyclogenesis_minimum_duration": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "cyclone_prob_exists_scale_factor": {
                    "const": 1
                  },
                  "disc_radius_cyclogenesis_refinement_km": {
                    "const": 250
                  },
                  "disc_radius_mean_latlon_km": {
                    "const": 250
                  },
                  "disc_radius_mean_probability_of_existence_km": {
                    "const": 500
                  },
                  "disc_radius_mode_latlon_km": {
                    "const": 250
                  },
                  "disc_radius_scalar_variables_km": {
                    "const": null
                  },
                  "dissipation_min_mean_probability_threshold": {
                    "const": 0.00001
                  },
                  "distance_for_pruning_nearby_cyclones_km": {
                    "const": 500
                  },
                  "drop_track_merge_indicator": {
                    "const": true
                  },
                  "enforce_physically_consistent_quadrants_and_winds": {
                    "const": true
                  },
                  "min_disc_radius_between_cyclogenesis_candidates_km": {
                    "const": 500
                  },
                  "momentum_constant": {
                    "const": 0.9
                  },
                  "probability_cyclone_exists_variable_name": {
                    "const": "cyclone_exists_gaussian_unit_mode"
                  },
                  "prune_nearby_cyclones": {
                    "const": true
                  },
                  "rmw_and_quad_clipping_mode": {
                    "const": "clip_quads_below_using_rmw"
                  },
                  "temporal_resolution_hours": {
                    "const": 6
                  },
                  "tracking_mode": {
                    "const": "mode_then_mean"
                  }
                }
              },
              "call_parameters": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "do_cyclogenesis",
                  "initial_storms"
                ],
                "properties": {
                  "do_cyclogenesis": {
                    "const": true
                  },
                  "initial_storms": {
                    "const": "typed_empty"
                  }
                }
              }
            }
          },
          "tracker": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "constructor",
              "variant",
              "code_commit",
              "source_files",
              "model_config",
              "effective_config",
              "effective_config_sha256",
              "official_config_sha256",
              "overrides"
            ],
            "properties": {
              "constructor": {
                "const": "weathernext.cyclones.direct_tracker.DirectTracker"
              },
              "variant": {
                "const": "direct-v1-candidate-no-duration-filter"
              },
              "code_commit": {
                "type": "string",
                "minLength": 1
              },
              "source_files": {
                "type": "array",
                "minItems": 8,
                "maxItems": 8,
                "items": {
                  "$ref": "#/$defs/source_file"
                }
              },
              "model_config": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "artifact_id",
                  "sha256"
                ],
                "properties": {
                  "artifact_id": {
                    "const": "wnc-mini-2023"
                  },
                  "sha256": {
                    "$ref": "#/$defs/hash"
                  }
                }
              },
              "effective_config": {
                "$ref": "#/$defs/config"
              },
              "effective_config_sha256": {
                "const": "2f8b6be6c889c14e182eb544ebcd18e1dc47b5f69fd964f16ab0ffbf08a13485"
              },
              "official_config_sha256": {
                "const": "6852e54e6b3a99adc4a06cb88ebcaa95d70f14bb347c25ce0f51c24390e66bf1"
              },
              "overrides": {
                "type": "array",
                "minItems": 1,
                "maxItems": 1,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "parameter",
                    "official",
                    "effective",
                    "reason_code"
                  ],
                  "properties": {
                    "parameter": {
                      "const": "cyclogenesis_minimum_duration"
                    },
                    "official": {
                      "const": "PT60H"
                    },
                    "effective": {
                      "const": null
                    },
                    "reason_code": {
                      "const": "horizon_shorter_than_official_persistence_filter"
                    }
                  }
                }
              }
            }
          },
          "point": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "member",
              "model_track_id",
              "valid_time",
              "latitude",
              "longitude",
              "mslp_hpa",
              "vmax_ms",
              "forecast_track_duration_hours",
              "forecast_track_point_count"
            ],
            "properties": {
              "member": {
                "type": "integer",
                "minimum": 0,
                "maximum": 31
              },
              "model_track_id": {
                "type": "string",
                "minLength": 1
              },
              "valid_time": {
                "type": "string",
                "format": "date-time"
              },
              "latitude": {
                "type": "number",
                "minimum": -90,
                "maximum": 90
              },
              "longitude": {
                "type": "number",
                "minimum": -180,
                "maximum": 180
              },
              "mslp_hpa": {
                "type": "number"
              },
              "vmax_ms": {
                "type": "number",
                "minimum": 0
              },
              "forecast_track_duration_hours": {
                "type": "integer",
                "minimum": 0
              },
              "forecast_track_point_count": {
                "type": "integer",
                "minimum": 1
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Token délivré sur demande — endpoints /last et /series uniquement."
      }
    }
  },
  "paths": {
    "/legacy/mensuelle": {
      "get": {
        "summary": "Dataset legacy/mensuelle",
        "description": "Le résumé de chaque mois par station — moyenne et extrêmes (jour le plus froid / le plus chaud) : pour des bilans mensuels, au format Météo-France d'origine.\n\nOrdre contractuel : AAAAMM ASC, NUM_POSTE ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (meteo.data.gouv.fr) — attribution Météo-France requise. Attribution : Météo-France / Infoclimat.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "legacy"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "NUM_POSTE": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "AAAAMM": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "pattern": "^\\d{4}(0[1-9]|1[0-2])$"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/legacy/decadaire": {
      "get": {
        "summary": "Dataset legacy/decadaire",
        "description": "Cumuls et moyennes par décade (période de 10 jours) par station, au format Météo-France d'origine — utile pour l'agronomie et le suivi des cultures.\n\nOrdre contractuel : AAAAMM ASC, NUM_DECADE ASC, NUM_POSTE ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (meteo.data.gouv.fr) — attribution Météo-France requise. Attribution : Météo-France / Infoclimat.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "legacy"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "NUM_POSTE": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "AAAAMM": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "pattern": "^\\d{4}(0[1-9]|1[0-2])$"
                          },
                          "NUM_DECADE": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "3e composante de la clé naturelle (1/2/3, 3 décades par mois)"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/legacy/decadaire_agro": {
      "get": {
        "summary": "Dataset legacy/decadaire_agro",
        "description": "Cumuls et moyennes agrométéo par décade (période de 10 jours) par station, au format Météo-France d'origine — pensé pour le suivi des cultures.\n\nOrdre contractuel : AAAAMM ASC, NUM_DECADE ASC, NUM_POSTE ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (meteo.data.gouv.fr) — attribution Météo-France requise. Attribution : Météo-France / Infoclimat.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "legacy"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "NUM_POSTE": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "AAAAMM": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "pattern": "^\\d{4}(0[1-9]|1[0-2])$"
                          },
                          "NUM_DECADE": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "3e composante de la clé naturelle (1/2/3, 3 décades par mois)"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/legacy/quotidienne": {
      "get": {
        "summary": "Dataset legacy/quotidienne",
        "description": "Températures et précipitations journalières par station, au format Météo-France d'origine : pour tracer des courbes de température ou alimenter un tableau de bord compatible avec les outils existants.\n\nOrdre contractuel : AAAAMMJJ ASC, NUM_POSTE ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (meteo.data.gouv.fr) — attribution Météo-France requise. Attribution : Météo-France / Infoclimat.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "legacy"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "NUM_POSTE": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "AAAAMMJJ": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "pattern": "^\\d{8}$"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/legacy/quotidienne_autres": {
      "get": {
        "summary": "Dataset legacy/quotidienne_autres",
        "description": "Les autres paramètres journaliers (pression, humidité, ensoleillement, vent, neige…) au-delà de la température et de la pluie, au format Météo-France d'origine.\n\nOrdre contractuel : AAAAMMJJ ASC, NUM_POSTE ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (meteo.data.gouv.fr) — attribution Météo-France requise. Attribution : Météo-France / Infoclimat.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "legacy"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "NUM_POSTE": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "AAAAMMJJ": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "pattern": "^\\d{8}$"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v2/journaliere": {
      "get": {
        "summary": "Dataset v2/journaliere",
        "description": "Températures journalières (min, max, moyenne) et cumul de précipitation par station, en °C et mm : pour tracer des courbes de température ou alimenter un tableau de bord. Recalculé avec un contrôle qualité qui écarte les valeurs aberrantes.\n\nOrdre contractuel : date ASC, ic_id ASC, mfid ASC.\n\nLicence : Agrégats dérivés de données Météo-France (Licence Ouverte Etalab 2.0) + valeur ajoutée Infoclimat, politique opendata IC. Attribution : Météo-France / Infoclimat.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "v2"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "identifiant de station : ic_id (ex. 07486) ou mfid (ex. 38384001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Identifiant station Infoclimat (crosswalk dim_station)"
                          },
                          "mfid": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France (crosswalk dim_station)"
                          },
                          "date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "tn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température min du jour (°C)"
                          },
                          "tx": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température max du jour (°C)"
                          },
                          "tm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "(tn+tx)/2 (°C)"
                          },
                          "tntxm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "alias de tm (°C)"
                          },
                          "rr": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Cumul de précipitation du jour (mm)"
                          },
                          "n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température agrégées ce jour-là — toutes celles du jour, plausibles ou non, rejets du contrôle qualité compris. C'est la profondeur de preuve du tn/tx : un extrême calculé sur 24 observations et un extrême calculé sur 2 ne se valent pas, et l'écart est massif selon l'époque (médiane de 4 observations par jour en 1960, de 24 en 2025). Attention : n_obs - n_obs_rejetees est un MAJORANT du nombre d'observations effectivement retenues, pas ce nombre — une valeur hors bornes physiques n'est comptée dans aucun des deux et n'est pas retenue. Même définition que sur gold_statIC.journaliere."
                          },
                          "n_obs_rejetees": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température écartées ce jour-là par le contrôle qualité des pics isolés — une valeur isolée au milieu de voisins normaux. Vaut 0 dans l'écrasante majorité des cas. La liste nominative des observations écartées est publiée sur /qc/pic_temperature."
                          },
                          "statut_extremes": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "releve_unique",
                              "partiel",
                              "quotidien",
                              null
                            ],
                            "description": "CALCULÉ PAR LE SERVING, pas stocké — ce que valent tn/tx compte tenu de la densité d'observation du jour. `tn`/`tx` sont le min/max des observations DU JOUR, pas les extrêmes DE LA JOURNÉE : quand la journée est mal échantillonnée, `tn` MAJORE le vrai minimum quotidien et `tx` MINORE le vrai maximum. · `quotidien` : au moins 8 observations retenues (`n_obs - n_obs_rejetees`) — le déficit médian d'amplitude tombe à 0,4 K et ne s'améliore plus au-delà. · `partiel` : 2 à 7 — amplitude amputée de 5,3 K (2 obs) à 0,6 K (7 obs) en médiane. · `releve_unique` : 1 seule — tn = tx = ce relevé, mesuré sur 100 % des 9 088 jours sondés ; ce n'est pas un extrême. · null : aucune observation retenue, rien à qualifier. Le compte est un MAJORANT (les valeurs hors bornes physiques ne sont dans aucun compteur) et il ignore la RÉPARTITION dans la journée : le statut oriente la lecture, il ne certifie pas l'extrême. Aucune valeur n'est filtrée ni nullifiée sur ce critère (issue #85)."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v2/mensuelle": {
      "get": {
        "summary": "Dataset v2/mensuelle",
        "description": "Le résumé de chaque mois par station — moyennes, extrêmes datés (jour le plus froid / le plus chaud), nombre de jours de gel : pour des bilans mensuels.\n\nOrdre contractuel : mois ASC, ic_id ASC, mfid ASC.\n\nLicence : Agrégats dérivés de données Météo-France (Licence Ouverte Etalab 2.0) + valeur ajoutée Infoclimat, politique opendata IC. Attribution : Météo-France / Infoclimat.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "v2"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "identifiant de station : ic_id (ex. 07486) ou mfid (ex. 38384001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "mfid": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "mois": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "pattern": "^\\d{4}-(0[1-9]|1[0-2])$",
                            "description": "Premier jour du mois (date_trunc('month', date))"
                          },
                          "tnm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle des tn (°C)"
                          },
                          "txm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle des tx (°C)"
                          },
                          "tmm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle des tm (°C)"
                          },
                          "rr": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Cumul de précipitation du mois (mm)"
                          },
                          "tnn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température min du mois (°C)"
                          },
                          "tnn_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "txx": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température max du mois (°C)"
                          },
                          "txx_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "nb_jours_gel": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de jours du mois avec tn < 0 °C"
                          },
                          "n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Somme des n_obs journaliers du mois : nombre total d'observations de température agrégées, toutes celles du mois, plausibles ou non. Sert de poids pour comparer des mois dont la densité de mesure diffère. Même définition que sur gold_statIC.mensuelle."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v2/records": {
      "get": {
        "summary": "Dataset v2/records",
        "description": "Les records de température (chaud/froid) de chaque station, par mois calendaire sur tout l'historique : pour afficher « record battu » et les extrêmes historiques.\n\nClé station × mois calendaire : from/to sans effet. Le contexte permet de vérifier un record sans rien savoir de la station : n_jours_tn/n_jours_tx disent sur combien de jours mesurés l'extrême est calculé (les deux diffèrent — tn et tx ne manquent pas les mêmes jours), premiere_obs/derniere_obs bornent la période couverte, et tnn_min_suivant/txx_max_suivant donnent la valeur distincte suivante EN VALEUR (pas dans le temps). Un écart important entre un record et son suivant signale un extrême isolé du reste de la série : sur le fonds sondé, l'écart médian est de 0,7 K et le p90 de 4 K. Aucun seuil n'est publié — l'écart est une donnée, la conclusion appartient au client.\n\nOrdre contractuel : mois_calendaire ASC, ic_id ASC, mfid ASC.\n\nLicence : Agrégats dérivés de données Météo-France (Licence Ouverte Etalab 2.0) + valeur ajoutée Infoclimat, politique opendata IC. Attribution : Météo-France / Infoclimat.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "v2"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "identifiant de station : ic_id (ex. 07486) ou mfid (ex. 38384001)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "mfid": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "mois_calendaire": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Mois calendaire (1-12), 3e composante de la clé naturelle"
                          },
                          "txx_max": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Record absolu de température max sur le mois calendaire (°C)"
                          },
                          "txx_max_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "txx_max_suivant": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "2e valeur DISTINCTE la plus haute de tx sur le mois calendaire (°C) — suivant en VALEUR, pas dans le temps. Un écart important avec txx_max signale un extrême isolé du reste de la série. Vide si le mois calendaire ne porte qu'une seule valeur distincte."
                          },
                          "tnn_min": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Record absolu de température min sur le mois calendaire (°C)"
                          },
                          "tnn_min_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "tnn_min_suivant": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "2e valeur DISTINCTE la plus basse de tn sur le mois calendaire (°C) — suivant en VALEUR, pas dans le temps. Un écart important avec tnn_min signale un extrême isolé du reste de la série. Vide si le mois calendaire ne porte qu'une seule valeur distincte."
                          },
                          "n_jours_tx": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de jours où tx est renseigné sur ce mois calendaire, tous millésimes confondus : le socle sur lequel txx_max est calculé."
                          },
                          "n_jours_tn": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de jours où tn est renseigné sur ce mois calendaire, tous millésimes confondus : le socle sur lequel tnn_min est calculé. Distinct de n_jours_tx — tn et tx ne manquent pas les mêmes jours."
                          },
                          "premiere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Premier jour mesuré de ce mois calendaire (tn ou tx renseigné)"
                          },
                          "derniere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Dernier jour mesuré de ce mois calendaire (tn ou tx renseigné)"
                          },
                          "txx_max_n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température du jour où txx_max est atteint. Avec txx_max_n_obs_rejetees, permet de qualifier la densité du jour du record : au moins 8 observations retenues (n_obs - n_obs_rejetees) correspondent à un extrême quotidien."
                          },
                          "tnn_min_n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température du jour où tnn_min est atteint. Avec tnn_min_n_obs_rejetees, permet de qualifier la densité du jour du record : au moins 8 observations retenues (n_obs - n_obs_rejetees) correspondent à un extrême quotidien."
                          },
                          "txx_max_n_obs_rejetees": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Observations du jour où txx_max est atteint, écartées par le contrôle qualité des pics de température. À soustraire de txx_max_n_obs pour lire la densité retenue du jour du record."
                          },
                          "tnn_min_n_obs_rejetees": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Observations du jour où tnn_min est atteint, écartées par le contrôle qualité des pics de température. À soustraire de tnn_min_n_obs pour lire la densité retenue du jour du record."
                          },
                          "tnn_min_statut": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "releve_unique",
                              "partiel",
                              "quotidien",
                              null
                            ],
                            "description": "CALCULÉ PAR LE SERVING, pas stocké — ce que valent tn/tx compte tenu de la densité d'observation du jour. `tn`/`tx` sont le min/max des observations DU JOUR, pas les extrêmes DE LA JOURNÉE : quand la journée est mal échantillonnée, `tn` MAJORE le vrai minimum quotidien et `tx` MINORE le vrai maximum. · `quotidien` : au moins 8 observations retenues (`n_obs - n_obs_rejetees`) — le déficit médian d'amplitude tombe à 0,4 K et ne s'améliore plus au-delà. · `partiel` : 2 à 7 — amplitude amputée de 5,3 K (2 obs) à 0,6 K (7 obs) en médiane. · `releve_unique` : 1 seule — tn = tx = ce relevé, mesuré sur 100 % des 9 088 jours sondés ; ce n'est pas un extrême. · null : aucune observation retenue, rien à qualifier. Le compte est un MAJORANT (les valeurs hors bornes physiques ne sont dans aucun compteur) et il ignore la RÉPARTITION dans la journée : le statut oriente la lecture, il ne certifie pas l'extrême. Aucune valeur n'est filtrée ni nullifiée sur ce critère (issue #85). Pour `tnn_min`, ce statut porte sur le jour du record, pas sur l'ensemble du mois calendaire."
                          },
                          "txx_max_statut": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "releve_unique",
                              "partiel",
                              "quotidien",
                              null
                            ],
                            "description": "CALCULÉ PAR LE SERVING, pas stocké — ce que valent tn/tx compte tenu de la densité d'observation du jour. `tn`/`tx` sont le min/max des observations DU JOUR, pas les extrêmes DE LA JOURNÉE : quand la journée est mal échantillonnée, `tn` MAJORE le vrai minimum quotidien et `tx` MINORE le vrai maximum. · `quotidien` : au moins 8 observations retenues (`n_obs - n_obs_rejetees`) — le déficit médian d'amplitude tombe à 0,4 K et ne s'améliore plus au-delà. · `partiel` : 2 à 7 — amplitude amputée de 5,3 K (2 obs) à 0,6 K (7 obs) en médiane. · `releve_unique` : 1 seule — tn = tx = ce relevé, mesuré sur 100 % des 9 088 jours sondés ; ce n'est pas un extrême. · null : aucune observation retenue, rien à qualifier. Le compte est un MAJORANT (les valeurs hors bornes physiques ne sont dans aucun compteur) et il ignore la RÉPARTITION dans la journée : le statut oriente la lecture, il ne certifie pas l'extrême. Aucune valeur n'est filtrée ni nullifiée sur ce critère (issue #85). Pour `txx_max`, ce statut porte sur le jour du record, pas sur l'ensemble du mois calendaire."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v2/itn": {
      "get": {
        "summary": "Dataset v2/itn",
        "description": "L'Indicateur Thermique National — la température moyenne quotidienne de la France (30 stations de référence) : pour suivre vagues de chaleur et de froid à l'échelle du pays.\n\nDataset national (indice thermique) : pas de paramètre station.\n\nOrdre contractuel : date ASC.\n\nLicence : Agrégats dérivés de données Météo-France (Licence Ouverte Etalab 2.0) + valeur ajoutée Infoclimat, politique opendata IC. Attribution : Météo-France / Infoclimat.",
        "tags": [
          "v2"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "year": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "month": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "day_of_month": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "is_fictive": {
                            "type": [
                              "boolean",
                              "null"
                            ],
                            "description": "29/02 synthétique des années non-bissextiles (toujours FALSE dans ce build)"
                          },
                          "itn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Indicateur Thermique National du jour (°C)"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/dataclimat/quotidienne": {
      "get": {
        "summary": "Dataset dataclimat/quotidienne",
        "description": "Températures journalières (min, max, moyenne) par station, valeurs officielles Météo-France, historique depuis 1816 : pour tracer des courbes de température ou alimenter un tableau de bord.\n\nto est inclus sur cette route (dataclimat_table fait <=, contrairement aux autres familles où to est exclu).\n\nOrdre contractuel : date ASC, station_code ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (data.gouv.fr). Méthodologie des agrégats : Data For Good, saison 14 (dataforgoodfr/14_ValorisationDonneeMeteo). Attribution : Météo-France.",
        "tags": [
          "dataclimat"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": false,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001) — facultatif, mais au moins un filtre est requis sur ce dataset (sinon 400 `missing-parameter`)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, inclus sur cette famille)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "station_code": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France"
                          },
                          "date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "tntxm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne (tn+tx)/2 — midrange officiel MF (°C)"
                          },
                          "tn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température minimale du jour climatologique (°C)"
                          },
                          "tx": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température maximale du jour climatologique (°C)"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/dataclimat/mensuelle": {
      "get": {
        "summary": "Dataset dataclimat/mensuelle",
        "description": "Le résumé de chaque mois par station — moyenne et extrêmes (jour le plus froid / le plus chaud) : pour des bilans mensuels.\n\nto est inclus sur cette route (dataclimat_table fait <=, contrairement aux autres familles où to est exclu).\n\nOrdre contractuel : date ASC, station_code ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (data.gouv.fr). Méthodologie des agrégats : Data For Good, saison 14 (dataforgoodfr/14_ValorisationDonneeMeteo). Attribution : Météo-France.",
        "tags": [
          "dataclimat"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": false,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001) — facultatif, mais au moins un filtre est requis sur ce dataset (sinon 400 `missing-parameter`)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, inclus sur cette famille)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "station_code": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France"
                          },
                          "date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Mois (premier jour du mois)"
                          },
                          "tnn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Tn minimale du mois (°C)"
                          },
                          "tnn_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Jour du Tn minimal (tie-break date la plus ancienne)"
                          },
                          "txx": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Tx maximale du mois (°C)"
                          },
                          "txx_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Jour du Tx maximal"
                          },
                          "tmm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle de tntxm, arrondie à 0,1 °C"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/dataclimat/records_absolus": {
      "get": {
        "summary": "Dataset dataclimat/records_absolus",
        "description": "Les records de température (chaud/froid) de chaque station, toute l'année / par mois / par saison : pour afficher « record battu » et les extrêmes historiques.\n\nRecords filtrés sur la classe de siting ≤ 3 ; une station sans record calculé renvoie n=0.\n\nOrdre contractuel : station_code ASC, period_type ASC, period_value ASC, record_type ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (data.gouv.fr). Méthodologie des agrégats : Data For Good, saison 14 (dataforgoodfr/14_ValorisationDonneeMeteo). Attribution : Météo-France.",
        "tags": [
          "dataclimat"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": false,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001) — facultatif, mais au moins un filtre est requis sur ce dataset (sinon 400 `missing-parameter`)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_type",
            "in": "query",
            "required": false,
            "description": "filtre sur le type de période du record",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_value",
            "in": "query",
            "required": false,
            "description": "filtre sur la valeur de période",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type_records",
            "in": "query",
            "required": false,
            "description": "hot = records de TX, cold = records de TN",
            "schema": {
              "type": "string",
              "enum": [
                "hot",
                "cold"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "period_type": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "all_time | month | season"
                          },
                          "period_value": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NULL (all_time) | '1'..'12' (mois) | spring|summer|autumn|winter"
                          },
                          "record_type": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "TX (chaud) | TN (froid)"
                          },
                          "station_code": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France"
                          },
                          "station_name": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "department": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "record_value": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Valeur du record (°C)"
                          },
                          "record_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Date du record (tie-break date la plus ancienne)"
                          },
                          "lat": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "lon": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "alt": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "classe_recente": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Classe d'homogénéité MF de la station (1 = meilleure … 5), valeur courante (station_classe.date_fin IS NULL). Le dataset ne retient que classe_recente <= 3 (iso-comportement D4G v_station_records)."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/dataclimat/records_battus": {
      "get": {
        "summary": "Dataset dataclimat/records_battus",
        "description": "L'HISTORIQUE des records progressivement battus par station : une ligne par date où la station a établi un nouvel extrême (chaud/froid), toute l'année / par mois / par saison. Distinct de records_absolus (extrême figé) — sert la timeline « records battus » de dataclimat.fr (API /records, alias /records/historical).\n\nOrdre contractuel : station_code ASC, period_type ASC, period_value ASC, record_type ASC, record_date ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (data.gouv.fr). Méthodologie des agrégats : Data For Good, saison 14 (dataforgoodfr/14_ValorisationDonneeMeteo). Attribution : Météo-France.",
        "tags": [
          "dataclimat"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": false,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001) — facultatif, mais au moins un filtre est requis sur ce dataset (sinon 400 `missing-parameter`)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_type",
            "in": "query",
            "required": false,
            "description": "filtre sur le type de période du record",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_value",
            "in": "query",
            "required": false,
            "description": "filtre sur la valeur de période",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type_records",
            "in": "query",
            "required": false,
            "description": "hot = records de TX, cold = records de TN",
            "schema": {
              "type": "string",
              "enum": [
                "hot",
                "cold"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "period_type": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "all_time | month | season"
                          },
                          "period_value": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NULL (all_time) | '1'..'12' (mois) | spring|summer|autumn|winter"
                          },
                          "record_type": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "TX (chaud) | TN (froid)"
                          },
                          "station_code": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France"
                          },
                          "station_name": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "department": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "record_value": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Valeur du record établi ce jour-là (°C)"
                          },
                          "record_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Date à laquelle ce nouvel extrême a été atteint"
                          },
                          "lat": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "lon": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "alt": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "classe_recente": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Classe d'homogénéité MF (1 = meilleure … 5), valeur courante. Filtre classe_recente <= 3 (iso-comportement D4G v_records_battus)."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/dataclimat/itn": {
      "get": {
        "summary": "Dataset dataclimat/itn",
        "description": "L'Indicateur Thermique National — la température moyenne quotidienne de la France (30 stations de référence) : pour suivre vagues de chaleur et de froid à l'échelle du pays.\n\nDataset national : pas de paramètre station. to est inclus sur cette route (dataclimat_table fait <=, contrairement aux autres familles où to est exclu).\n\nOrdre contractuel : date ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (data.gouv.fr). Méthodologie des agrégats : Data For Good, saison 14 (dataforgoodfr/14_ValorisationDonneeMeteo). Attribution : Météo-France.",
        "tags": [
          "dataclimat"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, inclus sur cette famille)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "year": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "month": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "day_of_month": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "is_fictive": {
                            "type": [
                              "boolean",
                              "null"
                            ],
                            "description": "TRUE si 29 février synthétique (année non bissextile)"
                          },
                          "itn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Indicateur Thermique National du jour (°C)"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/dataclimat/itn_baseline": {
      "get": {
        "summary": "Dataset dataclimat/itn_baseline",
        "description": "La normale 1991-2020 de l'ITN, jour par jour : la référence pour dire si une journée est au-dessus ou en dessous de la normale nationale.\n\nOrdre contractuel : month ASC, day_of_month ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (data.gouv.fr). Méthodologie des agrégats : Data For Good, saison 14 (dataforgoodfr/14_ValorisationDonneeMeteo). Attribution : Météo-France.",
        "tags": [
          "dataclimat"
        ],
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "mois calendaire 1-12",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "day",
            "in": "query",
            "required": false,
            "description": "jour du mois",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "month": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "day_of_month": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "sample_size": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "itn_mean": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "itn_stddev": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Écart-type de population (STDDEV_POP)"
                          },
                          "itn_p20": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "itn_p80": {
                            "type": [
                              "number",
                              "null"
                            ]
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/dataclimat/baseline_1991_2020": {
      "get": {
        "summary": "Dataset dataclimat/baseline_1991_2020",
        "description": "La normale de température 1991-2020 de chaque station, jour par jour de l'année : pour calculer l'écart à la normale.\n\nOrdre contractuel : station_code ASC, month ASC, day ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (data.gouv.fr). Méthodologie des agrégats : Data For Good, saison 14 (dataforgoodfr/14_ValorisationDonneeMeteo). Attribution : Météo-France.",
        "tags": [
          "dataclimat"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": false,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001) — facultatif, mais au moins un filtre est requis sur ce dataset (sinon 400 `missing-parameter`)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "mois calendaire 1-12",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "day",
            "in": "query",
            "required": false,
            "description": "jour du mois",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "station_code": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France"
                          },
                          "month": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "day": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "sample_count": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'années contributrices (>= 24)"
                          },
                          "baseline_mean_tntxm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne 1991-2020 de tntxm pour ce jour calendaire (°C)"
                          },
                          "classe_recente": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Classe d'homogénéité MF de la station (1 = meilleure … 5), valeur courante (station_classe.date_fin IS NULL). Le dataset ne retient que classe_recente <= 4 (iso-comportement D4G v_station_deviation)."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/dataclimat/first_temperature_date": {
      "get": {
        "summary": "Dataset dataclimat/first_temperature_date",
        "description": "Depuis quel mois chaque station mesure la température : pour connaître l'ancienneté d'une station. La date est un texte au format AAAAMM (année puis mois sur deux chiffres) — par exemple « 187206 » = juin 1872.\n\nOrdre contractuel : station_code ASC.\n\nLicence : Données source Météo-France, Licence Ouverte (Etalab) 2.0 (data.gouv.fr). Méthodologie des agrégats : Data For Good, saison 14 (dataforgoodfr/14_ValorisationDonneeMeteo). Attribution : Météo-France.",
        "tags": [
          "dataclimat"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": false,
            "description": "NUM_POSTE Météo-France, 8 caractères (ex. 75114001)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "station_code": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France"
                          },
                          "first_temperature_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Mois du premier relevé de température, texte au format AAAAMM (année + mois sur deux chiffres), ex. « 187206 » = juin 1872. Ni date ISO ni nombre."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/ic/journaliere": {
      "get": {
        "summary": "Dataset ic/journaliere",
        "description": "Températures journalières (min, max, moyenne) et cumul de précipitation par station, en °C et mm, à partir des sources collectées par Infoclimat hors Météo-France (synop/metar/bouées officiels relayés + StatIC + Météo-à-l'École). Contrôle qualité qui écarte les valeurs aberrantes.\n\nOrdre contractuel : date ASC, ic_id ASC, mfid ASC.\n\nLicence : Sources multiples collectées par Infoclimat hors Météo-France : réseaux officiels SYNOP/METAR/bouées (diffusions internationales) et réseaux participatifs StatIC / Météo-à-l'École, redistribués sous la politique opendata Infoclimat. Les données officielles restent sous la licence de leur producteur. Attribution : Infoclimat (collecte multi-sources hors Météo-France).\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "ic"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "identifiant de station : ic_id (ex. 07486) ou mfid (ex. 38384001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Identifiant station Infoclimat (crosswalk dim_station)"
                          },
                          "mfid": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France si la station est aussi référencée MF, sinon vide"
                          },
                          "date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "tn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température min du jour (°C)"
                          },
                          "tx": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température max du jour (°C)"
                          },
                          "tm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "(tn+tx)/2 (°C)"
                          },
                          "tntxm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "alias de tm (°C)"
                          },
                          "rr": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Cumul de précipitation du jour (mm)"
                          },
                          "n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température agrégées ce jour-là — toutes celles du jour, plausibles ou non, rejets du contrôle qualité compris. C'est la profondeur de preuve du tn/tx : un extrême calculé sur 24 observations et un extrême calculé sur 2 ne se valent pas, et l'écart est massif selon l'époque (médiane de 4 observations par jour en 1960, de 24 en 2025). Attention : n_obs - n_obs_rejetees est un MAJORANT du nombre d'observations effectivement retenues, pas ce nombre — une valeur hors bornes physiques n'est comptée dans aucun des deux et n'est pas retenue. Même définition que sur gold_statIC.journaliere."
                          },
                          "n_obs_rejetees": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température écartées ce jour-là par le contrôle qualité des pics isolés — une valeur isolée au milieu de voisins normaux. Vaut 0 dans l'écrasante majorité des cas. La liste nominative des observations écartées est publiée sur /qc/pic_temperature."
                          },
                          "statut_extremes": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "releve_unique",
                              "partiel",
                              "quotidien",
                              null
                            ],
                            "description": "CALCULÉ PAR LE SERVING, pas stocké — ce que valent tn/tx compte tenu de la densité d'observation du jour. `tn`/`tx` sont le min/max des observations DU JOUR, pas les extrêmes DE LA JOURNÉE : quand la journée est mal échantillonnée, `tn` MAJORE le vrai minimum quotidien et `tx` MINORE le vrai maximum. · `quotidien` : au moins 8 observations retenues (`n_obs - n_obs_rejetees`) — le déficit médian d'amplitude tombe à 0,4 K et ne s'améliore plus au-delà. · `partiel` : 2 à 7 — amplitude amputée de 5,3 K (2 obs) à 0,6 K (7 obs) en médiane. · `releve_unique` : 1 seule — tn = tx = ce relevé, mesuré sur 100 % des 9 088 jours sondés ; ce n'est pas un extrême. · null : aucune observation retenue, rien à qualifier. Le compte est un MAJORANT (les valeurs hors bornes physiques ne sont dans aucun compteur) et il ignore la RÉPARTITION dans la journée : le statut oriente la lecture, il ne certifie pas l'extrême. Aucune valeur n'est filtrée ni nullifiée sur ce critère (issue #85)."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/ic/mensuelle": {
      "get": {
        "summary": "Dataset ic/mensuelle",
        "description": "Le résumé de chaque mois par station — moyennes, extrêmes datés (jour le plus froid / le plus chaud), nombre de jours de gel — sur les sources collectées par Infoclimat hors Météo-France.\n\nOrdre contractuel : mois ASC, ic_id ASC, mfid ASC.\n\nLicence : Sources multiples collectées par Infoclimat hors Météo-France : réseaux officiels SYNOP/METAR/bouées (diffusions internationales) et réseaux participatifs StatIC / Météo-à-l'École, redistribués sous la politique opendata Infoclimat. Les données officielles restent sous la licence de leur producteur. Attribution : Infoclimat (collecte multi-sources hors Météo-France).\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "ic"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "identifiant de station : ic_id (ex. 07486) ou mfid (ex. 38384001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "mfid": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France si la station est aussi référencée MF, sinon vide"
                          },
                          "mois": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "pattern": "^\\d{4}-(0[1-9]|1[0-2])$",
                            "description": "Premier jour du mois (date_trunc('month', date))"
                          },
                          "tnm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle des tn (°C)"
                          },
                          "txm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle des tx (°C)"
                          },
                          "tmm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle des tm (°C)"
                          },
                          "rr": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Cumul de précipitation du mois (mm)"
                          },
                          "tnn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température min du mois (°C)"
                          },
                          "tnn_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "txx": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température max du mois (°C)"
                          },
                          "txx_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "nb_jours_gel": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de jours du mois avec tn < 0 °C"
                          },
                          "n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Somme des n_obs journaliers du mois : nombre total d'observations de température agrégées, toutes celles du mois, plausibles ou non. Sert de poids pour comparer des mois dont la densité de mesure diffère. Même définition que sur gold_statIC.mensuelle."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/ic/records": {
      "get": {
        "summary": "Dataset ic/records",
        "description": "Les records de température (chaud/froid) de chaque station, par mois calendaire sur tout l'historique, sur les sources collectées par Infoclimat hors Météo-France : pour afficher « record battu » et les extrêmes historiques.\n\nClé station × mois calendaire : from/to sans effet. Le contexte permet de vérifier un record sans rien savoir de la station : n_jours_tn/n_jours_tx disent sur combien de jours mesurés l'extrême est calculé (les deux diffèrent — tn et tx ne manquent pas les mêmes jours), premiere_obs/derniere_obs bornent la période couverte, et tnn_min_suivant/txx_max_suivant donnent la valeur distincte suivante EN VALEUR (pas dans le temps). Un écart important entre un record et son suivant signale un extrême isolé du reste de la série : sur le fonds sondé, l'écart médian est de 0,7 K et le p90 de 4 K. Aucun seuil n'est publié — l'écart est une donnée, la conclusion appartient au client.\n\nOrdre contractuel : mois_calendaire ASC, ic_id ASC, mfid ASC.\n\nLicence : Sources multiples collectées par Infoclimat hors Météo-France : réseaux officiels SYNOP/METAR/bouées (diffusions internationales) et réseaux participatifs StatIC / Météo-à-l'École, redistribués sous la politique opendata Infoclimat. Les données officielles restent sous la licence de leur producteur. Attribution : Infoclimat (collecte multi-sources hors Météo-France).\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "ic"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "identifiant de station : ic_id (ex. 07486) ou mfid (ex. 38384001)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "mfid": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France si la station est aussi référencée MF, sinon vide"
                          },
                          "mois_calendaire": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Mois calendaire (1-12), 3e composante de la clé naturelle"
                          },
                          "txx_max": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Record absolu de température max sur le mois calendaire (°C)"
                          },
                          "txx_max_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "txx_max_suivant": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "2e valeur DISTINCTE la plus haute de tx sur le mois calendaire (°C) — suivant en VALEUR, pas dans le temps. Un écart important avec txx_max signale un extrême isolé du reste de la série. Vide si le mois calendaire ne porte qu'une seule valeur distincte."
                          },
                          "tnn_min": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Record absolu de température min sur le mois calendaire (°C)"
                          },
                          "tnn_min_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "tnn_min_suivant": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "2e valeur DISTINCTE la plus basse de tn sur le mois calendaire (°C) — suivant en VALEUR, pas dans le temps. Un écart important avec tnn_min signale un extrême isolé du reste de la série. Vide si le mois calendaire ne porte qu'une seule valeur distincte."
                          },
                          "n_jours_tx": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de jours où tx est renseigné sur ce mois calendaire, tous millésimes confondus : le socle sur lequel txx_max est calculé."
                          },
                          "n_jours_tn": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de jours où tn est renseigné sur ce mois calendaire, tous millésimes confondus : le socle sur lequel tnn_min est calculé. Distinct de n_jours_tx — tn et tx ne manquent pas les mêmes jours."
                          },
                          "premiere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Premier jour mesuré de ce mois calendaire (tn ou tx renseigné)"
                          },
                          "derniere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Dernier jour mesuré de ce mois calendaire (tn ou tx renseigné)"
                          },
                          "txx_max_n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température du jour où txx_max est atteint. Avec txx_max_n_obs_rejetees, permet de qualifier la densité du jour du record : au moins 8 observations retenues (n_obs - n_obs_rejetees) correspondent à un extrême quotidien."
                          },
                          "tnn_min_n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température du jour où tnn_min est atteint. Avec tnn_min_n_obs_rejetees, permet de qualifier la densité du jour du record : au moins 8 observations retenues (n_obs - n_obs_rejetees) correspondent à un extrême quotidien."
                          },
                          "txx_max_n_obs_rejetees": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Observations du jour où txx_max est atteint, écartées par le contrôle qualité des pics de température. À soustraire de txx_max_n_obs pour lire la densité retenue du jour du record."
                          },
                          "tnn_min_n_obs_rejetees": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Observations du jour où tnn_min est atteint, écartées par le contrôle qualité des pics de température. À soustraire de tnn_min_n_obs pour lire la densité retenue du jour du record."
                          },
                          "tnn_min_statut": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "releve_unique",
                              "partiel",
                              "quotidien",
                              null
                            ],
                            "description": "CALCULÉ PAR LE SERVING, pas stocké — ce que valent tn/tx compte tenu de la densité d'observation du jour. `tn`/`tx` sont le min/max des observations DU JOUR, pas les extrêmes DE LA JOURNÉE : quand la journée est mal échantillonnée, `tn` MAJORE le vrai minimum quotidien et `tx` MINORE le vrai maximum. · `quotidien` : au moins 8 observations retenues (`n_obs - n_obs_rejetees`) — le déficit médian d'amplitude tombe à 0,4 K et ne s'améliore plus au-delà. · `partiel` : 2 à 7 — amplitude amputée de 5,3 K (2 obs) à 0,6 K (7 obs) en médiane. · `releve_unique` : 1 seule — tn = tx = ce relevé, mesuré sur 100 % des 9 088 jours sondés ; ce n'est pas un extrême. · null : aucune observation retenue, rien à qualifier. Le compte est un MAJORANT (les valeurs hors bornes physiques ne sont dans aucun compteur) et il ignore la RÉPARTITION dans la journée : le statut oriente la lecture, il ne certifie pas l'extrême. Aucune valeur n'est filtrée ni nullifiée sur ce critère (issue #85). Pour `tnn_min`, ce statut porte sur le jour du record, pas sur l'ensemble du mois calendaire."
                          },
                          "txx_max_statut": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "releve_unique",
                              "partiel",
                              "quotidien",
                              null
                            ],
                            "description": "CALCULÉ PAR LE SERVING, pas stocké — ce que valent tn/tx compte tenu de la densité d'observation du jour. `tn`/`tx` sont le min/max des observations DU JOUR, pas les extrêmes DE LA JOURNÉE : quand la journée est mal échantillonnée, `tn` MAJORE le vrai minimum quotidien et `tx` MINORE le vrai maximum. · `quotidien` : au moins 8 observations retenues (`n_obs - n_obs_rejetees`) — le déficit médian d'amplitude tombe à 0,4 K et ne s'améliore plus au-delà. · `partiel` : 2 à 7 — amplitude amputée de 5,3 K (2 obs) à 0,6 K (7 obs) en médiane. · `releve_unique` : 1 seule — tn = tx = ce relevé, mesuré sur 100 % des 9 088 jours sondés ; ce n'est pas un extrême. · null : aucune observation retenue, rien à qualifier. Le compte est un MAJORANT (les valeurs hors bornes physiques ne sont dans aucun compteur) et il ignore la RÉPARTITION dans la journée : le statut oriente la lecture, il ne certifie pas l'extrême. Aucune valeur n'est filtrée ni nullifiée sur ce critère (issue #85). Pour `txx_max`, ce statut porte sur le jour du record, pas sur l'ensemble du mois calendaire."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/statIC/journaliere": {
      "get": {
        "summary": "Dataset statIC/journaliere",
        "description": "Températures journalières (min, max, moyenne) et cumul de précipitation par station StatIC, en °C et mm, avec la densité d'observations et le taux de mesures plausibles : pour exploiter le réseau participatif en connaissance de cause.\n\nclasse_station est toujours null (pas de classification de siting sur un réseau participatif). taux_qc_valide est un ratio [0,1] — 1 = 100 %, ce n'est pas un pourcentage : part des obs air_temperature du jour comprises dans les bornes de plausibilité physique [-90, +60] °C, rapportée à n_obs (toutes les obs de température du jour, plausibles ou non), arrondie à 3 décimales. Ce n'est pas un flag QC de réseau : les obs StatIC arrivent sans QC amont. Jamais null — un jour sans obs de température ne produit pas de ligne. Les bornes sont assez larges pour qu'il vaille 1,0 sur tout le fonds sondé (26 870 jours, 50 stations, 2024-2026) : garde-fou de plausibilité, pas indicateur de qualité discriminant. La valeur 0 impliquerait tn/tx/tm null.\n\nOrdre contractuel : date ASC, ic_id ASC.\n\nLicence : Données du réseau participatif StatIC (Infoclimat), Licence Ouverte (Etalab) 2.0 (cf. infoclimat.fr/opendata). Licence propre à trancher au besoin (gate CA). Attribution : Infoclimat / réseau StatIC.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "statIC"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "ic_id d'une station StatIC — aucune forme unique (ex. STATIC0253, 00006)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Identifiant station StatIC (Infoclimat)"
                          },
                          "date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "tn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température min du jour (°C)"
                          },
                          "tx": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température max du jour (°C)"
                          },
                          "tm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "(tn+tx)/2 (°C)"
                          },
                          "tntxm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "alias de tm (°C)"
                          },
                          "rr": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Cumul de précipitation du jour (mm), nul si > 2000 mm (impossible)"
                          },
                          "n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température agrégées ce jour (densité)"
                          },
                          "taux_qc_valide": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Part des obs de température dans les bornes physiques [-90,+60] °C (0-1) — ratio, pas un pourcentage : 1 = 100 %, arrondi à 3 décimales",
                            "minimum": 0,
                            "maximum": 1
                          },
                          "classe_station": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Classe siting StatIC (1-5) — NON RENSEIGNÉE (déviation, cf. limitations)"
                          },
                          "n_obs_rejetees": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température écartées ce jour-là par le contrôle qualité des pics isolés — une valeur isolée au milieu de voisins normaux. Vaut 0 dans l'écrasante majorité des cas. La liste nominative des observations écartées est publiée sur /qc/pic_temperature."
                          },
                          "statut_extremes": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "releve_unique",
                              "partiel",
                              "quotidien",
                              null
                            ],
                            "description": "CALCULÉ PAR LE SERVING, pas stocké — ce que valent tn/tx compte tenu de la densité d'observation du jour. `tn`/`tx` sont le min/max des observations DU JOUR, pas les extrêmes DE LA JOURNÉE : quand la journée est mal échantillonnée, `tn` MAJORE le vrai minimum quotidien et `tx` MINORE le vrai maximum. · `quotidien` : au moins 8 observations retenues (`n_obs - n_obs_rejetees`) — le déficit médian d'amplitude tombe à 0,4 K et ne s'améliore plus au-delà. · `partiel` : 2 à 7 — amplitude amputée de 5,3 K (2 obs) à 0,6 K (7 obs) en médiane. · `releve_unique` : 1 seule — tn = tx = ce relevé, mesuré sur 100 % des 9 088 jours sondés ; ce n'est pas un extrême. · null : aucune observation retenue, rien à qualifier. Le compte est un MAJORANT (les valeurs hors bornes physiques ne sont dans aucun compteur) et il ignore la RÉPARTITION dans la journée : le statut oriente la lecture, il ne certifie pas l'extrême. Aucune valeur n'est filtrée ni nullifiée sur ce critère (issue #85)."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/statIC/mensuelle": {
      "get": {
        "summary": "Dataset statIC/mensuelle",
        "description": "Le résumé de chaque mois par station StatIC — moyennes, extrêmes datés, jours de gel — avec la densité et le taux de mesures plausibles du mois.\n\nclasse_station est toujours null, comme en journalière. taux_qc_valide est la moyenne des ratios journaliers pondérée par n_obs — même échelle [0,1] et mêmes réserves. n_obs est la somme des n_obs journaliers du mois.\n\nOrdre contractuel : mois ASC, ic_id ASC.\n\nLicence : Données du réseau participatif StatIC (Infoclimat), Licence Ouverte (Etalab) 2.0 (cf. infoclimat.fr/opendata). Licence propre à trancher au besoin (gate CA). Attribution : Infoclimat / réseau StatIC.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "statIC"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "ic_id d'une station StatIC — aucune forme unique (ex. STATIC0253, 00006)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "mois": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "pattern": "^\\d{4}-(0[1-9]|1[0-2])$",
                            "description": "Premier jour du mois"
                          },
                          "tnm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle des tn (°C)"
                          },
                          "txm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle des tx (°C)"
                          },
                          "tmm": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne mensuelle des tm (°C)"
                          },
                          "rr": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Cumul de précipitation du mois (mm)"
                          },
                          "tnn": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température min du mois (°C)"
                          },
                          "tnn_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "txx": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Température max du mois (°C)"
                          },
                          "txx_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "nb_jours_gel": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de jours du mois avec tn < 0 °C"
                          },
                          "n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température du mois"
                          },
                          "taux_qc_valide": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Taux d'obs plausibles du mois, pondéré par la densité (0-1) — ratio, pas un pourcentage : 1 = 100 %, arrondi à 3 décimales",
                            "minimum": 0,
                            "maximum": 1
                          },
                          "classe_station": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Classe siting StatIC — NON RENSEIGNÉE (déviation)"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/statIC/records": {
      "get": {
        "summary": "Dataset statIC/records",
        "description": "Les records de température (chaud/froid) de chaque station StatIC, par mois calendaire sur tout l'historique : extrêmes bruts du réseau participatif (à lire avec la densité/qualité de la station).\n\nClé station × mois calendaire : from/to sans effet. Le contexte permet de vérifier un record sans rien savoir de la station : n_jours_tn/n_jours_tx disent sur combien de jours mesurés l'extrême est calculé (les deux diffèrent — tn et tx ne manquent pas les mêmes jours), premiere_obs/derniere_obs bornent la période couverte, et tnn_min_suivant/txx_max_suivant donnent la valeur distincte suivante EN VALEUR (pas dans le temps). Un écart important entre un record et son suivant signale un extrême isolé du reste de la série : sur le fonds sondé, l'écart médian est de 0,7 K et le p90 de 4 K. Aucun seuil n'est publié — l'écart est une donnée, la conclusion appartient au client.\n\nOrdre contractuel : mois_calendaire ASC, ic_id ASC.\n\nLicence : Données du réseau participatif StatIC (Infoclimat), Licence Ouverte (Etalab) 2.0 (cf. infoclimat.fr/opendata). Licence propre à trancher au besoin (gate CA). Attribution : Infoclimat / réseau StatIC.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "statIC"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "ic_id d'une station StatIC — aucune forme unique (ex. STATIC0253, 00006)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "mois_calendaire": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Mois calendaire (1-12)"
                          },
                          "txx_max": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Record de température max sur le mois calendaire (°C)"
                          },
                          "txx_max_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "txx_max_suivant": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "2e valeur DISTINCTE la plus haute de tx sur le mois calendaire (°C) — suivant en VALEUR, pas dans le temps. Un écart important avec txx_max signale un extrême isolé du reste de la série. Vide si le mois calendaire ne porte qu'une seule valeur distincte."
                          },
                          "tnn_min": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Record de température min sur le mois calendaire (°C)"
                          },
                          "tnn_min_date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "tnn_min_suivant": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "2e valeur DISTINCTE la plus basse de tn sur le mois calendaire (°C) — suivant en VALEUR, pas dans le temps. Un écart important avec tnn_min signale un extrême isolé du reste de la série. Vide si le mois calendaire ne porte qu'une seule valeur distincte."
                          },
                          "n_jours_tx": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de jours où tx est renseigné sur ce mois calendaire, tous millésimes confondus : le socle sur lequel txx_max est calculé."
                          },
                          "n_jours_tn": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de jours où tn est renseigné sur ce mois calendaire, tous millésimes confondus : le socle sur lequel tnn_min est calculé. Distinct de n_jours_tx — tn et tx ne manquent pas les mêmes jours."
                          },
                          "premiere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Premier jour mesuré de ce mois calendaire (tn ou tx renseigné)"
                          },
                          "derniere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Dernier jour mesuré de ce mois calendaire (tn ou tx renseigné)"
                          },
                          "txx_max_n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température du jour où txx_max est atteint. Avec txx_max_n_obs_rejetees, permet de qualifier la densité du jour du record : au moins 8 observations retenues (n_obs - n_obs_rejetees) correspondent à un extrême quotidien."
                          },
                          "tnn_min_n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations de température du jour où tnn_min est atteint. Avec tnn_min_n_obs_rejetees, permet de qualifier la densité du jour du record : au moins 8 observations retenues (n_obs - n_obs_rejetees) correspondent à un extrême quotidien."
                          },
                          "txx_max_n_obs_rejetees": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Observations du jour où txx_max est atteint, écartées par le contrôle qualité des pics de température. À soustraire de txx_max_n_obs pour lire la densité retenue du jour du record."
                          },
                          "tnn_min_n_obs_rejetees": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Observations du jour où tnn_min est atteint, écartées par le contrôle qualité des pics de température. À soustraire de tnn_min_n_obs pour lire la densité retenue du jour du record."
                          },
                          "tnn_min_statut": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "releve_unique",
                              "partiel",
                              "quotidien",
                              null
                            ],
                            "description": "CALCULÉ PAR LE SERVING, pas stocké — ce que valent tn/tx compte tenu de la densité d'observation du jour. `tn`/`tx` sont le min/max des observations DU JOUR, pas les extrêmes DE LA JOURNÉE : quand la journée est mal échantillonnée, `tn` MAJORE le vrai minimum quotidien et `tx` MINORE le vrai maximum. · `quotidien` : au moins 8 observations retenues (`n_obs - n_obs_rejetees`) — le déficit médian d'amplitude tombe à 0,4 K et ne s'améliore plus au-delà. · `partiel` : 2 à 7 — amplitude amputée de 5,3 K (2 obs) à 0,6 K (7 obs) en médiane. · `releve_unique` : 1 seule — tn = tx = ce relevé, mesuré sur 100 % des 9 088 jours sondés ; ce n'est pas un extrême. · null : aucune observation retenue, rien à qualifier. Le compte est un MAJORANT (les valeurs hors bornes physiques ne sont dans aucun compteur) et il ignore la RÉPARTITION dans la journée : le statut oriente la lecture, il ne certifie pas l'extrême. Aucune valeur n'est filtrée ni nullifiée sur ce critère (issue #85). Pour `tnn_min`, ce statut porte sur le jour du record, pas sur l'ensemble du mois calendaire."
                          },
                          "txx_max_statut": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "enum": [
                              "releve_unique",
                              "partiel",
                              "quotidien",
                              null
                            ],
                            "description": "CALCULÉ PAR LE SERVING, pas stocké — ce que valent tn/tx compte tenu de la densité d'observation du jour. `tn`/`tx` sont le min/max des observations DU JOUR, pas les extrêmes DE LA JOURNÉE : quand la journée est mal échantillonnée, `tn` MAJORE le vrai minimum quotidien et `tx` MINORE le vrai maximum. · `quotidien` : au moins 8 observations retenues (`n_obs - n_obs_rejetees`) — le déficit médian d'amplitude tombe à 0,4 K et ne s'améliore plus au-delà. · `partiel` : 2 à 7 — amplitude amputée de 5,3 K (2 obs) à 0,6 K (7 obs) en médiane. · `releve_unique` : 1 seule — tn = tx = ce relevé, mesuré sur 100 % des 9 088 jours sondés ; ce n'est pas un extrême. · null : aucune observation retenue, rien à qualifier. Le compte est un MAJORANT (les valeurs hors bornes physiques ne sont dans aucun compteur) et il ignore la RÉPARTITION dans la journée : le statut oriente la lecture, il ne certifie pas l'extrême. Aucune valeur n'est filtrée ni nullifiée sur ce critère (issue #85). Pour `txx_max`, ce statut porte sur le jour du record, pas sur l'ensemble du mois calendaire."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/statIC/indicateur_reseau": {
      "get": {
        "summary": "Dataset statIC/indicateur_reseau",
        "description": "L'indicateur thermique national du réseau StatIC — la température moyenne quotidienne de la France, calculée pour être SPATIALEMENT REPRÉSENTATIVE : moyenne par département puis moyenne des départements couverts (et non moyenne brute des stations, qui sur-pondérerait les zones denses). La couverture (nombre de stations, de départements) et la dispersion sont exposées pour la transparence. V1 national ; régional et anomalies vs normales = suite.\n\nDataset national : pas de paramètre station. DOM-TOM exclus.\n\nOrdre contractuel : date ASC, echelle ASC.\n\nLicence : Données du réseau participatif StatIC (Infoclimat), Licence Ouverte (Etalab) 2.0 (cf. infoclimat.fr/opendata). Licence propre à trancher au besoin (gate CA). Attribution : Infoclimat / réseau StatIC.",
        "tags": [
          "statIC"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "licence",
                    "attribution",
                    "n",
                    "tronque",
                    "mesures"
                  ],
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer",
                      "description": "lignes réellement rendues"
                    },
                    "plafond": {
                      "type": "integer",
                      "description": "plafond de lignes en vigueur sur cette route"
                    },
                    "tronque": {
                      "type": "boolean",
                      "description": "true = la source avait plus de lignes que le plafond ; la série rendue est incomplète"
                    },
                    "fenetre": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "extension effective des lignes rendues, bornes incluses ; null si aucune ligne ou dataset sans colonne de date",
                      "properties": {
                        "debut": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        },
                        "fin": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "suite": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "requête suivante : réémettre la MÊME URL en remplaçant from par cette valeur. null s'il n'y a pas de suite, ou si le dataset n'offre aucun point de reprise (pas de colonne de date, ou page entièrement occupée par une seule date)",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "date",
                          "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                        }
                      },
                      "additionalProperties": false
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "echelle": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Échelle spatiale ('national' en V1)"
                          },
                          "itn_statIC": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Indicateur thermique StatIC du jour, représentatif (°C)"
                          },
                          "tn_moy": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne réseau des tn (par maille puis des mailles) (°C)"
                          },
                          "tx_moy": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Moyenne réseau des tx (°C)"
                          },
                          "n_stations": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de stations StatIC contribuant ce jour (transparence)"
                          },
                          "n_mailles": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre de départements couverts ce jour (représentativité)"
                          },
                          "ecart_type": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Écart-type inter-stations des tm (dispersion, transparence)"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "temps_ms": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/statIC/stations": {
      "get": {
        "summary": "Dataset statIC/stations",
        "description": "L'annuaire du réseau StatIC, triable par département : pour chaque station, tous les paramètres réellement mesurés et leur profondeur temporelle (première/dernière observation, volume). Grain : 1 ligne par (station, paramètre). Stations fermées incluses — les colonnes ouverte et derniere_obs permettent de filtrer. Dérivée de gold_ref (référentiel), refresh quotidien.\n\nAnnuaire du réseau, une ligne par station × paramètre, sans station ni from/to. format=csv accepté ; sans filtre, dump complet (référentiel borné). Référentiel NON plafonné, contrairement aux familles de série : pas de tronque, pas de suite (son CSV n'aurait nulle part où les porter).\n\nLicence : Données du réseau participatif StatIC (Infoclimat), Licence Ouverte (Etalab) 2.0 (cf. infoclimat.fr/opendata). Licence propre à trancher au besoin (gate CA). Attribution : Infoclimat / réseau StatIC.",
        "tags": [
          "statIC"
        ],
        "parameters": [
          {
            "name": "dep",
            "in": "query",
            "required": false,
            "description": "code département",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "parametre",
            "in": "query",
            "required": false,
            "description": "clé de paramètre (cf. /params) ; inconnue -> n=0, pas une erreur",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ouverte",
            "in": "query",
            "required": false,
            "description": "1 = stations ouvertes uniquement",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (défaut) ou csv",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "n",
                    "licence",
                    "attribution",
                    "stations"
                  ],
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "stations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Identifiant station StatIC (Infoclimat)"
                          },
                          "libelle": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Nom de la station"
                          },
                          "departement": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Département (code, ex. « 31 ») — null hors France"
                          },
                          "pays": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Code pays (ex. FR)"
                          },
                          "latitude": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "longitude": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "altitude": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Altitude (m)"
                          },
                          "ouverte": {
                            "type": [
                              "boolean",
                              "null"
                            ],
                            "description": "Station encore ouverte dans le référentiel"
                          },
                          "dh_ouverture": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                            "description": "Date d'ouverture de la station"
                          },
                          "parametre": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Paramètre mesuré (vocabulaire canonique, cf. /params)"
                          },
                          "premiere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
                            "description": "Première observation de ce paramètre sur cette station"
                          },
                          "derniere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
                            "description": "Dernière observation de ce paramètre sur cette station"
                          },
                          "n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre total d'observations de ce paramètre"
                          }
                        },
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/ref/stations": {
      "get": {
        "summary": "Dataset ref/station",
        "description": "Une ligne par station : identité, géolocalisation, réseau, état d'ouverture, paramètres mesurés (tableau) et date de dernière activité.\n\nRéférentiel NON plafonné, contrairement aux familles de série : pas de tronque, pas de suite. Filtre d'activité par défaut sur 365 j (actif_depuis), qui le borne davantage que le plafond ne le ferait.\n\nLicence : Référentiel multi-sources (réseau participatif StatIC Infoclimat + stations officielles Météo-France et autres producteurs), redistribué sous la politique opendata Infoclimat ; les métadonnées officielles restent sous la licence de leur producteur. Attribution : Infoclimat / réseau StatIC.",
        "tags": [
          "ref"
        ],
        "parameters": [
          {
            "name": "genre",
            "in": "query",
            "required": false,
            "description": "filtre genre de station",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type_poste",
            "in": "query",
            "required": false,
            "description": "filtre type de poste",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dep",
            "in": "query",
            "required": false,
            "description": "code département",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "parametre",
            "in": "query",
            "required": false,
            "description": "ne garder que les stations mesurant ce paramètre (clé de /params)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actif_depuis",
            "in": "query",
            "required": false,
            "description": "ne garder que les stations actives depuis cette date",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "ouverte",
            "in": "query",
            "required": false,
            "description": "1 = stations ouvertes uniquement",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          },
          {
            "name": "publiable",
            "in": "query",
            "required": false,
            "description": "0 = inclure aussi les stations sans aucune observation",
            "schema": {
              "type": "string",
              "enum": [
                "0"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (défaut) ou csv",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "FeatureCollection"
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer"
                    },
                    "features": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "const": "Feature"
                          },
                          "geometry": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "properties": {
                            "type": "object",
                            "properties": {
                              "ic_id": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "IDENTIFIANT CANONIQUE — celui qui fait foi. Hétérogène par conception : code OACI pour les metar (FMEE), indicatif OMM à 5 chiffres pour les synop (61980). Les stations StatIC n'ont AUCUNE forme unique (00006, STATIC0253, MNWERO090) : ne présumez d'aucun format, lisez la valeur."
                              },
                              "mfid": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "NUM_POSTE Météo-France — c'est le MÊME identifiant, pas un second système. null hors du périmètre Météo-France."
                              },
                              "station_uid": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "uuid5 dérivé de ic_id : pivot de jointure interne, PAS un identifiant plus stable que ic_id — il change si ic_id change."
                              },
                              "reseau": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "réseau d'appartenance, dérivé du genre. À ne pas confondre avec le ?reseau= de la Live API, qui filtre des sources d'observation.",
                                "enum": [
                                  "mf",
                                  "static",
                                  "mae",
                                  "metar",
                                  "synop",
                                  null
                                ]
                              },
                              "genre": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "type_poste": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "principale|secondaire — renseigné pour les seules stations Météo-France"
                              },
                              "libelle": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "libellé normalisé : le préfixe laissé par l'import CSV Météo-France (« TEST MF CSV3 … ») est retiré. Ces stations ne sont PAS des stations de test."
                              },
                              "libelle_source": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "description": "libellé brut du référentiel amont"
                              },
                              "latitude": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "longitude": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "altitude": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "departement": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "pays": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "ouverte": {
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "dh_ouverture": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date",
                                "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                              },
                              "publiable": {
                                "type": [
                                  "boolean",
                                  "null"
                                ],
                                "description": "false = aucune observation dans le fonds. Écartée par défaut ; publiable=0 rouvre la quarantaine."
                              },
                              "parametres_mesures": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "derniere_activite": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$"
                              },
                              "acces": {
                                "type": "object",
                                "description": "Indication de ROUTAGE : quel identifiant passer à quelle famille d'endpoints. La famille acceptera cette valeur ; ce n'est pas une garantie de présence de mesures (voir /ref/station-parametre pour cela). null = la famille ne sert pas cette station.",
                                "properties": {
                                  "v2": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "ic": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "legacy": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "dataclimat": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "statIC": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "ref": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                },
                                "additionalProperties": true
                              }
                            },
                            "additionalProperties": true
                          }
                        },
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/ref/station-parametre": {
      "get": {
        "summary": "Dataset ref/station_parametre",
        "description": "Pont station × paramètre : pour chaque paramètre observé par une station, première/dernière observation et volume. Fait autorité sur « quelles stations mesurent quoi ».\n\nLicence : Référentiel multi-sources (réseau participatif StatIC Infoclimat + stations officielles Météo-France et autres producteurs), redistribué sous la politique opendata Infoclimat ; les métadonnées officielles restent sous la licence de leur producteur. Attribution : Infoclimat / réseau StatIC.",
        "tags": [
          "ref"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "uid canonique ou ic_id",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "n": {
                      "type": "integer"
                    },
                    "parametres": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "station_uid": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "parametre": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Clé canonique du paramètre (vocabulaire dim_parametre)"
                          },
                          "premiere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$"
                          },
                          "derniere_obs": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$"
                          },
                          "n_obs": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Nombre d'observations du couple (station, paramètre)"
                          }
                        },
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Le processus répond",
        "description": "Toujours 200 tant que le service est en vie, y compris **pendant sa chauffe** — la sonde ne touche ni base ni catalogue, sans quoi elle tomberait avec eux et ne dirait plus rien du processus.\n\n`pret` distingue les deux états : `false` = démarrage en cours (les routes de données renvoient alors 503), `true` = service opérationnel. Pour savoir si le service peut SERVIR, c'est /ready qu'il faut interroger.",
        "tags": [
          "exploitation"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statut": {
                      "type": "string",
                      "enum": [
                        "ok"
                      ]
                    },
                    "service": {
                      "type": "string"
                    },
                    "pret": {
                      "type": "boolean"
                    },
                    "uptime_s": {
                      "type": "number"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/ready": {
      "get": {
        "summary": "Le service peut servir",
        "description": "200 quand le service peut répondre, **503 + `Retry-After` sinon** — pendant la chauffe du démarrage (~1,5 s) ou quand le pool DuckDB est saturé. Un client doit lire `Retry-After` plutôt que réessayer en boucle.\n\nLa réponse dit ce qui a été vérifié (`verifie`) **et ce qui ne l'a pas été** (`non_verifie`) : la joignabilité du catalogue Iceberg n'est pas testée, parce que les emplacements de métadonnées sont figés au démarrage (la tester ne dirait donc rien de ce qui est servi) et qu'un scan déclenché depuis une route publique sans clé serait un amplificateur.",
        "tags": [
          "exploitation"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pret": {
                      "type": "boolean"
                    },
                    "service": {
                      "type": "string"
                    },
                    "uptime_s": {
                      "type": "number"
                    },
                    "tables_catalogue": {
                      "type": "integer"
                    },
                    "verifie": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "non_verifie": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "raison": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "Service pas (encore) en état de servir : chauffe en cours, ou pool DuckDB saturé. Réessayer après le délai de Retry-After.",
            "headers": {
              "Retry-After": {
                "description": "Délai conseillé avant de réessayer, en secondes.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pret": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "raison": {
                      "type": "string"
                    },
                    "uptime_s": {
                      "type": "number"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/stations": {
      "get": {
        "summary": "Recherche de station",
        "description": "Résout un nom OU l'un des trois identifiants (ic_id, mfid, station_uid) en fiche station. Point de départ de tout usage de l'API.\n\nL'identifiant canonique est **ic_id** : c'est lui qui fait foi, et station_uid en est une dérivée déterministe (uuid5), donc pas un identifiant plus stable. mfid est le NUM_POSTE Météo-France — le même identifiant, pas un second système.\n\nL'objet renvoyé est IDENTIQUE à celui des properties de /ref/stations (aux alias dépréciés lat/lon près) : les deux endpoints lisent la même source. Le bloc `acces` dit quel identifiant passer à quelle famille.\n\nPas de filtre d'activité, contrairement à /ref/stations : une station fermée reste trouvable. Seule la quarantaine publiable s'applique.\n\nOrdre contractuel : correspondance exacte DESC, libelle ASC, ic_id ASC, station_uid ASC.",
        "tags": [
          "annuaire"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "nom (recherche partielle) ou identifiant exact : ic_id, mfid ou station_uid",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "publiable",
            "in": "query",
            "required": false,
            "description": "0 = inclure aussi les stations sans aucune observation",
            "schema": {
              "type": "string",
              "enum": [
                "0"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "stations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "IDENTIFIANT CANONIQUE — celui qui fait foi. Hétérogène par conception : code OACI pour les metar (FMEE), indicatif OMM à 5 chiffres pour les synop (61980). Les stations StatIC n'ont AUCUNE forme unique (00006, STATIC0253, MNWERO090) : ne présumez d'aucun format, lisez la valeur."
                          },
                          "mfid": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France — c'est le MÊME identifiant, pas un second système. null hors du périmètre Météo-France."
                          },
                          "station_uid": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "uuid5 dérivé de ic_id : pivot de jointure interne, PAS un identifiant plus stable que ic_id — il change si ic_id change."
                          },
                          "reseau": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "réseau d'appartenance, dérivé du genre. À ne pas confondre avec le ?reseau= de la Live API, qui filtre des sources d'observation.",
                            "enum": [
                              "mf",
                              "static",
                              "mae",
                              "metar",
                              "synop",
                              null
                            ]
                          },
                          "genre": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "type_poste": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "principale|secondaire — renseigné pour les seules stations Météo-France"
                          },
                          "libelle": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "libellé normalisé : le préfixe laissé par l'import CSV Météo-France (« TEST MF CSV3 … ») est retiré. Ces stations ne sont PAS des stations de test."
                          },
                          "libelle_source": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "libellé brut du référentiel amont"
                          },
                          "latitude": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "longitude": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "altitude": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "departement": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "pays": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "ouverte": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "dh_ouverture": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                          },
                          "publiable": {
                            "type": [
                              "boolean",
                              "null"
                            ],
                            "description": "false = aucune observation dans le fonds. Écartée par défaut ; publiable=0 rouvre la quarantaine."
                          },
                          "parametres_mesures": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "derniere_activite": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$"
                          },
                          "acces": {
                            "type": "object",
                            "description": "Indication de ROUTAGE : quel identifiant passer à quelle famille d'endpoints. La famille acceptera cette valeur ; ce n'est pas une garantie de présence de mesures (voir /ref/station-parametre pour cela). null = la famille ne sert pas cette station.",
                            "properties": {
                              "v2": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "ic": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "legacy": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "dataclimat": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "statIC": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "ref": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "additionalProperties": true
                          },
                          "lat": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "deprecated": true,
                            "description": "DÉPRÉCIÉ — alias de latitude, conservé le temps de la migration"
                          },
                          "lon": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "deprecated": true,
                            "description": "DÉPRÉCIÉ — alias de longitude, conservé le temps de la migration"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "q": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`schema-not-ready` — Station reference schema not ready · `service-warming-up` — Service warming up · `service-saturated` — Service saturated · `Retry-After` is present on `service-warming-up`, `service-saturated` only.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/coverage": {
      "get": {
        "summary": "Fraîcheur du fonds",
        "description": "Bornes temporelles réelles du fonds, archive et live. À interroger plutôt que de coder en dur une hypothèse de fraîcheur. Le bloc `serving` porte la date de résolution de l'instantané Iceberg réellement servi et son âge en secondes : un âge qui cesse d'osciller sous 5 min signale une boucle de rafraîchissement arrêtée.",
        "tags": [
          "annuaire"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`coverage-unavailable` — Coverage unavailable · `service-warming-up` — Service warming up · `Retry-After` is present on `service-warming-up` only.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/params": {
      "get": {
        "summary": "Vocabulaire des paramètres",
        "description": "Les 131 paramètres canoniques (clé, libellé, unité). Contrat de nommage : docs/vocabulaire-parametres-serving.md.",
        "tags": [
          "annuaire"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/ref/stations-legacy": {
      "get": {
        "summary": "Référentiel stations legacy",
        "description": "Tableau JSON nu de lignes plates, mêmes clés que stations_xhr.php (pas du GeoJSON — voir /ref/stations pour la variante GeoJSON). Hérite du filtre d'activité de _ref_rows (365 jours par défaut sur derniere_activite : ce n'est donc pas un dump complet ; désactivable avec un actif_depuis très ancien) et de tous ses autres filtres.\n\n**Famille de compatibilité : la notation des dates est celle de la source**, `YYYY-MM-DD HH:MM:SS` en UTC, et non le RFC 3339 des familles canoniques. L'instant désigné est le même que celui de /ref/stations, seule l'écriture change. Une station sans activité connue porte la sentinelle `0000-00-00 00:00:00` plutôt que `null`, comme le feed.\n\n**`perimetre=stations_xhr` : mode de PARITÉ.** Le périmètre et le code de licence viennent alors de la réplication versionnée du référentiel amont (`data/reference-licence-statIC.json`) : une station absente de la réplication est absente de la réponse, `licence` porte le code entier de la source, et le filtre d'activité ne s'applique plus — le périmètre du feed est décidé par la licence amont (contrat `static-stations-obs` : « filtre par défaut `licence IN (0,1,2)` »), jamais par une ancienneté. Les valeurs restent celles de `gold_ref.station`, vivantes : la réplication ne porte aucune mesure du feed, seulement l'appartenance et la licence. Sans réplication lisible, ce mode échoue en 503 plutôt que de se dégrader silencieusement.\n\n**Ce qui reste ouvert, et pourquoi.** `display_closed=1` répond **451** : la population que ce paramètre ajoute est celle que la source publie sous licence 3 (« CLOSED: NO REDISTRIBUTION ALLOWED »), plus celle dont la licence n'est pas renseignée en amont, que le contrat amont déclare exclue de l'opendata. Les servir serait redistribuer ce que la source interdit de redistribuer. Et même en mode de parité, les stations du feed absentes de `gold_ref.station` (31 sur 1 208 au relevé du 2026-08-08, soit 1 177 servies) restent sans ligne à servir. Pour ces deux points-là, interrogez le feed amont.",
        "tags": [
          "ref"
        ],
        "parameters": [
          {
            "name": "genre",
            "in": "query",
            "required": false,
            "description": "filtre genre de station",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type_poste",
            "in": "query",
            "required": false,
            "description": "filtre type de poste",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "dep",
            "in": "query",
            "required": false,
            "description": "code département",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "parametre",
            "in": "query",
            "required": false,
            "description": "ne garder que les stations mesurant ce paramètre (clé de /params)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "actif_depuis",
            "in": "query",
            "required": false,
            "description": "ne garder que les stations actives depuis cette date",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "ouverte",
            "in": "query",
            "required": false,
            "description": "1 = stations ouvertes uniquement",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          },
          {
            "name": "publiable",
            "in": "query",
            "required": false,
            "description": "0 = inclure aussi les stations sans aucune observation",
            "schema": {
              "type": "string",
              "enum": [
                "0"
              ]
            }
          },
          {
            "name": "perimetre",
            "in": "query",
            "required": false,
            "description": "stations_xhr = mode de parité : périmètre et code de licence adossés à la réplication du référentiel amont",
            "schema": {
              "type": "string",
              "enum": [
                "stations_xhr"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (défaut, tableau nu) ou geojson (vocabulaire geojson de la source, qui exige perimetre=stations_xhr : son objet `license` porte le code de licence amont)",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "geojson"
              ]
            }
          },
          {
            "name": "display_closed",
            "in": "query",
            "required": false,
            "description": "reconnu, et refusé en 451 : la source publie les stations fermées sous une licence qui en interdit la redistribution. `0` (le défaut de la source) est accepté et sans effet.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "libelle",
                          "departement",
                          "latitude",
                          "longitude",
                          "altitude",
                          "pays",
                          "genre",
                          "last_report",
                          "derniere_activite",
                          "licence"
                        ],
                        "properties": {
                          "id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "ic_id de la station — `id` dans le feed d'origine"
                          },
                          "libelle": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "departement": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "latitude": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "longitude": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "altitude": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "pays": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "genre": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "last_report": {
                            "type": "string",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
                            "description": "dernière remontée, notation de la source (`YYYY-MM-DD HH:MM:SS`, UTC) — PAS du RFC 3339, contrairement aux familles canoniques. Jamais null : une station sans activité connue porte la sentinelle `0000-00-00 00:00:00`, comme le feed d'origine."
                          },
                          "derniere_activite": {
                            "type": "string",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$",
                            "description": "redondante avec last_report — le feed publie les deux, avec la même valeur sur 1 208 lignes sur 1 208. Reproduit tel quel."
                          },
                          "licence": {
                            "type": [
                              "integer",
                              "string",
                              "null"
                            ],
                            "description": "DEUX FORMES, selon le mode. Avec `perimetre=stations_xhr` : le CODE ENTIER de la source (0 = Licence Ouverte Etalab, 1 = CC BY, 2 = CC BY-NC), lu dans la réplication versionnée du référentiel de licences amont — la forme qu'attend un client drop-in. SANS ce paramètre : une chaîne unique, parce que gold_ref.station ne porte aucune licence par station et qu'en inventer une serait pire. Le code 3 (« CLOSED: NO REDISTRIBUTION ALLOWED ») ne peut pas apparaître ici : ces stations ne sont jamais répliquées."
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "type",
                        "features"
                      ],
                      "properties": {
                        "type": {
                          "type": "string",
                          "const": "FeatureCollection"
                        },
                        "features": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "const": "Feature"
                              },
                              "geometry": {
                                "type": "object",
                                "additionalProperties": true
                              },
                              "properties": {
                                "type": "object",
                                "required": [
                                  "id",
                                  "name",
                                  "elevation",
                                  "license",
                                  "country",
                                  "departement",
                                  "last_activity"
                                ],
                                "properties": {
                                  "id": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "description": "ic_id de la station"
                                  },
                                  "name": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "description": "libellé — `name` dans le feed d'origine"
                                  },
                                  "elevation": {
                                    "type": [
                                      "number",
                                      "null"
                                    ],
                                    "description": "altitude en mètres — `elevation` dans le feed d'origine"
                                  },
                                  "license": {
                                    "type": "object",
                                    "required": [
                                      "code",
                                      "license",
                                      "url",
                                      "source"
                                    ],
                                    "description": "licence de la station, recomposée depuis la réplication versionnée du référentiel amont. `source` porte l'attribution et varie à code constant (le code 0 porte METEO-FRANCE et infoclimat.fr).",
                                    "properties": {
                                      "code": {
                                        "type": "integer",
                                        "enum": [
                                          0,
                                          1,
                                          2
                                        ]
                                      },
                                      "license": {
                                        "type": "string"
                                      },
                                      "url": {
                                        "type": "string"
                                      },
                                      "source": {
                                        "type": "string"
                                      }
                                    },
                                    "additionalProperties": true
                                  },
                                  "country": {
                                    "type": [
                                      "string",
                                      "null"
                                    ],
                                    "description": "code pays — `country` dans le feed d'origine"
                                  },
                                  "departement": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "last_activity": {
                                    "type": "string",
                                    "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
                                    "description": "MÊME instant que `last_report` du tableau nu, autre graphie : RFC 3339 ici, `YYYY-MM-DD HH:MM:SS` là-bas. Jamais null — une station sans activité connue porte `0000-00-00T00:00:00Z`, la sentinelle de la source sous cette graphie. Ce n'est pas une date valide, et c'est reproduit tel quel : le « corriger » servirait autre chose que la source."
                                  }
                                },
                                "additionalProperties": true
                              }
                            },
                            "additionalProperties": true
                          }
                        }
                      },
                      "additionalProperties": true
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "451": {
            "description": "`upstream-licence-restricted` — Upstream licence forbids redistribution",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`licence-reference-unavailable` — Upstream licence reference unavailable · `service-warming-up` — Service warming up · `service-saturated` — Service saturated · `Retry-After` is present on `service-warming-up`, `service-saturated` only.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/canicule/records": {
      "get": {
        "summary": "Records de chaleur d'un territoire",
        "description": "Records récents par département, commune ou EPCI. Un des filtres dep/insee/epci est requis. format=csv accepté.\n\nOrdre contractuel : record_date DESC, record_type ASC, station_code ASC, period_type ASC, period_value ASC.",
        "tags": [
          "canicule"
        ],
        "parameters": [
          {
            "name": "dep",
            "in": "query",
            "required": false,
            "description": "code département",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "insee",
            "in": "query",
            "required": false,
            "description": "code INSEE commune",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "epci",
            "in": "query",
            "required": false,
            "description": "code SIREN EPCI",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "nombre max de lignes (défaut 100, plafond 2000)",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (défaut) ou csv",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "records": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/canicule/saisons": {
      "get": {
        "summary": "Saisons disponibles",
        "description": "Années disponibles pour les indicateurs canicule, avec la saison par défaut.",
        "tags": [
          "canicule"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "saisons": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      }
                    },
                    "defaut": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/canicule/stations": {
      "get": {
        "summary": "Stations de la saison",
        "description": "Stations contribuant aux indicateurs canicule d'une année.",
        "tags": [
          "canicule"
        ],
        "parameters": [
          {
            "name": "annee",
            "in": "query",
            "required": false,
            "description": "année civile (défaut : saison la plus récente)",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "n": {
                      "type": "integer"
                    },
                    "stations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "annee": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/canicule/{niveau}/{code}": {
      "get": {
        "summary": "Indicateurs d'été extrême d'un territoire",
        "description": "Nuits tropicales, jours ≥ 30/35 °C, rang historique, couverture. mode=live renvoie les dernières Tn/Tx et streaks en cours. format=csv accepté.",
        "tags": [
          "canicule"
        ],
        "parameters": [
          {
            "name": "niveau",
            "in": "path",
            "required": true,
            "description": "échelon territorial",
            "schema": {
              "type": "string",
              "enum": [
                "commune",
                "epci",
                "departement"
              ]
            }
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "code INSEE (commune), SIREN (epci) ou numéro de département",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "annee",
            "in": "query",
            "required": false,
            "description": "saison (défaut : plus récente)",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "description": "saison (défaut) ou live",
            "schema": {
              "type": "string",
              "enum": [
                "saison",
                "live"
              ]
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "json (défaut) ou csv",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "`territory-not-found` — Territory not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/qc/pic_temperature": {
      "get": {
        "summary": "Les observations écartées par le contrôle qualité",
        "description": "La liste **nominative** des observations de température que le contrôle qualité écarte des agrégats journaliers : une valeur isolée au milieu de voisins normaux, comme un 0 °C un 9 mai à La Réunion.\n\nElle est publiée pour que le correctif soit **réfutable** : un rejet qu'on ne peut pas relire est une homogénéisation qui ne dit pas son nom. Si vous pensez qu'une valeur a été écartée à tort, elle est ici, avec la marge (`profondeur`) par laquelle elle a franchi le seuil.\n\nLe test : une observation dont les **deux** voisins temporels immédiats (≤ 6 h, même station, même source) s'écartent de plus de `seuil` degrés **dans le même sens**. Exiger les deux voisins dans le même sens est ce qui distingue un pic d'une variation monotone — un réchauffement diurne n'est jamais rejeté.\n\n**Une seconde condition, indispensable.** La forme ne suffit pas : une station dont la série se bloque à une valeur constante produit des « pics » qui sont en réalité ses VRAIES mesures. Un rejet exige donc aussi que la valeur soit hors de la climatologie propre de la station pour ce mois **et cette heure** — hors de `[q01 − marge, q99 + marge]`, quantiles calculés sur tout son historique. C'est ce qui sépare un 0 °C un 9 mai à La Réunion, impossible, d'un 32 °C un après-midi de décembre en Thaïlande, banal : les deux ont la même forme, pas la même climatologie.\n\nConséquence assumée : sur une station dont la série est corrompue de part en part, sa propre climatologie ne condamne plus rien et le filtre ne rejette rien. Ces séries relèvent d'un diagnostic station par station — mieux vaut les signaler que prétendre les réparer.\n\nDeuxième cas d'abstention, distinct du premier : une cellule (station, mois, heure) de moins de 100 observations ne produit aucun rejet, faute de climatologie fiable pour trancher. Une station récente, ou peu de mesures à une heure donnée, échappe donc au filtre. Deux raisons différentes, donc, pour lesquelles une valeur que vous jugez suspecte peut ne pas figurer ici — l'absence d'une observation dans cette table ne vaut pas certificat de validité.\n\n**Troisième cas, le plus important à connaître : l'archive ancienne n'est pas filtrée.** Le test exige deux voisins à moins de 6 h. Avant le passage à la cadence horaire (vers 1996 selon les stations), les séries sont synoptiques — 2 à 3 observations par jour, espacées de 6 à 12 h — et la condition n'est alors structurellement jamais remplie. Mesuré sur une station de référence : 100 % des observations d'avant 1954 et jusqu'à un tiers de celles des années 1973-1995 n'ont aucun voisin dans la fenêtre, contre 0,0 à 0,4 % après 1996.\n\nConséquence directe : **un record mensuel ou absolu établi sur l'archive ancienne n'a pas traversé ce filtre**, et peut porter une valeur aberrante que les séries récentes, elles, ne porteraient plus. Élargir la fenêtre pour couvrir cette cadence affaiblirait le critère d'isolement partout ailleurs — le choix assumé est de filtrer correctement là où c'est possible plutôt qu'approximativement partout.\n\nLe filtre est sélectif : 183 958 rejets pour 2 081 075 candidats testés par la garde climatologique, soit 91,2 % écartés. Un rejet publié ici n'est donc pas un hasard de bord de seuil, c'est ce qui reste après un tri déjà très strict.\n\nLimite connue : `ic_id` et `mfid` sont `null` pour environ 11 % des lignes (stations absentes du référentiel `gold_ref.station`, une lacune préexistante de ce référentiel, pas un défaut de ce filtre). `station_uid` reste renseigné dans tous les cas et permet la jointure interne.\n\nCes bornes-ci ne remplacent pas les bornes **physiques** [-90, +60] °C, qui restent appliquées en amont : 0 °C est à l'intérieur des bornes physiques, c'est bien son isolement qui le trahit, pas sa valeur.\n\nOrdre contractuel : dh_utc ASC, station_uid ASC, source ASC.\n\nStation resolution: an identifier absent from the canonical reference (published aliases included) returns 404 `station-not-found`. A canonical station with no observations in the requested window returns 200 with `n = 0`. A missing or blank `station` returns 400 `missing-parameter`; identifiers quarantined or classified outside the reference are not promoted to canonical stations.",
        "tags": [
          "qc"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "identifiant de station : ic_id (ex. 07486) ou mfid (ex. 38384001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "début de plage (YYYY-MM-DD, inclus, sur l'horodatage d'observation)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "fin de plage (YYYY-MM-DD, exclu, sur l'horodatage d'observation)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "station": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "licence": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "n": {
                      "type": "integer"
                    },
                    "mesures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "station_uid": {
                            "type": "string",
                            "description": "identifiant interne opaque"
                          },
                          "ic_id": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "identifiant station Infoclimat ; null si la station est absente du référentiel gold_ref.station"
                          },
                          "mfid": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "NUM_POSTE Météo-France si connu ; peut être null pour la même raison que ic_id"
                          },
                          "source": {
                            "type": "string",
                            "description": "source de l'observation écartée"
                          },
                          "dh_utc": {
                            "type": "string",
                            "format": "date-time",
                            "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$",
                            "description": "horodatage de l'observation écartée (RFC 3339 UTC)"
                          },
                          "valeur_degC": {
                            "type": "number",
                            "description": "la valeur écartée (°C)"
                          },
                          "profondeur": {
                            "type": "number",
                            "description": "écart au voisin le plus proche (°C) — la marge par laquelle le rejet a franchi le seuil"
                          },
                          "seuil": {
                            "type": "number",
                            "description": "seuil appliqué au build (°C)"
                          },
                          "marge": {
                            "type": "number",
                            "description": "tolérance (°C) ajoutée aux quantiles climatologiques (q01/q99) de la station pour ce mois et cette heure"
                          }
                        },
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `dataset-not-found` — Dataset not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/last": {
      "get": {
        "summary": "Dernières valeurs d'une station",
        "description": "Dernière valeur connue par station × paramètre × durée. Renvoie le canonique SI : températures en kelvin, pressions en pascals (contrairement aux familles Gold, converties en °C/hPa/mm). /params donne l'unité de chaque clé. Token Bearer délivré sur demande.",
        "tags": [
          "live (token)"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "identifiant de station : ic_id (ex. 07486) ou mfid (ex. 38384001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "param",
            "in": "query",
            "required": false,
            "description": "clé de paramètre canonique (cf. /params)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reseau",
            "in": "query",
            "required": false,
            "description": "filtre réseau",
            "schema": {
              "type": "string",
              "enum": [
                "mf",
                "ic",
                "static",
                "synop",
                "metar",
                "bouees"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`no-current-value` — No current value · `route-not-found` — Route not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "servers": [
          {
            "url": "https://live.chom.engineering",
            "description": "API live (token)"
          }
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      }
    },
    "/series": {
      "get": {
        "summary": "Série brute au pas de mesure",
        "description": "Série brute sur le fonds canonique complet. Renvoie le canonique SI : températures en kelvin, pressions en pascals (contrairement aux familles Gold, converties en °C/hPa/mm). /params donne l'unité de chaque clé. Token Bearer délivré sur demande.",
        "tags": [
          "live (token)"
        ],
        "parameters": [
          {
            "name": "station",
            "in": "query",
            "required": true,
            "description": "identifiant de station : ic_id (ex. 07486) ou mfid (ex. 38384001)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "param",
            "in": "query",
            "required": true,
            "description": "clé de paramètre canonique (cf. /params)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "description": "début de plage (YYYY-MM-DD, inclus)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "fin de plage (YYYY-MM-DD, exclu)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "reseau",
            "in": "query",
            "required": false,
            "description": "filtre réseau",
            "schema": {
              "type": "string",
              "enum": [
                "mf",
                "ic",
                "static",
                "synop",
                "metar",
                "bouees"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`missing-parameter` — Missing parameter · `invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`station-not-found` — Station not found · `route-not-found` — Route not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal-error` — Internal error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-saturated` — Service saturated",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. `details.retry_after_s` repeats the value in the body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "servers": [
          {
            "url": "https://archive.chom.engineering",
            "description": "API archive brute (token)"
          }
        ],
        "security": [
          {
            "bearer": []
          }
        ]
      }
    },
    "/weather-ai/runs": {
      "get": {
        "summary": "Runs historiques Weather AI",
        "description": "Index des runs historiques immuables disponibles sur les 30 derniers jours.",
        "tags": [
          "weather-ai"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "famille",
                    "experimental",
                    "autorite_alerte",
                    "schema_version",
                    "window_start",
                    "window_end",
                    "n",
                    "oldest_available_published_at",
                    "newest_available_published_at",
                    "runs"
                  ],
                  "properties": {
                    "famille": {
                      "const": "weather-ai-experimental"
                    },
                    "experimental": {
                      "const": true
                    },
                    "autorite_alerte": {
                      "const": false
                    },
                    "schema_version": {
                      "const": "weather-ai-runs/1.0.0"
                    },
                    "window_start": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "window_end": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "n": {
                      "type": "integer"
                    },
                    "oldest_available_published_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "newest_available_published_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "runs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "502": {
            "description": "`weather-ai-history-invalid` — Weather AI history invalid",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `weather-ai-history-unavailable` — Weather AI history unavailable · `Retry-After` is present on `service-warming-up` only.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/weather-ai/products": {
      "get": {
        "summary": "Catalogue Weather AI",
        "description": "Catalogue live validé, ou catalogue immuable du run historique demandé.",
        "tags": [
          "weather-ai"
        ],
        "parameters": [
          {
            "name": "run_id",
            "in": "query",
            "required": false,
            "description": "identifiant opaque d’un run historique immuable ; absent = catalogue live",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "catalog_id",
                    "catalog_uri",
                    "catalog_version_id",
                    "catalog_sha256",
                    "run_id",
                    "run_date",
                    "published_at",
                    "n",
                    "produits",
                    "experimental",
                    "famille",
                    "autorite_alerte"
                  ],
                  "properties": {
                    "famille": {
                      "const": "weather-ai-experimental"
                    },
                    "experimental": {
                      "const": true
                    },
                    "autorite_alerte": {
                      "const": false
                    },
                    "catalog_id": {
                      "type": "string"
                    },
                    "catalog_uri": {
                      "type": "string",
                      "format": "uri"
                    },
                    "catalog_version_id": {
                      "type": "string"
                    },
                    "catalog_sha256": {
                      "type": "string",
                      "pattern": "^[0-9a-f]{64}$"
                    },
                    "run_id": {
                      "type": "string"
                    },
                    "run_date": {
                      "type": "string",
                      "format": "date"
                    },
                    "published_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "n": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "produits": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "product_id",
                          "run_id",
                          "valid_time",
                          "snapshot_id",
                          "experimental",
                          "famille",
                          "autorite_alerte"
                        ],
                        "properties": {
                          "product_id": {
                            "type": "string",
                            "enum": [
                              "global-mslp-1deg",
                              "global-cyclone-existence-1deg",
                              "global-cyclone-tracks-1deg"
                            ]
                          },
                          "run_id": {
                            "type": "string"
                          },
                          "valid_time": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "uri": {
                            "type": "string",
                            "format": "uri"
                          },
                          "sha256": {
                            "type": "string",
                            "pattern": "^[0-9a-f]{64}$"
                          },
                          "snapshot_id": {
                            "type": "string"
                          },
                          "lineage_uri": {
                            "type": "string",
                            "format": "uri"
                          },
                          "license_notice": {
                            "type": "string"
                          },
                          "attribution": {
                            "type": "string"
                          },
                          "famille": {
                            "const": "weather-ai-experimental"
                          },
                          "experimental": {
                            "const": true
                          },
                          "autorite_alerte": {
                            "const": false
                          }
                        },
                        "additionalProperties": false
                      }
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "`invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`weather-ai-history-run-not-found` — Weather AI historical run not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`weather-ai-history-invalid` — Weather AI history invalid",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `weather-ai-catalog-unavailable` — Weather AI catalog unavailable · `weather-ai-history-unavailable` — Weather AI history unavailable · `Retry-After` is present on `service-warming-up` only.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/weather-ai/products/{product_id}": {
      "get": {
        "summary": "Première frame d’un produit Weather AI",
        "description": "Métadonnée de la première frame chronologique de la famille sélectionnée.",
        "tags": [
          "weather-ai"
        ],
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "required": true,
            "description": "famille de produit annoncée par le catalogue validé",
            "schema": {
              "type": "string",
              "enum": [
                "global-mslp-1deg",
                "global-cyclone-existence-1deg",
                "global-cyclone-tracks-1deg"
              ]
            }
          },
          {
            "name": "run_id",
            "in": "query",
            "required": false,
            "description": "identifiant opaque d’un run historique immuable ; absent = catalogue live",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "product_id",
                    "run_id",
                    "valid_time",
                    "snapshot_id",
                    "experimental",
                    "famille",
                    "autorite_alerte"
                  ],
                  "properties": {
                    "product_id": {
                      "type": "string",
                      "enum": [
                        "global-mslp-1deg",
                        "global-cyclone-existence-1deg",
                        "global-cyclone-tracks-1deg"
                      ]
                    },
                    "run_id": {
                      "type": "string"
                    },
                    "valid_time": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "uri": {
                      "type": "string",
                      "format": "uri"
                    },
                    "sha256": {
                      "type": "string",
                      "pattern": "^[0-9a-f]{64}$"
                    },
                    "snapshot_id": {
                      "type": "string"
                    },
                    "lineage_uri": {
                      "type": "string",
                      "format": "uri"
                    },
                    "license_notice": {
                      "type": "string"
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "famille": {
                      "const": "weather-ai-experimental"
                    },
                    "experimental": {
                      "const": true
                    },
                    "autorite_alerte": {
                      "const": false
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "`invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`weather-ai-history-run-not-found` — Weather AI historical run not found · `weather-ai-product-not-found` — Weather AI product not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`weather-ai-history-invalid` — Weather AI history invalid · `weather-ai-product-invalid` — Weather AI product invalid",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `weather-ai-catalog-unavailable` — Weather AI catalog unavailable · `weather-ai-history-unavailable` — Weather AI history unavailable · `Retry-After` is present on `service-warming-up` only.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/weather-ai/products/{product_id}/timeline": {
      "get": {
        "summary": "Timeline d’un produit Weather AI",
        "description": "Frames ordonnées d’une famille pour un unique run et snapshot.",
        "tags": [
          "weather-ai"
        ],
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "required": true,
            "description": "famille de produit annoncée par le catalogue validé",
            "schema": {
              "type": "string",
              "enum": [
                "global-mslp-1deg",
                "global-cyclone-existence-1deg",
                "global-cyclone-tracks-1deg"
              ]
            }
          },
          {
            "name": "run_id",
            "in": "query",
            "required": false,
            "description": "identifiant opaque d’un run historique immuable ; absent = catalogue live",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "product_id",
                    "run_id",
                    "snapshot_id",
                    "frames",
                    "experimental",
                    "famille",
                    "autorite_alerte"
                  ],
                  "properties": {
                    "famille": {
                      "const": "weather-ai-experimental"
                    },
                    "experimental": {
                      "const": true
                    },
                    "autorite_alerte": {
                      "const": false
                    },
                    "product_id": {
                      "type": "string",
                      "enum": [
                        "global-mslp-1deg",
                        "global-cyclone-existence-1deg",
                        "global-cyclone-tracks-1deg"
                      ]
                    },
                    "run_id": {
                      "type": "string"
                    },
                    "snapshot_id": {
                      "type": "string"
                    },
                    "frames": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "product_id",
                          "run_id",
                          "valid_time",
                          "snapshot_id",
                          "experimental",
                          "famille",
                          "autorite_alerte"
                        ],
                        "properties": {
                          "product_id": {
                            "type": "string",
                            "enum": [
                              "global-mslp-1deg",
                              "global-cyclone-existence-1deg",
                              "global-cyclone-tracks-1deg"
                            ]
                          },
                          "run_id": {
                            "type": "string"
                          },
                          "valid_time": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "uri": {
                            "type": "string",
                            "format": "uri"
                          },
                          "sha256": {
                            "type": "string",
                            "pattern": "^[0-9a-f]{64}$"
                          },
                          "snapshot_id": {
                            "type": "string"
                          },
                          "lineage_uri": {
                            "type": "string",
                            "format": "uri"
                          },
                          "license_notice": {
                            "type": "string"
                          },
                          "attribution": {
                            "type": "string"
                          },
                          "famille": {
                            "const": "weather-ai-experimental"
                          },
                          "experimental": {
                            "const": true
                          },
                          "autorite_alerte": {
                            "const": false
                          }
                        },
                        "additionalProperties": false
                      }
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "`invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`weather-ai-history-run-not-found` — Weather AI historical run not found · `weather-ai-product-not-found` — Weather AI product not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`weather-ai-history-invalid` — Weather AI history invalid · `weather-ai-product-invalid` — Weather AI product invalid",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `weather-ai-catalog-unavailable` — Weather AI catalog unavailable · `weather-ai-history-unavailable` — Weather AI history unavailable · `Retry-After` is present on `service-warming-up` only.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/weather-ai/products/{product_id}/data": {
      "get": {
        "summary": "Corps validé d’un produit Weather AI",
        "description": "Retourne le corps validé de la frame demandée ; les trajectoires candidates peuvent être vides.",
        "tags": [
          "weather-ai"
        ],
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "required": true,
            "description": "famille de produit annoncée par le catalogue validé",
            "schema": {
              "type": "string",
              "enum": [
                "global-mslp-1deg",
                "global-cyclone-existence-1deg",
                "global-cyclone-tracks-1deg"
              ]
            }
          },
          {
            "name": "run_id",
            "in": "query",
            "required": false,
            "description": "identifiant opaque d’un run historique immuable ; absent = catalogue live",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "valid_time",
            "in": "query",
            "required": false,
            "description": "instant RFC 3339 de la frame ; absent = première frame chronologique",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Corps produit limité à 16 MiB après lecture. Données expérimentales, sans aucune autorité d'alerte.",
                  "required": [
                    "famille",
                    "experimental",
                    "autorite_alerte",
                    "attribution",
                    "license_notice",
                    "product"
                  ],
                  "properties": {
                    "famille": {
                      "const": "weather-ai-experimental"
                    },
                    "experimental": {
                      "const": true
                    },
                    "autorite_alerte": {
                      "const": false
                    },
                    "attribution": {
                      "type": "string"
                    },
                    "license_notice": {
                      "type": "string"
                    },
                    "product": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/WeatherAiGridProduct"
                        },
                        {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/WeatherAiCycloneTracksProduct"
                            }
                          ],
                          "description": "Trajectoires candidates : aucune probabilité, cône ou association à une tempête observée."
                        }
                      ]
                    }
                  },
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "`invalid-parameter` — Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`weather-ai-history-run-not-found` — Weather AI historical run not found · `weather-ai-product-not-found` — Weather AI product not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`weather-ai-history-invalid` — Weather AI history invalid · `weather-ai-product-invalid` — Weather AI product invalid · `weather-ai-product-integrity-failed` — Weather AI product integrity failed",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`service-warming-up` — Service warming up · `weather-ai-catalog-unavailable` — Weather AI catalog unavailable · `weather-ai-history-unavailable` — Weather AI history unavailable · `weather-ai-product-unavailable` — Weather AI product unavailable · `Retry-After` is present on `service-warming-up` only.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  }
}