← Vaisala Xweather API & MapsCONTENT HISTORY

Update to Vaisala Xweather API & Maps

Snapshot Sep 30, 2026 · 23:15 UTC · version 0.14.1

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "This skill should be used to build Xweather Raster Maps image URLs (maps.api.xweather.com) — either static map images or XYZ map tile URLs for Leaflet, Mapbox, Google Maps, OpenLayers and similar libraries — from a description of the weather imagery wanted. Use it whenever a task mentions Raster Maps, maps.api.xweather.com, maps.aerisapi.com, an Xweather weather map layer or overlay (radar, satellite, alerts, temperatures, lightning, tropical cyclones, air quality, base maps, admin overlays), a weather map image or tile layer, layer opacity/blur/blend/scale-hsla modifiers, or asks how Raster Maps usage is measured — map units, tile counts, the daily allowance, or how many accesses a static map or tile layer will consume. Also covers Xweather's attribution requirement — the 'Powered by Vaisala Xweather' credit and logo rules that apply wherever Xweather data or imagery is displayed.",
  "included_files": [
    {
      "relative_path": "references/layers.md",
      "size_in_bytes": 35523
    },
    {
      "relative_path": "references/map-units.md",
      "size_in_bytes": 5759
    },
    {
      "relative_path": "references/modifiers.md",
      "size_in_bytes": 7210
    },
    {
      "relative_path": "references/url-formats.md",
      "size_in_bytes": 7719
    },
    {
      "relative_path": "scripts/xwmap.py",
      "size_in_bytes": 6214
    }
  ],
  "name": "raster-maps",
  "skill_md_contents": "---\nname: raster-maps\ndescription: This skill should be used to build Xweather Raster Maps image URLs (maps.api.xweather.com) — either static map images or XYZ map tile URLs for Leaflet, Mapbox, Google Maps, OpenLayers and similar libraries — from a description of the weather imagery wanted. Use it whenever a task mentions Raster Maps, maps.api.xweather.com, maps.aerisapi.com, an Xweather weather map layer or overlay (radar, satellite, alerts, temperatures, lightning, tropical cyclones, air quality, base maps, admin overlays), a weather map image or tile layer, layer opacity/blur/blend/scale-hsla modifiers, or asks how Raster Maps usage is measured — map units, tile counts, the daily allowance, or how many accesses a static map or tile layer will consume. Also covers Xweather's attribution requirement — the 'Powered by Vaisala Xweather' credit and logo rules that apply wherever Xweather data or imagery is displayed.\ncompatibility: Skill instructions are provider-neutral. The bundled scripts/xwmap.py needs Python 3 (standard library only) and network access to maps.api.xweather.com.\nlicense: MIT\n---\n\n# Xweather Raster Maps URL builder\n\nTurn a description of wanted weather imagery into a `maps.api.xweather.com` URL — as a standalone\nstatic image or as a tile template for an interactive mapping library.\n\nThis is a different product from the Weather API: different host, different URL grammar, and\ncredentials sit **in the path**, not in the query string.\n\n```\nhttps://maps.api.xweather.com/{client_id}_{client_secret}/{layers}/…/{offset}.{format}\n```\n\n## Two output methods — ask which one\n\nEvery Raster Maps request is one of two shapes, and they are not interchangeable:\n\n| | Static map | Map tiles |\n|---|---|---|\n| Produces | A single finished image | A 256×256 tile template a library fetches many of |\n| Use when | Email, report, dashboard panel, `<img>` tag, Slack, PDF | Leaflet / Mapbox / Google Maps / OpenLayers / Apple Maps |\n| Path | `{layers}/{w}x{h}/{place},{zoom}/{offset}.{fmt}` | `{layers}/{z}/{x}/{y}/{offset}.{fmt}` |\n| Interactive | No — no pan or zoom | Yes |\n\n**If the user hasn't said which one they want, ask before generating anything.** Use\nAsk a direct either/or question — a structured-choice prompt if the agent has one, plain text otherwise.\nDon't guess from weak signals and don't produce both by default — a tile template pasted into an\n`<img>` tag renders one 256-pixel square, and a static URL handed to Leaflet fails outright.\n\nSignals strong enough to skip the question: the user names a mapping library, says \"tile layer\" or\n\"XYZ\", or gives `{z}/{x}/{y}` (→ tiles); or names pixel dimensions, says \"image\", \"PNG for a\nreport\", or shows an `<img>` tag (→ static).\n\n## Workflow\n\n1. **Determine the output method** — ask if not already clear (above).\n2. **Pick the layers.** Use the intent map below and confirm codes against `references/layers.md`.\n   Order matters: they composite left to right, so base map first, weather next, labels last.\n3. **Add the geography.** Static: `place,zoom` or a `south,west,north,east` bounding box. Tiles: the\n   library substitutes `{z}/{x}/{y}` — leave the placeholders in.\n4. **Add the time offset.** `current` unless the user wants past or forecast imagery.\n5. **Pick the format.** `png` for tile overlays (transparency is mandatory); `png` or `jpg` for\n   static maps that include their own base layer.\n6. **Apply modifiers** if the request implies them — opacity, blur, blend, recolour. See\n   `references/modifiers.md`.\n7. **Report the URL with its map-unit cost** (see Map units), then handle credentials (see below).\n8. **Include the attribution.** Any markup you hand over — an `<img>` tag, a tile layer, a template —\n   needs the Xweather credit alongside it. See \"Attribution is required\" below.\n\nNever invent a layer code. Check `references/layers.md`, or refetch the live catalog:\n\n```bash\ncurl -s https://www.xweather.com/docs/api/maps/layers\n```\n\nThat JSON (`{ layers: [{ id, title, description, multiplier, modifiers, categories, dataRange,\ndataCoverage, updateInterval }] }`) is the authoritative layer list and is what\n`references/layers.md` was generated from.\n\n## Intent → layer\n\n| The user wants | Layer code |\n|---|---|\n| Radar | `radar` (regional, higher res) · `radar-global` (satellite-derived fill where radar is absent) |\n| Future radar | `fradar` — add `-hrrr` / `-nam` / `-gfs` to pick the model |\n| *Forecast of any `f`-prefixed layer* | Raster Maps splits observed from forecast — `temperatures` vs `ftemperatures`. **MapsGL doesn't**: one layer spans both there, so don't carry `f`-prefixed codes across. |\n| Satellite | `satellite-geocolor` (the good-looking default) · `satellite-visible` · `satellite-infrared-color` · `satellite-water-vapor` |\n| Watches and warnings | `alerts` — `-severe`, `-fire`, `-flood`, `-winter`, `-heat`, `-wind`, `-surge`, `-frost-freeze`; `-watches` / `-warnings` |\n| Temperature | `temperatures` · forecast `ftemperatures` · labels `temperatures-text` |\n| Feels-like, dew point, humidity, wind, gusts, visibility | `feels-like` · `dew-points` · `humidity` · `wind-speeds` · `wind-gusts` · `visibility` — each has an `f`-prefixed forecast twin and a `-text` label variant |\n| Lightning | `lightning-strikes` (**×10**) · `lightning-flash` (×1) · `lightning-strike-density` (×1) |\n| Storm cells, storm reports | `stormcells` · `stormreports` |\n| Severe outlook, fire outlook, drought | `convective` · `fires-outlook` · `drought-monitor` |\n| Hurricanes | `tropical-cyclones` plus the `tropical-cyclones-*` family (positions, track lines, forecast cones, icons, names) |\n| Air quality | `air-quality-index` / `air-quality-index-categories` (×1) · individual pollutants and national scales (**×5**) |\n| Snow, ice, precip accumulation | `snow-depth` · `fqsf-accum` · `fice-accum` · `fqpf-accum` · `precip` |\n| Marine | `maritime-wave-heights` · `maritime-swell-*` · `maritime-sst` · `maritime-currents` · `maritime-tides` |\n| Fronts and pressure | `surface-analysis` · `surface-analysis-fronts` · `surface-analysis-pressure` |\n| Base map | `flat` · `flat-dk` · `terrain` · `terrain-dk` · `blue-marble` |\n| Borders, cities, roads | `admin` (combined) · `admin-cities` / `-dk` · `states` · `counties` · `countries-outlines` · `roads` · `interstates` |\n| Clip weather to land or water | the `Masks` layers — `land-flat`, `water-flat`, `clip-us-terrain`, … |\n\nLayers with a **Modifier** group in `layers.md` take dash-joined options — `alerts-severe`,\n`alerts-severe-warnings`, `temperatures-rtma`, `fradar-hrrr`. One option per group; groups combine.\n\nA few modifier groups are described in the catalog without enumerated options (`radar`'s Region says\n\"either US or Global\" but lists no values). Treat those as unconfirmed: say the modifier exists, and\ncheck the layer's doc page or test the request rather than emitting a guessed suffix.\n\nA conventional stack is base → weather → labels:\n\n```\nflat-dk,alerts,radar,admin\nterrain,temperatures:blend(overlay),admin-cities\n```\n\nMaximum **10 layers** per request.\n\n## URL shapes\n\nWhen the URL goes into a page, the attribution goes with it:\n\n```html\n<img src=\"https://maps.api.xweather.com/{client_id}_{client_secret}/flat,radar,admin/800x600/minneapolis,mn,7/current.png\"\n     width=\"800\" height=\"600\" alt=\"Radar\" />\n<a href=\"https://www.xweather.com/\" target=\"_blank\" title=\"Powered by Vaisala Xweather\">Powered by Vaisala Xweather</a>\n```\n\nFor a tile layer, most mapping libraries take it as an attribution option instead — Leaflet and\nMapbox GL both accept an `attribution` string on the layer or source, which is the idiomatic place to\nput it.\n\n**Static, centre point** — place and zoom share one comma-joined segment:\n\n```\nhttps://maps.api.xweather.com/{client_id}_{client_secret}/flat,radar,admin/800x600/minneapolis,mn,7/current.png\nhttps://maps.api.xweather.com/{client_id}_{client_secret}/radar/300x300/44.96,-93.27,7/current.png\n```\n\n**Static, bounding box** — `south,west,north,east`:\n\n```\nhttps://maps.api.xweather.com/{client_id}_{client_secret}/flat,radar,admin/320x320/30.1010,-85.9578,33.0948,-82.4421/current.png\n```\n\nThree comma-separated numbers means `lat,lon,zoom`; four means a bounding box. That count is the only\nthing telling them apart, so a dropped coordinate silently changes what the request means.\n\n**Tiles** — hand over the template with placeholders intact:\n\n```\nhttps://maps.api.xweather.com/{client_id}_{client_secret}/radar/{z}/{x}/{y}/current.png\nhttps://maps{s}.api.xweather.com/{client_id}_{client_secret}/radar/{z}/{x}/{y}/current.png   # with subdomains: '1234'\n```\n\nPair a tile URL with the matching library snippet — Leaflet, Mapbox GL, Google Maps, and OpenLayers\nexamples are in `references/url-formats.md`. Give the snippet, not just the URL; the URL alone is\nrarely enough to get a layer on screen.\n\n**Time offset:** `current` / `latest`, a relative offset (`-10minutes`, `+1hour`, `-3days`; integers\nonly, so `-90minutes` not `-1.5hours`), or a UTC valid time `YYYYMMDDhhiiss`.\n\n**Format:** `png` (true colour), `png32`–`png256` (indexed, smaller), `jpg` / `jpg70`–`jpg100`,\n`webp`. Prefix with `@2x` for retina. **Tile overlays must be `png` or `webp`** — JPEG has no alpha,\nso a JPEG tile paints an opaque block over the base map.\n\nSize limits: 5000×5000 on paid plans, 2000×2000 on the free developer trial.\n\n## Map units — report the cost with the URL\n\nRaster Maps measures usage in **map units**, against a **daily** allowance set by the subscription.\nOne map unit = **one 256×256 tile carrying one ×1 layer**.\n\n```\ntiles     = ceil(width / 256) × ceil(height / 256)\nmap units = tiles × Σ(multiplier of each layer)\n```\n\nMost layers are ×1, but `lightning-strikes` and the `lightning-all` family are **×10**, and\nindividual air-quality pollutant and national-index layers are **×5**. A layer listed twice counts\ntwice.\n\n**Show the arithmetic, not just the total** — the division is where people get surprised:\n\n> `flat,alerts,radar` at 800×600:\n> ```\n> 800 / 256 = 3.125 → 4 columns\n> 600 / 256 = 2.34  → 3 rows\n> 4 × 3 = 12 tiles × 3 layers = 36 map units\n> ```\n\n> `flat,lightning-strikes` at 800×600 → 12 tiles × (1 + 10) = **132 map units**, because\n> `lightning-strikes` is a ×10 layer. `lightning-flash` or `lightning-strike-density` are ×1 if\n> either answers the question.\n\nTwo facts worth volunteering, because both surprise people:\n\n> **Combining layers into one request doesn't reduce map units.** `flat,radar,admin` as a single\n> comma-joined request costs the same 3× as three separate layers — the docs are explicit that two\n> layers cost 2× \"either as separate layers or combined\". Combining saves round trips and latency,\n> not units.\n>\n> **Cost is quantised in 256-pixel steps.** 512×512 and 500×500 are both 4 tiles; 520×520 jumps to 9.\n> Sizing just under a tile boundary is free savings.\n\n### Static vs. interactive\n\nFor a **static image** the number is exact — you control the dimensions, so the calculation above is\nthe answer.\n\nFor **tiles**, it's an estimate and you should say so. A ~800×600 viewport is roughly 12 tiles, but\nthe container's real size and the map's centre shift it, and libraries commonly pull an extra row and\ncolumn to make panning smooth. More importantly: **every pan and zoom renders new tiles, each costing\nagain**, so an interactive map's lifetime cost is driven by user interaction rather than by initial\nload. Give a per-viewport figure and name that caveat rather than implying a total.\n\n**Caching is the biggest real-world lever.** Tiles and static images are cached in browser memory for\na period tied to the layer's update interval — radar refreshes every ~6 minutes, temperatures roughly\nhourly — so re-requests inside that window don't generate new units. Native apps should implement\nequivalent memory or file caching.\n\nIf the user is building something animated, multi-layer, and heavily interactive, mention that\n**MapsGL bills completely differently** — in 5-minute sessions where layer count and interaction are\nfree — and may be far cheaper for that pattern. See the `mapsgl` skill.\n\nUsage is visible in the account dashboard, with a Usage tab for history and per-application\nbreakdown; stats lag slightly behind real time.\n\n`scripts/xwmap.py … --estimate-only` computes all of this from a path, pulling live multipliers from the\ncatalog. Full model, the multiplier tables, and reduction tactics: `references/map-units.md`.\n\n## Credentials and returning the image\n\n**Without credentials:** hand over the URL with `{client_id}` and `{client_secret}` placeholders and\nsay where keys come from (the API Keys page at https://data.portal.xweather.com/account/keys). Nothing\nelse to do.\n\n**With credentials — ask before fetching.** If the user has supplied a client id and secret, ask\nwhether they want the image requested and shown, or just the URL to copy. Ask; don't assume. Fetching spends real map units against their allowance, and for a tile template there's no\nsingle meaningful image to return anyway.\n\nIf they say yes:\n\n```bash\nexport XWEATHER_CLIENT_ID='…' XWEATHER_CLIENT_SECRET='…'\npython3 scripts/xwmap.py 'flat,radar,admin/800x600/minneapolis,mn,7/current.png' -o radar.png\n```\n\nInvoke it as `python3 scripts/xwmap.py`, resolved relative to this skill's directory. Some clients\nalso expose it as a bare `xwmap` command on PATH — use that if available, but don't assume it.\n\nThe script prints the placeholder URL and the map-unit estimate, saves the image, and detects the\nJSON error body that Raster Maps returns in place of an image on failure. Read the saved file back\nto view it, and say where it was written.\n\nFor a **tile** URL, offer to render one representative tile (or a small static equivalent of the same\nlayers) rather than pretending a `{z}/{x}/{y}` template resolves to one image.\n\n### Handling credentials\n\n- **Show the URL with `{client_id}` / `{client_secret}` placeholders in your reply**, not the literal\n  keys — Raster Maps URLs get pasted into HTML, committed configs, and shared dashboards, and the\n  credentials are right there in the path. If the user explicitly asks for a populated copy-paste\n  URL, give it to them; that's their call.\n- Don't write credentials into a file or committed config unless asked. Note that a tile URL used in\n  client-side JavaScript exposes the key pair to anyone viewing the page — which is why Xweather ties\n  each key pair to a registered namespace (domain or bundle id).\n- `403` with `{\"error\":{\"code\":\"authorization_error\"}}` means bad keys or a namespace mismatch. Note\n  this envelope differs from the Weather API's `{\"success\",\"error\",\"response\"}`, and the status is\n  403 rather than 401.\n\n## Gotchas\n\n| Symptom | Cause |\n|---|---|\n| Tile layer hides the base map entirely | JPEG format on an overlay tile. Use `png` or `webp`. |\n| One small square instead of a map | A tile URL used as a static image. Switch to the static form. |\n| Blank or transparent image | Layer has no data for that place or time — check the layer's `Coverage` and `Range` in `layers.md`. Radar is regional; `radar-global` fills the gaps. |\n| Map is centred wrong or wildly zoomed | Three vs. four coordinates — `lat,lon,zoom` vs. bounding box. |\n| Labels buried under the weather | Put `admin` / `admin-cities` last in the layer list. |\n| Nothing renders at high zoom | Past the layer's max zoom, or past its data range for the requested offset. |\n| Blend has no effect | Two blends on one layer — only one is allowed per layer. |\n| Layer code rejected | A legacy alias (`sat`, `cities`, `frad`) — use the catalog code (`satellite-geocolor`, `admin-cities`, `fradar`). |\n| Higher bill than expected | A ×10 lightning or ×5 air-quality layer, a layer plotted twice, or an interactive map being panned. |\n\n## Attribution is required\n\nXweather requires attribution wherever its data or imagery is displayed. This applies to **all\nproducts** — Weather API, Raster Maps, and MapsGL alike. Build it into anything you produce, and say\nso when handing over code or URLs that will end up in front of users.\n\nThe minimum is a link to `https://www.xweather.com/` reading \"Powered by Vaisala Xweather\":\n\n```html\n<a href=\"https://www.xweather.com/\" target=\"_blank\" title=\"Powered by Vaisala Xweather\">Powered by Vaisala Xweather</a>\n```\n\nThe logo may be substituted for the \"Xweather\" text. Light and dark variants exist in SVG and PNG:\n\n```html\n<a href=\"https://www.xweather.com/\" target=\"_blank\" title=\"Powered by Vaisala Xweather\">\n  <img src=\"https://www.xweather.com/assets/logos/vaisala-xweather-logo-dark.svg\" alt=\"Vaisala Xweather\" height=\"40\" />\n</a>\n```\n\nSwap `-dark` for `-light` over a dark background, or `.svg` for `.png`. Using the logo brings rules:\nkeep it unmodified, leave at least a **10px buffer** of space around it, and only adjust lightness or\nopacity in greyscale. Don't rotate it, don't recolour it (monotone black or white excepted), and don't\nuse the symbol without the Xweather name.\n\nFull guide: https://www.xweather.com/docs/weather-api/resources/attribution\n\n## Reference files\n\n- `references/layers.md` — every layer by category: code, description, multiplier, coverage, data\n  range, update interval, and each layer's dash-joined modifier options.\n- `references/url-formats.md` — static centre-point and bounding-box forms, tile form, library\n  snippets for Leaflet / Mapbox GL / Google Maps / OpenLayers, time offsets, image-quality\n  extensions, layer combination rules, error envelope.\n- `references/modifiers.md` — colon-attached modifiers: opacity, blur, gray, invert, all blend modes,\n  and `scale-hsla` with the documented tint / recolour / heatmap / shadow recipes.\n- `references/map-units.md` — the cost model, layers grouped by multiplier, caching, and how to\n  reduce consumption.\n- `scripts/xwmap.py` — estimates map units from a path (`--estimate-only`) and fetches\n  the image using `XWEATHER_CLIENT_ID` / `XWEATHER_CLIENT_SECRET` from the environment.\n\nRelated: the `weather-api` skill covers the Weather **data** API\n(`data.api.xweather.com`), and `mapsgl` covers the MapsGL JavaScript SDK. Raster Maps is\nthe server-rendered image product — reach for MapsGL instead when the user wants animated,\nstyleable, client-side layers.\n"
}

SHA-256 of public snapshot: 566a5b699cfb16d4e20c1544cad81047edcc272835e2c1ea3033cd9dd30150bd