{
  "openapi": "3.1.0",
  "info": {
    "title": "Metmaps Weather API",
    "version": "1.4.0",
    "description": "Professional weather data API: numerical model point forecasts and worldwide surface observations.\n\n## Authentication\n\nEvery request needs your API key, preferably as a header:\n\n```\nAuthorization: Bearer <your-api-key>\n```\n\n(`?apikey=<key>` is accepted as a fallback for quick tests.) Keys are issued per subscription; contact **info@metmaps.de** for a trial key or plan.\n\n## Plans & quotas\n\n| Plan | Price | Requests | Products |\n|---|---|---|---|\n| Trial | free, 14 days | 1,000 / day | all 36 models |\n| Starter | EUR 39 / month | 150,000 / month | 5 core global models |\n| Pro | EUR 149 / month | 1,000,000 / month | all 24 deterministic models + observations + radar (7-day reach-back) |\n| Business | EUR 399 / month | 5,000,000 / month | all 36 models incl. 12 ensembles + observations + radar (30-day reach-back) + ERA5 history since 1940, priority support |\n| Enterprise | custom | custom | redistribution rights, SLA, deep observation archive, custom limits |\n\n1 request = 1 call, regardless of endpoint. Every key additionally carries an hourly burst cap.\n\nMonthly-metered plans get quota headers on every response: `X-Quota-Limit`, `X-Quota-Used`, `X-Quota-Reset`. From 80% usage an `X-Quota-Warning` header is added; a 10% grace allowance applies beyond the quota, after which requests are rejected with `429` and a `Retry-After` header until the monthly reset (1st of month, 00:00 UTC). Hourly and daily limits likewise answer `429` with `Retry-After`. An expired trial or lapsed subscription answers `403 key_expired`.\n\n## Model catalog\n\n**36 numerical weather models, individually selectable** \u2014 deterministic and ensemble, physical and AI, from ten national/international centres. No black-box blend: you pick the model, we tell you the run. `GET /v1/models` returns the live catalog with retrievable runs for your plan; the public `GET /v1/catalog` lists coverage area and parameter set per model \u2014 on this page, click any model slug below to see them.\n\n**Global deterministic**\n\n| Model | slug | Resolution | From plan |\n|---|---|---|---|\n| ECMWF IFS | `ecmwf-ifs` | 0.25\u00b0 | Pro |\n| ECMWF AIFS (AI) | `ecmwf-aifs` | 0.25\u00b0 | Pro |\n| DWD ICON | `icon` | 0.125\u00b0 | Starter |\n| NOAA GFS | `gfs` | 0.125\u00b0 | Starter |\n| M\u00e9t\u00e9o-France ARPEGE | `arpege` | 0.25\u00b0 | Starter |\n| ECCC GEM | `gem` | 0.15\u00b0 | Starter |\n| CMA-GFS | `cma-gfs` | 0.125\u00b0 | Pro |\n| NOAA AIGFS (AI) | `aigfs` | 0.25\u00b0 | Pro |\n| GraphCast / Pangu-Weather (AI, NOAA MLWP) | `graphcast` `pangu` | 0.25\u00b0 | Pro |\n| FourCastNet / Aurora (AI, NOAA MLWP) | `fourcastnet` `aurora` | 0.25\u00b0 | Pro |\n\n**Regional & high-resolution**\n\n| Model | slug | Resolution | From plan |\n|---|---|---|---|\n| DWD ICON-EU | `icon-eu` | 0.0625\u00b0 | Starter |\n| DWD ICON-D2 (D-A-CH) | `icon-d2` | 0.02\u00b0 (~2 km) | Pro |\n| ICON-2I (Italy) | `icon-2i` | 0.025\u00b0 | Pro |\n| MeteoSwiss ICON-CH1 / ICON-CH2 (Alps) | `icon-ch1` `icon-ch2` | ~1 km / ~2 km | Pro |\n| ARPEGE Europe | `arpege-eu` | 0.1\u00b0 | Pro |\n| M\u00e9t\u00e9o-France AROME | `arome` | 0.01\u00b0 (~1 km) | Pro |\n| NOAA NAM / HRRR (North America) | `nam` `hrrr` | ~3 km | Pro |\n| HARMONIE (DMI, northern Europe) | `harmonie-dmi` | 0.024\u00b0 | Pro |\n| GeoSphere Austria NWP (Alps) | `geosphere-at` | ~2.5 km | Pro |\n| BOLAM (ItaliaMeteo) | `bolam` | 0.075\u00b0 | Pro |\n\n**Ensemble systems** (Business plan)\n\n| Ensemble | slug | Resolution | Members |\n|---|---|---|---|\n| ECMWF ENS | `ecmwf-ens` | 0.25\u00b0 | 51 |\n| ECMWF AIFS-ENS (AI) | `ecmwf-aifs-ens` | 0.25\u00b0 | 50 |\n| NOAA GEFS | `gefs` | 0.25\u00b0 | 31 |\n| NOAA AI-GEFS (AI) | `aigefs` | 0.25\u00b0 | 31 |\n| DWD ICON-EPS / ICON-EU-EPS / ICON-D2-EPS | `icon-eps` `icon-eu-eps` `icon-d2-eps` | 0.25\u00b0 / 0.125\u00b0 / 0.02\u00b0 | 40 / 40 / 20 |\n| MeteoSwiss ICON-CH1-EPS / ICON-CH2-EPS | `icon-ch1-eps` `icon-ch2-eps` | ~1 km / ~2 km | 10 / 20 |\n| M\u00e9t\u00e9o-France AROME-EPS | `arome-eps` | 0.025\u00b0 | 25 |\n| ARPEGE-EPS global / Europe | `arpege-eps` `arpege-eu-eps` | 0.25\u00b0 / 0.1\u00b0 | 35 |\n\n**Reanalysis archive** (Business plan) \u2014 model data for the past, hourly/3-hourly back to 1940:\n\n| Model | slug | Resolution | Archive |\n|---|---|---|---|\n| ERA5 Europe (ECMWF/Copernicus) | `era5-eu` | 0.25\u00b0 | since 1940 |\n| ERA5 USA (ECMWF/Copernicus) | `era5-us` | 0.25\u00b0 | since 1980 |\n\nERA5 compensates for the short model-run retention: where forecast models only keep their most recent runs, the reanalysis serves the observed past as gridded model data \u2014 same point endpoint, same parameter codes. `from` and `to` are required (there is no run), analyses are 3-hourly with hourly precipitation/snowfall (`RR1h`, `SF1h`), and one call is limited to 13 container-months (one data container = one parameter-group for one month) \u2014 e.g. all parameters for one month, or a single parameter for a year. Page longer histories with multiple calls. Snow fields are water equivalents: `SWE` (snow cover) and `SF1h` (snowfall), both mm.\n\nEnsemble point responses return the ensemble mean under the plain parameter code (e.g. `TL`) plus `_med`, `_p10`, `_p90`, `_min`, `_max` spread keys and the precipitation probability `PROB_RR` \u2014 see *Model parameters* below.\n\n## Time\n\nAll times are **UTC, ISO 8601** (`2026-07-04T06:00Z`), both in requests and responses. A bare date (`2026-07-04`) means midnight UTC.\n\n## Units\n\nDefaults are metric. Four request parameters switch unit systems per quantity; everything else is fixed. The `meta.units` object of every response states the unit per parameter, so responses are always self-describing.\n\n| Request parameter | Options (default first) | Applies to |\n|---|---|---|\n| `temperature_unit` | `c`, `f` | all temperatures |\n| `wind_unit` | `kmh`, `ms`, `kt`, `mph` | wind speed and gusts |\n| `pressure_unit` | `hpa`, `inhg` | all pressures |\n| `precipitation_unit` | `mm`, `in` | precipitation; also snow depth (cm\u2192in) and visibility (km\u2192mi) |\n\nFixed units: radiation W/m2, sunshine minutes, cloud amounts okta, direction degrees, ceiling metres.\n\n## Parameter vocabulary\n\nAll parameter codes are **period-explicit**: the code tells you exactly what time window a value covers. Select a subset with `parameters=TL,FF,RR1h` (comma-separated); omit for all available.\n\n### Model parameters\n\n| Code | Description |\n|---|---|\n| `TL` `TD` `RH` | 2 m temperature, dew point, relative humidity |\n| `TX` / `TN` | max / min 2 m temperature over a recent window \u2014 model-dependent: since the previous output step (e.g. ECMWF) or since the last synoptic reset at 00/06/12/18 UTC (e.g. ICON family, GFS) |\n| `FF` `DIR` | 10 m wind speed and direction |\n| `FF100` | 100 m wind speed |\n| `G1h` | 10 m wind gust since the previous output step |\n| `QFF` | mean-sea-level pressure |\n| `RR1h` | precipitation since the previous output step (`RR1h_hours` gives the actual step width) |\n| `RR6h` `RR12h` `RR24h` | precipitation totals over the named window (availability model-dependent) |\n| `NL` `NM` `NH` | low / medium / high cloud cover, okta |\n| `SNO` | snow depth |\n| `VIS` | visibility |\n| `www` | significant weather code |\n| `Sh` | sunshine minutes per step (`Sh_hours` = step width) |\n| `GHI` `DNI` `DHI` | global / direct / diffuse irradiance, mean W/m2 per step (`GHI_hours` = step width) |\n| `GHI24h` `DNI24h` `DHI24h` | global / direct / diffuse irradiance, mean W/m2 over the past 24 h (ensemble systems) |\n| `PROB_RR` | ensemble precipitation probability, % (ensemble models only) |\n| `CAPE` | convective available potential energy, J/kg (model-dependent) |\n| `TCWV` | total column water vapour, kg/m2 (ensemble models, ERA5) |\n| `SWE` | snow water equivalent of the snow cover, mm (ERA5) |\n| `SF1h` | snowfall, mm water equivalent, past 1 h (ERA5) |\n\nEnsemble models additionally return spread keys per parameter: `_med`, `_p10`, `_p90`, `_min`, `_max` (e.g. `TL_p90`).\n\n### Observation parameters\n\n| Code | Description | Window |\n|---|---|---|\n| `TL` | air temperature 2 m | instantaneous |\n| `TD` | dew point 2 m | instantaneous |\n| `RH` | relative humidity (derived from TL+TD) | instantaneous |\n| `TW` | water temperature | instantaneous |\n| `TX1h` / `TN1h` | max / min temperature | past 1 h |\n| `TX6h` / `TN6h` | max / min temperature | past 6 h |\n| `TX12h` / `TN12h` | max / min temperature (synoptic reports at 05/06 and 17/18 UTC) | past 12 h |\n| `TN5cm` | minimum temperature 5 cm above ground | night/synoptic |\n| `DIR` | wind direction | 10-min mean |\n| `FF` | wind speed | 10-min mean |\n| `G10m` | wind gust | past 10 min |\n| `G1h` | wind gust | past 1 h |\n| `QFF` | mean-sea-level pressure (see note below) | instantaneous |\n| `QFE` | station-level pressure | instantaneous |\n| `QNH` | altimeter setting | instantaneous |\n| `GP925` / `GP850` / `GP700` | geopotential height of the 925/850/700 hPa surface, gpm (mountain stations, see note below) | instantaneous |\n| `RR10m` `RR1h` `RR3h` `RR6h` `RR12h` `RR24h` | precipitation total | named window |\n| `SNO` | total snow depth | instantaneous |\n| `VIS` | horizontal visibility | instantaneous |\n| `CLG` | cloud ceiling | instantaneous |\n| `N` | total cloud cover, okta (9 = sky obscured) | instantaneous |\n| `Nh` | amount of low clouds (or middle, if no low clouds), okta | instantaneous |\n| `CL` / `CM` / `CH` | low / middle / high cloud type, WMO code tables 0513 / 0515 / 0509 (SYNOP-reporting stations) | instantaneous |\n| `www` | present weather, WMO code table 4677 | instantaneous |\n| `Sh10m` / `Sh1h` / `Sh24h` | sunshine duration, minutes | named window |\n| `GHI1h` / `DHI1h` | global / diffuse solar irradiance, mean W/m2 | past 1 h |\n| `GHI24h` / `DHI24h` | global / diffuse solar irradiance, mean W/m2 | past 24 h |\n\n**Notes on observation data**\n\n- Parameters a station did not report are simply absent from the response \u2014 there are no null placeholders.\n- **`QFF` and mountain stations:** high-elevation stations do not reduce their pressure to sea level; they transmit the geopotential height of a standard pressure surface (925/850/700 hPa) in the same report field instead. The API separates the two: genuine sea-level pressures appear as `QFF`, the heights appear as `GP925`/`GP850`/`GP700` (whichever surface the station reports). A mountain station therefore has no `QFF` \u2014 use `QFE` for its pressure and `GPxxx` for its height report.\n- Precipitation reported over non-standard periods (2/9/15/18 h totals from some networks) is not mapped to any `RRxh` code and is omitted rather than mislabelled.\n- In area snapshots the per-station observation time is the actual report time (stations report at mixed cadences). Without `time=`, the snapshot merges the most recent three hours and returns each station's newest report \u2014 so 3-hourly synoptic networks stay present right after the top of the hour. With an explicit `time=`, only that hour's reports are used.\n\n## Radar\n\nEuropean precipitation radar, one product: the pan-European composite (`aeu`) \u2014 the EUMETNET **OPERA** composite with the Italian national radar mosaic (Protezione Civile DPC) layered in south of 45.7\u00b0N, where OPERA has a structural coverage gap. Coverage \u221230..40\u00b0E / 34..74\u00b0N, **5-minute frames**, ~1 km native resolution.\n\n- `GET /radar/composite` \u2014 rendered PNG map section for a `bbox`, optionally at a historical `time`. `style=palette` (default) gives the coloured dBZ palette on a transparent background; `style=raw` gives the underlying **grey-value PNG** for machine reading \u2014 each pixel value encodes dBZ (`dBZ = (value \u2212 2) / 2 \u2212 32`; `0` = no echo, `255` = outside coverage). The `X-Radar-Time` response header states the frame actually used.\n- `GET /radar/encoding` \u2014 the grey value \u2194 dBZ mapping for `style=raw` as JSON (formula, special values and the full lookup table).\n- `GET /radar/point` \u2014 machine-readable **precipitation time series** at a location in 5-minute steps. Each row carries `RATE` (rain rate in **mm/h**, `0` = no echo) and the underlying reflectivity `DBZ` (`null` = no echo); frames without coverage at the point are omitted (`meta.frames_missing` counts frames absent from the archive); `source` names the layer used (`opera` or `dpc-italy`).\n\n`RATE` derives from `DBZ` via the standard Marshall-Palmer relation (Z = 200\u00b7R^1.6) \u2014 strictly monotonic, so the mapping is 1:1 in both directions: 20 dBZ \u2248 0.7 mm/h, 30 \u2248 2.7, 40 \u2248 11.5, 50 \u2248 49. Above ~55 dBZ the echo is usually hail \u2014 treat such rates as upper-bound estimates.\n\nRadar requires the **Pro plan or higher**. Reach-back is plan-dependent (Pro 7 days, Business 30 days); point series span max **6 hours per call**. Note: values sourced from the Italian layer are licensed **CC BY-SA** (share-alike applies if you redistribute them); OPERA data is CC BY 4.0. `meta.attribution` (JSON) / `X-Attribution` (PNG) always state what applies to your response.\n\n## Data attribution\n\nSome models carry license attribution (e.g. `ecmwf-ifs`: ECMWF data under CC BY 4.0). Where required, the exact attribution text is included as `meta.attribution` in every response for that model (and on its catalog entry in `/models`). **If you redistribute or republish such data, you must preserve this attribution.**\n\n## Limits\n\n- Model runs: the **most recent runs** per model are retrievable (typically 2, model-dependent \u2014 `/models` lists them). For the past beyond that, the reanalysis archive (`era5-*`) provides continuous coverage back to 1940. During model production the newest run fills progressively; `meta.run` always states what you got.\n- Observations reach back **7 days** (Business plan: **30 days**); time-series span max **72 h** (default: last 24 h).\n- Observation `bbox` max **90 x 60 degrees**.\n- Radar reach-back **7 days** (Business: **30 days**); point series span max **6 h** per call; composite width max **1600 px**.\n- ERA5 history: **13 container-months per call** (see *Reanalysis archive*); windows are clamped to the archive.\n- Request quotas per plan (see *Plans & quotas*); `429` + `Retry-After` when exhausted.\n\n## Errors\n\nAll errors are JSON with an HTTP status:\n\n```json\n{\"error\": {\"code\": \"out_of_grid\", \"message\": \"...\", \"status\": 422}}\n```\n\n| HTTP | `code` | Meaning |\n|---|---|---|\n| 400 | `invalid_parameter` | malformed or unknown request parameter |\n| 401 | `missing_key` / `invalid_key` | authentication failed |\n| 403 | `not_entitled` / `key_expired` | product or model not in your plan; trial or subscription ended |\n| 404 | `not_found` / `run_not_found` | unknown endpoint, model, station or run |\n| 405 | `method_not_allowed` | only GET is supported |\n| 422 | `out_of_grid` / `out_of_range` | point outside model domain; bbox/time span too large |\n| 429 | `quota_exceeded` | hourly, daily or monthly request limit reached (see `Retry-After`) |\n| 503 | `data_unavailable` | backend data temporarily unavailable |\n\n## Terms of use & disclaimer\n\nBy requesting an API key or using this API you accept these terms:\n\n- **No warranty.** The service and all data are provided \"as is\" and \"as available\", without warranty of any kind, express or implied \u2014 including availability, accuracy, completeness, timeliness or fitness for a particular purpose. There is no uptime guarantee (no SLA).\n- **Third-party source data.** Forecasts and observations derive from third-party providers (national weather services and other agencies). Source data can be missing, delayed or wrong, and models, runs or parameters can change or be discontinued at the source at any time. Such gaps are passed through \u2014 values are never fabricated to fill them.\n- **Limitation of liability.** To the maximum extent permitted by law, Metmaps.eu and its operator are not liable for any damages \u2014 direct, indirect, incidental or consequential (including lost profits, lost data or business interruption) \u2014 arising from use of, or inability to use, the API or its data.\n- **Not for safety-critical use.** The data must not be the sole basis for decisions involving protection of life or property (e.g. aviation, marine, emergency response). Official warnings of your national meteorological authority always prevail.\n- **Access.** We may modify, suspend or terminate the API, individual endpoints, models, plans or any API key at any time, without prior notice and without stating reasons. API keys are personal and non-transferable; sharing, resale or circumvention of quotas leads to immediate termination.\n- **Redistribution.** Where responses carry attribution requirements (see Data attribution), redistribution of the data must preserve them.\n- **Changes.** These terms may change at any time; continued use after a change constitutes acceptance.\n- **Governing law.** German law applies; exclusive place of jurisdiction is the operator's seat in Germany.\n"
  },
  "servers": [
    {
      "url": "https://api.metmaps.eu/v1"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKeyQuery": []
    }
  ],
  "paths": {
    "/catalog": {
      "get": {
        "summary": "Public model catalog: coverage and parameters",
        "description": "No API key required. Marketing/discovery listing of all models: coverage area (global flag or lon/lat bbox), the parameter set each model delivers, grid resolution, ensemble member count and the minimum plan. Powers the model explorer on the docs page. No runs and no data values \u2014 use /models (with key) for retrievable runs.",
        "security": [],
        "responses": {
          "200": {
            "description": "Catalog",
            "content": {
              "application/json": {
                "example": {
                  "meta": {
                    "count": 36
                  },
                  "data": [
                    {
                      "model": "icon-eu",
                      "name": "DWD ICON-EU",
                      "resolution_deg": 0.0625,
                      "ensemble": false,
                      "plan": "starter",
                      "coverage": {
                        "bbox": [
                          -23.5,
                          29.5,
                          62.56,
                          70.56
                        ]
                      },
                      "parameters": [
                        "TL",
                        "TX",
                        "TN",
                        "FF",
                        "DIR",
                        "G1h",
                        "QFF",
                        "RR1h",
                        "NL",
                        "NM",
                        "NH",
                        "Sh"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/models": {
      "get": {
        "summary": "List available models and runs",
        "description": "Catalog of the models your key is entitled to, with the currently retrievable run times (newest first).",
        "operationId": "listModels",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "meta": {
                      "type": "object",
                      "properties": {
                        "count": {
                          "type": "integer"
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "model": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "resolution_deg": {
                            "type": "number"
                          },
                          "ensemble": {
                            "type": "boolean"
                          },
                          "runs": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "attribution": {
                            "type": "string",
                            "description": "License attribution text \u2014 must be preserved when redistributing this model's data"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "meta": {
                    "count": 2
                  },
                  "data": [
                    {
                      "model": "icon-eu",
                      "name": "Icon-Eu",
                      "resolution_deg": 0.0625,
                      "ensemble": false,
                      "runs": [
                        "2026-07-04T06:00Z",
                        "2026-07-04T00:00Z",
                        "2026-07-03T18:00Z"
                      ]
                    },
                    {
                      "model": "gfs",
                      "name": "Gfs",
                      "resolution_deg": 0.125,
                      "ensemble": false,
                      "runs": [
                        "2026-07-04T00:00Z",
                        "2026-07-03T18:00Z",
                        "2026-07-03T12:00Z"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          }
        }
      }
    },
    "/models/{model}/point": {
      "get": {
        "summary": "Model forecast time series at a point",
        "description": "Full forecast time series of the requested (or latest) run at the model grid point nearest to `lat`/`lon`. The resolved grid point, its elevation and land fraction are returned in `meta.grid_point`. For the reanalysis slugs (`era5-eu`, `era5-us`) `from` and `to` are required, `run` does not apply, and `meta.archive` states the retrievable range.",
        "operationId": "modelPoint",
        "parameters": [
          {
            "name": "model",
            "in": "path",
            "required": true,
            "description": "Model slug from /models",
            "schema": {
              "type": "string",
              "enum": [
                "icon",
                "icon-eu",
                "gfs",
                "ecmwf-ifs"
              ]
            }
          },
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lon",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          },
          {
            "name": "run",
            "in": "query",
            "required": false,
            "description": "Explicit run (ISO 8601 UTC). Must be one of the runs listed by /models; defaults to the newest.",
            "schema": {
              "type": "string"
            },
            "example": "2026-07-04T06:00Z"
          },
          {
            "$ref": "#/components/parameters/parameters"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/temperatureUnit"
          },
          {
            "$ref": "#/components/parameters/windUnit"
          },
          {
            "$ref": "#/components/parameters/pressureUnit"
          },
          {
            "$ref": "#/components/parameters/precipitationUnit"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "meta": {
                      "type": "object",
                      "properties": {
                        "model": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "run": {
                          "type": "string"
                        },
                        "requested_point": {
                          "$ref": "#/components/schemas/Point"
                        },
                        "grid_point": {
                          "$ref": "#/components/schemas/GridPoint"
                        },
                        "units": {
                          "$ref": "#/components/schemas/Units"
                        },
                        "count": {
                          "type": "integer"
                        },
                        "attribution": {
                          "type": "string",
                          "description": "Present for models with license attribution (e.g. ecmwf-ifs) \u2014 must be preserved when redistributing"
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TimeRow"
                      }
                    }
                  }
                },
                "example": {
                  "meta": {
                    "model": "icon-eu",
                    "name": "Icon-Eu",
                    "run": "2026-07-04T06:00Z",
                    "requested_point": {
                      "lat": 48.4,
                      "lon": 11.9
                    },
                    "grid_point": {
                      "lat": 48.375,
                      "lon": 11.875,
                      "elevation_m": 436.6,
                      "land_fraction": 1
                    },
                    "units": {
                      "TL": "C",
                      "FF": "km/h",
                      "RR1h": "mm"
                    },
                    "count": 2
                  },
                  "data": [
                    {
                      "time": "2026-07-04T07:00Z",
                      "TL": 18.7,
                      "FF": 7,
                      "RR1h": 0,
                      "RR1h_hours": 1
                    },
                    {
                      "time": "2026-07-04T08:00Z",
                      "TL": 20.7,
                      "FF": 9,
                      "RR1h": 0,
                      "RR1h_hours": 1
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NotEntitled"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/OutOfRange"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          },
          "503": {
            "$ref": "#/components/responses/DataUnavailable"
          }
        }
      }
    },
    "/observations": {
      "get": {
        "summary": "Observation snapshot for an area",
        "description": "Latest surface observations for all stations inside `bbox` at the requested hour (default: most recent). Stations report at mixed cadences (10-minute automatic stations, hourly/synoptic reports); each station object carries the actual observation time and the most recent value per parameter within that hour.",
        "operationId": "obsSpatial",
        "parameters": [
          {
            "name": "bbox",
            "in": "query",
            "required": true,
            "description": "lon1,lat1,lon2,lat2 (WGS84, west,south,east,north). Max 90x60 degrees.",
            "schema": {
              "type": "string"
            },
            "example": "6,45.8,10.5,47.9"
          },
          {
            "name": "time",
            "in": "query",
            "required": false,
            "description": "Hour to query (ISO 8601 UTC), up to 7 days back. Default: latest available.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/parameters"
          },
          {
            "$ref": "#/components/parameters/temperatureUnit"
          },
          {
            "$ref": "#/components/parameters/windUnit"
          },
          {
            "$ref": "#/components/parameters/pressureUnit"
          },
          {
            "$ref": "#/components/parameters/precipitationUnit"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "meta": {
                      "type": "object",
                      "properties": {
                        "time": {
                          "type": "string"
                        },
                        "bbox": {
                          "type": "array",
                          "items": {
                            "type": "number"
                          }
                        },
                        "units": {
                          "$ref": "#/components/schemas/Units"
                        },
                        "count": {
                          "type": "integer"
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "station": {
                            "$ref": "#/components/schemas/Station"
                          },
                          "time": {
                            "type": "string"
                          },
                          "values": {
                            "type": "object",
                            "additionalProperties": {
                              "type": "number"
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "meta": {
                    "time": "2026-07-04T09:00Z",
                    "bbox": [
                      6,
                      45.8,
                      10.5,
                      47.9
                    ],
                    "units": {
                      "TL": "C",
                      "RH": "%"
                    },
                    "count": 1
                  },
                  "data": [
                    {
                      "station": {
                        "wmo": "066700",
                        "locator": "SMNKLO",
                        "name": "Z\u00fcrich / Kloten",
                        "type": "SM10",
                        "lat": 47.479,
                        "lon": 8.53596,
                        "elevation_m": 426
                      },
                      "time": "2026-07-04T09:00Z",
                      "values": {
                        "TL": 22.4,
                        "RH": 41
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NotEntitled"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/OutOfRange"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          },
          "503": {
            "$ref": "#/components/responses/DataUnavailable"
          }
        }
      }
    },
    "/observations/stations": {
      "get": {
        "summary": "Station catalog",
        "description": "Stations currently reporting, for onboarding and id lookup. Filter with `bbox` and/or a name/id search `q`.",
        "operationId": "obsCatalog",
        "parameters": [
          {
            "name": "bbox",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "example": "6,45.8,10.5,47.9"
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Case-insensitive substring match on station name, or exact WMO/locator id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "meta": {
                      "type": "object",
                      "properties": {
                        "as_of": {
                          "type": "string"
                        },
                        "count": {
                          "type": "integer"
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Station"
                      }
                    }
                  }
                },
                "example": {
                  "meta": {
                    "as_of": "2026-07-04T09:00Z",
                    "count": 1
                  },
                  "data": [
                    {
                      "wmo": "066700",
                      "locator": "SMNKLO",
                      "name": "Z\u00fcrich / Kloten",
                      "type": "SM10",
                      "lat": 47.479,
                      "lon": 8.53596,
                      "elevation_m": 426
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NotEntitled"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          },
          "503": {
            "$ref": "#/components/responses/DataUnavailable"
          }
        }
      }
    },
    "/observations/stations/{id}": {
      "get": {
        "summary": "Observation time series for one station",
        "description": "All reports of one station in the requested window (default: last 24 h, max 72 h, up to 7 days back), at the station's native cadence \u2014 10-minute resolution where available. Rows are flat (`time` + parameter keys), symmetric with the model point response, so observations and forecasts join on identical keys.",
        "operationId": "obsSeries",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Station id: 5/6-digit WMO index (`06670`) or locator/ICAO (`LSZH`). Prefixes `wmo:` and `icao:` force the interpretation.",
            "schema": {
              "type": "string"
            },
            "example": "06670"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/parameters"
          },
          {
            "$ref": "#/components/parameters/temperatureUnit"
          },
          {
            "$ref": "#/components/parameters/windUnit"
          },
          {
            "$ref": "#/components/parameters/pressureUnit"
          },
          {
            "$ref": "#/components/parameters/precipitationUnit"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "meta": {
                      "type": "object",
                      "properties": {
                        "station": {
                          "$ref": "#/components/schemas/Station"
                        },
                        "from": {
                          "type": "string"
                        },
                        "to": {
                          "type": "string"
                        },
                        "units": {
                          "$ref": "#/components/schemas/Units"
                        },
                        "count": {
                          "type": "integer"
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TimeRow"
                      }
                    }
                  }
                },
                "example": {
                  "meta": {
                    "station": {
                      "wmo": "066700",
                      "locator": "SMNKLO",
                      "name": "Z\u00fcrich / Kloten",
                      "type": "SM10",
                      "lat": 47.479,
                      "lon": 8.53596,
                      "elevation_m": 426
                    },
                    "from": "2026-07-04T06:00Z",
                    "to": "2026-07-04T09:00Z",
                    "units": {
                      "TL": "C",
                      "RH": "%",
                      "FF": "km/h"
                    },
                    "count": 2
                  },
                  "data": [
                    {
                      "time": "2026-07-04T06:00Z",
                      "TL": 17.4,
                      "RH": 50,
                      "FF": 2
                    },
                    {
                      "time": "2026-07-04T06:10Z",
                      "TL": 17.6,
                      "RH": 54,
                      "FF": 2
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NotEntitled"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/OutOfRange"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          },
          "503": {
            "$ref": "#/components/responses/DataUnavailable"
          }
        }
      }
    },
    "/radar/composite": {
      "get": {
        "summary": "Radar composite image (PNG)",
        "description": "Map section of the European radar composite (`aeu`: OPERA + Italian DPC layer) as a PNG. `style=palette` (default): coloured dBZ palette, transparent background. `style=raw`: grey-value PNG in the unified value encoding (dBZ = (value \u2212 2) / 2 \u2212 32; 0 = no echo, 255 = outside coverage \u2014 full mapping from `/radar/encoding`), nearest-neighbour sampled so values are never interpolated. Image height follows the bbox aspect ratio. The `X-Radar-Time` header states the 5-minute frame used (latest frame up to 30 minutes before the requested time); `X-Attribution` carries the license attribution.",
        "operationId": "radarComposite",
        "parameters": [
          {
            "name": "bbox",
            "in": "query",
            "required": true,
            "description": "lon1,lat1,lon2,lat2 (WGS84, west,south,east,north). Must intersect \u221230..40\u00b0E / 34..74\u00b0N.",
            "schema": {
              "type": "string"
            },
            "example": "5.5,45.5,11,48"
          },
          {
            "name": "time",
            "in": "query",
            "required": false,
            "description": "Frame time (ISO 8601 UTC), plan-dependent reach-back. Default: latest frame.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "width",
            "in": "query",
            "required": false,
            "description": "Image width in pixels, 64..1600. Height derives from the bbox aspect ratio. Default 800.",
            "schema": {
              "type": "integer",
              "default": 800
            }
          },
          {
            "name": "style",
            "in": "query",
            "required": false,
            "description": "palette (coloured image, default) or raw (grey values encoding dBZ, see /radar/encoding).",
            "schema": {
              "type": "string",
              "enum": [
                "palette",
                "raw"
              ],
              "default": "palette"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Radar-Time": {
                "description": "Frame time actually rendered (ISO 8601 UTC)",
                "schema": {
                  "type": "string"
                }
              },
              "X-Attribution": {
                "description": "License attribution (must be preserved on redistribution)",
                "schema": {
                  "type": "string"
                }
              },
              "X-Radar-Encoding": {
                "description": "style=raw only: the value encoding in short form",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NotEntitled"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/OutOfRange"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          },
          "503": {
            "$ref": "#/components/responses/DataUnavailable"
          }
        }
      }
    },
    "/radar/point": {
      "get": {
        "summary": "Radar precipitation time series at a point",
        "description": "Rain rate (`RATE`, mm/h) and reflectivity (`DBZ`) at a location in 5-minute steps, read from the archived composite frames. `RATE` is the standard Marshall-Palmer estimate from `DBZ` (Z = 200\u00b7R^1.6, 1:1 and monotonic); `RATE: 0` / `DBZ: null` = coverage but no echo. South of 45.7\u00b0N inside Italy the DPC layer is used where it has coverage (`source: dpc-italy`), elsewhere OPERA. Frames without radar coverage at the point are omitted from `data`. Default window: the last hour.",
        "operationId": "radarPoint",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "description": "Latitude (WGS84), 34..74.",
            "schema": {
              "type": "number"
            },
            "example": 47.38
          },
          {
            "name": "lon",
            "in": "query",
            "required": true,
            "description": "Longitude (WGS84), \u221230..40.",
            "schema": {
              "type": "number"
            },
            "example": 8.54
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Window start (ISO 8601 UTC), plan-dependent reach-back. Default: to \u2212 1 h.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Window end (ISO 8601 UTC). Default: now. Max span 6 h.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "meta": {
                      "type": "object",
                      "properties": {
                        "product": {
                          "type": "string"
                        },
                        "lat": {
                          "type": "number"
                        },
                        "lon": {
                          "type": "number"
                        },
                        "from": {
                          "type": "string"
                        },
                        "to": {
                          "type": "string"
                        },
                        "step_minutes": {
                          "type": "integer"
                        },
                        "frames_expected": {
                          "type": "integer"
                        },
                        "frames_missing": {
                          "type": "integer"
                        },
                        "units": {
                          "type": "object"
                        },
                        "note": {
                          "type": "string"
                        },
                        "attribution": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "time": {
                            "type": "string"
                          },
                          "RATE": {
                            "type": "number",
                            "description": "Rain rate in mm/h (Marshall-Palmer from DBZ); 0 = no echo"
                          },
                          "DBZ": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Reflectivity in dBZ; null = no echo (clear sky)"
                          },
                          "source": {
                            "type": "string",
                            "enum": [
                              "opera",
                              "dpc-italy"
                            ]
                          }
                        }
                      }
                    }
                  },
                  "example": {
                    "meta": {
                      "product": "aeu",
                      "lat": 47.55,
                      "lon": 22.05,
                      "from": "2026-07-08T14:20Z",
                      "to": "2026-07-08T14:50Z",
                      "step_minutes": 5,
                      "frames_expected": 7,
                      "frames_missing": 0,
                      "units": {
                        "RATE": "mm/h",
                        "DBZ": "dBZ"
                      }
                    },
                    "data": [
                      {
                        "time": "2026-07-08T14:40Z",
                        "RATE": 9.99,
                        "DBZ": 39,
                        "source": "opera"
                      },
                      {
                        "time": "2026-07-08T14:45Z",
                        "RATE": 339.32,
                        "DBZ": 63.5,
                        "source": "opera"
                      },
                      {
                        "time": "2026-07-08T14:50Z",
                        "RATE": 804.65,
                        "DBZ": 69.5,
                        "source": "opera"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NotEntitled"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/OutOfRange"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          }
        }
      }
    },
    "/radar/encoding": {
      "get": {
        "summary": "Grey value to dBZ / mm-h mapping for raw composites",
        "description": "The pixel-value encoding used by `/radar/composite?style=raw`: conversion formulas, special values (0 = no echo, 255 = outside coverage) and the full value\u2194dBZ\u2194mm/h lookup table (0.5 dBZ steps; mm/h via Marshall-Palmer Z = 200\u00b7R^1.6, 1:1 and monotonic).",
        "operationId": "radarEncoding",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "meta": {
                      "type": "object",
                      "properties": {
                        "product": {
                          "type": "string"
                        },
                        "applies_to": {
                          "type": "string"
                        }
                      }
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "formula": {
                          "type": "string"
                        },
                        "special_values": {
                          "type": "object"
                        },
                        "step_dbz": {
                          "type": "number"
                        },
                        "range": {
                          "type": "object"
                        },
                        "values": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "value": {
                                "type": "integer"
                              },
                              "dbz": {
                                "type": "number"
                              }
                            }
                          }
                        }
                      }
                    }
                  },
                  "example": {
                    "meta": {
                      "product": "aeu",
                      "applies_to": "grey pixel values of /radar/composite?style=raw"
                    },
                    "data": {
                      "formula": "dBZ = (value - 2) / 2 - 32",
                      "special_values": {
                        "0": "radar coverage, no echo (clear sky)",
                        "255": "outside radar coverage"
                      },
                      "step_dbz": 0.5,
                      "range": {
                        "value_min": 2,
                        "value_max": 254,
                        "dbz_min": -32,
                        "dbz_max": 94
                      },
                      "values": [
                        {
                          "value": 2,
                          "dbz": -32,
                          "mmh": 0.0
                        },
                        {
                          "value": 66,
                          "dbz": 0,
                          "mmh": 0.04
                        },
                        {
                          "value": 126,
                          "dbz": 30,
                          "mmh": 2.73
                        },
                        {
                          "value": 254,
                          "dbz": 94,
                          "mmh": 27343.64
                        }
                      ],
                      "formula_mmh": "mm/h = (10^(dBZ/10) / 200)^(1/1.6)"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/QuotaExceeded"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key as Bearer token"
      },
      "apiKeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "apikey",
        "description": "API key as query parameter (fallback)"
      }
    },
    "parameters": {
      "parameters": {
        "name": "parameters",
        "in": "query",
        "required": false,
        "description": "Comma-separated parameter codes to include (see vocabulary above). Default: all available.",
        "schema": {
          "type": "string"
        },
        "example": "TL,FF,RR1h"
      },
      "from": {
        "name": "from",
        "in": "query",
        "required": false,
        "description": "Window start, ISO 8601 UTC.",
        "schema": {
          "type": "string"
        },
        "example": "2026-07-04T06:00Z"
      },
      "to": {
        "name": "to",
        "in": "query",
        "required": false,
        "description": "Window end, ISO 8601 UTC.",
        "schema": {
          "type": "string"
        },
        "example": "2026-07-04T18:00Z"
      },
      "temperatureUnit": {
        "name": "temperature_unit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "c",
            "f"
          ],
          "default": "c"
        }
      },
      "windUnit": {
        "name": "wind_unit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "kmh",
            "ms",
            "kt",
            "mph"
          ],
          "default": "kmh"
        }
      },
      "pressureUnit": {
        "name": "pressure_unit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "hpa",
            "inhg"
          ],
          "default": "hpa"
        }
      },
      "precipitationUnit": {
        "name": "precipitation_unit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "mm",
            "in"
          ],
          "default": "mm"
        }
      }
    },
    "schemas": {
      "Point": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number"
          },
          "lon": {
            "type": "number"
          }
        }
      },
      "GridPoint": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number"
          },
          "lon": {
            "type": "number"
          },
          "elevation_m": {
            "type": "number",
            "description": "model grid cell elevation"
          },
          "land_fraction": {
            "type": "number",
            "description": "model grid cell land fraction 0..1"
          }
        }
      },
      "Station": {
        "type": "object",
        "properties": {
          "wmo": {
            "type": [
              "string",
              "null"
            ],
            "description": "WMO index (6-digit archive form; 5-digit WMO id + trailing 0)"
          },
          "locator": {
            "type": [
              "string",
              "null"
            ],
            "description": "ICAO code or national station id"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "internal report-type tag (e.g. SM10 = 10-min AWS, SYNO = SYNOP)"
          },
          "lat": {
            "type": "number"
          },
          "lon": {
            "type": "number"
          },
          "elevation_m": {
            "type": "integer"
          }
        }
      },
      "TimeRow": {
        "type": "object",
        "description": "One timestamp with parameter values. Keys besides `time` are the parameter codes (plus `_hours` step-width companions and, for ensembles, `_med`/`_p10`/`_p90`/`_min`/`_max` spread keys).",
        "required": [
          "time"
        ],
        "properties": {
          "time": {
            "type": "string"
          }
        },
        "additionalProperties": {
          "type": "number"
        }
      },
      "Units": {
        "type": "object",
        "description": "Unit per parameter code actually present in the response",
        "additionalProperties": {
          "type": "string"
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "status": {
                "type": "integer"
              }
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Malformed or unknown request parameter",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotEntitled": {
        "description": "Product or model not included in your plan",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Unknown endpoint, model, station or run",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "OutOfRange": {
        "description": "Point outside model domain, or bbox/time window outside limits",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "QuotaExceeded": {
        "description": "Hourly request quota reached (see Retry-After header)",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "DataUnavailable": {
        "description": "Backend data temporarily unavailable",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}
