Aller au contenu

Domaines skiables

Chaque requête nécessite une clé API; voir Authentification.

Le module Ski sert les domaines skiables canadiens construits à partir d'OpenStreetMap. Il a trois parties : une API des domaines skiables avec leurs faits d'altitude, de pistes, de remontées, d'orientation et de temps de route; la géométrie 3D des remontées de chaque domaine; et une superposition ski qui dessine pistes et remontées sur n'importe quel style, dans les couleurs qu'un skieur sait déjà lire. Les trois viennent d'une même version immuable, que chaque réponse nomme.

Des faits de terrain, pas des conseils de sécurité

Ces données décrivent où les pistes et les remontées sont cartographiées et la forme du terrain sous elles. Elles ne donnent aucun état en direct des remontées, des pistes ou du damage, et aucun danger d'avalanche, conseil d'itinéraire ni cote de sécurité d'aucune sorte. Une piste présente sur la carte n'est pas pour autant ouverte, damée ni à votre niveau. Consultez les rapports du domaine lui-même et, en terrain avalancheux, le bulletin d'avalanche public avant de partir.

Accès et tarifs

Chaque point de terminaison /ski et la superposition ski sont derrière le module Ski, SKU addon-ski, à 39 $ US par mois ou 390 $ US par an. Le module ne peut pas encore être acheté : ses prix n'existent pas, et la page des tarifs l'indique comme « Pas encore offert ». D'ici là :

  • Une clé payante sans le module reçoit 403 addon_required, qui nomme addon-ski.
  • Une clé du forfait dev est gratuite depuis une origine dev (localhost, 127.0.0.1, *.localhost, *.pages.dev et *.workers.dev) : vous pouvez donc construire toute l'intégration dès maintenant. Depuis une origine de production, elle reçoit 403 dev_only, et au-delà des appels premium du mois (5 000, additionnés sur tous les modules à accès contrôlé), elle reçoit usage_limit_reached.

Un refus n'est jamais facturé. Un 503 non plus : c'est ce que vous recevez, avec retryable: true, quand aucune version ski n'est publiée ou que son fichier est illisible. Un pays vide n'est jamais servi comme une liste vide. Voir Compléments et comptage pour le lien entre SKU et capacités, et Erreurs pour les corps d'erreur.

Domaines

Lister les domaines

GET /ski/areas?province=BC&activity=downhill

Renvoie tous les domaines de la version, triés par id, ou ceux qui répondent à tous les filtres donnés :

  • province est un code de province ou de territoire à deux lettres : AB, BC, MB, NB, NL, NS, NT, NU, ON, PE, QC, SK ou YT. Toute autre valeur est un 400.
  • activity vaut downhill (alpin) ou nordic (nordique). Un domaine qui offre les deux répond à l'un comme à l'autre.
  • bbox vaut ouest,sud,est,nord en degrés, et retient un domaine d'après son point location, pas son contour.
  • q retient les noms qui le contiennent, sans égard à la casse, aux accents ni à la ponctuation : mont sainte anne trouve Mont-Sainte-Anne. Un q fait uniquement de ponctuation retiendrait tout, c'est donc un 400.
curl "https://api.unmap.dev/ski/areas?q=sainte-anne&key=um_live_..."
curl "https://api.unmap.dev/ski/areas?bbox=-123.5,49,-122,50.5&activity=downhill&key=um_live_..."

Un domaine

GET /ski/areas/{id}

Passez un id tiré de la liste. Un id absent de la version est un 404 not_found.

Géométrie 3D des remontées

GET /ski/areas/{id}/lifts-3d

Les remontées du domaine en géométrie 3D : les gares, les pylônes et le câble qui les relie, chacun avec son altitude en mètres au-dessus du niveau de la mer, calculée à la construction à partir de la même version du terrain que les altitudes du domaine. Le schéma de la charge utile est unmap.ski-lifts-3d.v1. C'est ce que dessinent les câbles de remontées en 3D décrits sous Code client.

data vaut { schema, area_id, terrain_release, lifts }. Chaque remontée a id, name, aerialway, stations (les deux extrémités, au sol), pylons (chacun au sommet de son pylône) et cable, la ligne qui les relie avec sa flèche, chaque point valant [lng, lat, z]. Un domaine sans remontée dans OSM répond lifts: [].

La fiche d'un domaine

Chaque réponse est { data, meta } : data est un domaine, ou un tableau de domaines pour la liste.

{
  "data": {
    "id": "osm-way-123",
    "name": "Example Ski Hill",
    "province": "BC",
    "locality": "Example",
    "location": [-118.2, 50.9],
    "base": [-118.19, 50.95],
    "bbox": [-118.25, 50.88, -118.15, 50.97],
    "activities": ["downhill", "nordic"],
    "status": null,
    "websites": ["https://example.com"],
    "wikidata_id": null,
    "elevation": { "top_m": 2225, "base_m": 512, "vertical_m": 1713 },
    "runs": { "count": 75, "downhill_km": 68.4, "nordic_km": 12.1 },
    "lifts": { "count": 5 },
    "aspect": { "n": 0.31, "ne": 0.18, "e": 0.07, "se": 0.03, "s": 0.02, "sw": 0.05, "w": 0.14, "nw": 0.2 },
    "drive": { "from": "Kelowna", "minutes": 200 },
    "source": "OpenStreetMap",
    "licence": "ODbL-1.0"
  },
  "meta": {
    "attribution": "© OpenStreetMap contributors",
    "data_version": "2026-09-17.c6cf3548a49a"
  }
}

Les valeurs ci-dessus sont fictives, et meta est abrégé.

ChampCe que c'est
idosm-way-<n>, osm-relation-<n> ou osm-node-<n>, d'après l'objet OpenStreetMap dont le domaine est tiré. Stable d'une reconstruction à l'autre tant que cet objet existe.
nameLe nom cartographié dans OpenStreetMap.
provinceCode à deux lettres, ou "" quand le domaine n'a pas pu être situé.
localityLa localité la plus proche, selon notre géocodeur inverse.
locationUn point représentatif, [lng, lat]. C'est sur lui que bbox filtre.
base[lng, lat] de la gare de remontée la plus basse, là où se trouvent d'ordinaire la route et le stationnement. null quand le domaine n'a ni remontée ni piste.
bbox[ouest, sud, est, nord] du domaine.
activitiesdownhill, nordic, ou les deux.
statusL'état d'exploitation cartographié dans OpenStreetMap, ou null. Une étiquette cartographiée, pas les conditions du jour.
websitesLes sites Web du domaine, tels que cartographiés.
wikidata_idL'élément Wikidata, ou null.
elevation{ top_m, base_m, vertical_m } en mètres, échantillonnés dans la version 6 du terrain le long des remontées et des pistes du domaine. null quand il n'y a rien à échantillonner.
runs{ count, downhill_km, nordic_km }.
lifts{ count }.
aspectLa part de la longueur des pistes alpines orientée dans chaque direction, de n à nw, dont la somme vaut environ 1.
drive{ from, minutes } : le trajet en voiture le plus rapide depuis la région métropolitaine de recensement de 100 000 habitants ou plus la plus proche, sur le calcul d'itinéraires d'Unmap. null quand aucune n'est à la portée de la matrice d'itinéraires, ce qui est le cas de 27 domaines éloignés.
sourceLa provenance du domaine.
licenceLa licence du domaine.

Attribution et licence

Tout ce qui est ici est dérivé d'OpenStreetMap, statistiques calculées comprises, et relève donc de l'Open Database License (ODbL). Affichez « © OpenStreetMap contributors » partout où vous montrez les données ou la superposition; chaque réponse le porte dans meta.attribution. meta porte aussi les champs de source et de fraîcheur du registre, ainsi que data_version, la version exacte qui a répondu. Mettez en cache selon data_version : une version publiée ne change jamais.

La superposition ski

Ajoutez overlays=ski à l'URL d'un style. Elle se dessine sur n'importe quel style et est faite pour winter, dont le sol blanc et discret laisse les couleurs des pistes porter le contenu. Ajoutez terrain=on pour la draper sur le terrain en 3D. Les deux sont documentés sur la page API de cartes.

curl "https://api.unmap.dev/styles/winter.json?overlays=ski&terrain=on&key=um_live_..."
import { Unmap } from "@unmap/sdk";
 
const unmap = new Unmap({
  key: "um_live_...",
  container: "map",
  style: "winter",
  overlays: ["ski"],
  center: [-118.16, 50.96],
  zoom: 12,
});

Les tuiles de la superposition portent quatre couches sources, que vous pouvez styler ou interroger vous-même :

Couche sourceGéométriePropriétés
ski_areasContours des domainesid, name
ski_area_labelsPoints d'étiquetteid, name
runsLignespiste_type (downhill ou nordic), difficulty, name, pitch_avg_deg (pente moyenne en degrés) et aspect (orientation, en degrés), là où le terrain a pu être échantillonné
liftsLignesaerialway (le type de remontée dans OpenStreetMap), name

Chaque objet porte aussi source et licence. Les contours s'affichent dès le zoom 9, les pistes et les remontées dès le zoom 11, et les noms de pistes dès le zoom 14.

Couleurs des pistes

Les pistes alpines suivent la convention nord-américaine :

difficultyDessinée en
novice, easyCercle vert : vert
intermediateCarré bleu : bleu
advancedLosange noir : noir
expert, freeride, extremeDouble losange noir : noir, en trait plus épais
parkParc à neige : orange

Une piste cartographiée sans difficulté prend la couleur des limites du style plutôt qu'une cote que personne n'a donnée. Les pistes nordiques sont en tirets. Sur un style sombre, les pistes noires et doubles noires se dessinent en clair, parce que du noir sur un sol sombre ne se lit pas.

Ces couleurs ne viennent ni du style ni d'un thème. C'est une convention que le skieur lit avant la carte, donc un thème ne peut pas rendre un losange noir rose. Elles sont testées pour garder un contraste de 3:1 avec le sol sur chaque style.

Code client

SDK

@unmap/sdk expose les trois points de terminaison par unmap.ski :

import { Unmap } from "@unmap/sdk";
 
const unmap = new Unmap({ key: "um_live_..." });
 
const areas = await unmap.ski.areas({ province: "QC", activity: "downhill", q: "mont" });
const first = areas.data[0];
if (first) {
  const area = await unmap.ski.area(first.id);
  const lifts = await unmap.ski.lifts3d(first.id);
}

unmap.ski.areas({ province, activity, bbox, q }) prend les mêmes filtres que l'API. Chaque méthode renvoie { data, meta }.

Bloc d'exploration des domaines skiables

ski-resort-explorer est une page entière construite à partir du registre : chercher et filtrer les domaines, en voir un sur la carte avec la superposition ski, et lire ses faits. Installez-le comme tout autre bloc :

npx shadcn@latest registry add @unmap=https://registry.unmap.dev/r/{name}.json
npx shadcn@latest add @unmap/ski-resort-explorer
npx shadcn-vue@latest add https://registry.unmap.dev/r/vue/ski-resort-explorer.json

Les deux premières lignes sont la voie React; la troisième est Vue et Nuxt, où shadcn-vue prend directement l'URL de l'élément. Activez sa propriété lifts3d pour tracer les câbles de la station choisie avec @unmap/deck, chargé seulement au choix d'une station.

Câbles de remontées en 3D

@unmap/deck dessine la géométrie lifts-3d avec deck.gl, entrelacé dans le contexte WebGL de la carte elle-même. C'est un paquet distinct : une carte qui ne dessine pas de remontées ne charge jamais deck.gl.

import { createMap } from "@unmap/maps";
import { createDeckOverlay, deckMapOptions, fetchLifts3d, liftCablesLayer } from "@unmap/deck";
 
const key = "um_live_...";
const map = createMap({ key, container: "map", style: "winter", terrain: true, maplibre: deckMapOptions });
const lifts = await fetchLifts3d({ key, areaId: "osm-way-474288286" });
createDeckOverlay(map).setLayers([liftCablesLayer(lifts)]);

deckMapOptions active l'anticrénelage, que MapLibre laisse désactivé et sans lequel les câbles ont des bords crénelés. Les hauteurs sont précalculées, jamais lues dans la carte au moment du rendu : si vous changez l'amplification du terrain, passez la même exaggeration à liftCablesLayer.

Couverture et limites

  • La version actuelle est 2026-09-17.c6cf3548a49a : OpenStreetMap au 2026-09-17, lu dans le même extrait canadien que celui du graphe d'itinéraires. Elle compte 226 domaines nommés, 21 095 pistes et 1 121 remontées.
  • Elle ne contient que ce qu'OpenStreetMap cartographie. Dans un échantillon de référence de 112 domaines skiables canadiens, 94 % avaient à la fois des pistes et des remontées cartographiées; ce sont surtout les petites stations qui manquent.
  • Les altitudes viennent de la version 6 du terrain. Les dénivelés concordent à environ 1 % près avec les chiffres publiés des domaines, sauf là où la gare de remontée la plus haute est sous le sommet.
  • Aucun état en direct des remontées, des pistes ou du damage, et aucun danger d'avalanche, conseil d'itinéraire ni cote de sécurité d'aucune sorte.

Prochaines étapes