Vent, houle et marées
pour développeurs
Mesures en temps réel de 13 000+ stations vent dans le monde (≈ 35 sources : services météo nationaux, aéroports, balises de spots, réseaux communautaires), de ~470 bouées houlographes (15 réseaux), marées de ~2 000 ports avec coefficients, prévisions et vent animé mondial. Données agrégées et normalisées dans un schéma unique.
| URL de base | https://api.levent.live/api |
| Authentification | En-tête X-API-Key (ou ?apikey=) |
| Format | JSON UTF-8, compressé br / gzip |
| Unités | Vent en nœuds · directions en degrés · heures ISO 8601 UTC |
| Limite | 120 requêtes / minute par clé (par défaut) |
| Rafraîchissement | Stations : liste reconstruite toutes les 2 min · Bouées : 5 min |
| Historique | Stations : 168 h max · Bouées : ~7 jours |
| Spécification | OpenAPI 3.1 — levent.live/openapi.json |
Authentification & CORS
Chaque requête porte votre clé dans l’en-tête X-API-Key. Le paramètre ?apikey= est accepté aussi, mais il apparaît dans les journaux et l’historique : préférez l’en-tête.
curl --compressed -H "X-API-Key: votre_cle_ici" \ "https://api.levent.live/api/all-buoys"
| Réponse | Cause |
|---|---|
| 401 API key required | Aucune clé fournie |
| 403 Invalid API key | Clé inconnue ou désactivée |
| 403 Origin not allowed | Appel depuis un navigateur sur une origine non autorisée pour cette clé |
| 429 Rate limit exceeded | Limite par minute de la clé dépassée (voir Limites) |
Un appel fetch depuis une page web envoie un en-tête Origin. Il n’est accepté que si cette origine (ex. https://www.monclub.fr) est enregistrée sur votre clé (allowedOrigins) : indiquez-nous vos domaines lors de la demande de clé. Les appels sans Origin (serveur, script, application mobile) ne sont pas concernés.
Les en-têtes X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After et ETag sont lisibles depuis JavaScript (Access-Control-Expose-Headers).
Demander une clé gratuite : contact@levent.live (usage prévu, volume estimé, domaines web éventuels).
Quickstart
Votre premier appel en 2 minutes. Les bibliothèques HTTP courantes (fetch, requests, URLSession) gèrent la compression automatiquement ; avec curl, ajoutez --compressed.
curl --compressed -H "X-API-Key: VOTRE_CLE" \ "https://api.levent.live/api/stations-lite?near=48.38,-4.49&radius=20&online=1&fields=name,wind,gust,direction,ts,distanceKm"
# Bretagne : lat 47.2 → 48.9, lon -5 → -1, stations en ligne de Météo-France curl --compressed -H "X-API-Key: VOTRE_CLE" \ "https://api.levent.live/api/all-stations?source=meteofrance&bbox=47.2,-5,48.9,-1&online=true"
curl --compressed -H "X-API-Key: VOTRE_CLE" \ "https://api.levent.live/api/all-stations?history=meteofrance_29075001&hours=24"
# Liste complète (~13 000 stations, ~0,5 Mo compressé) + ETag
curl --compressed -sD headers.txt -o stations.json -H "X-API-Key: VOTRE_CLE" \
"https://api.levent.live/api/all-stations"
ETAG=$(grep -i '^etag:' headers.txt | cut -d' ' -f2- | tr -d '\r')
# 2 minutes plus tard : 304 Not Modified (corps vide) si la liste n’a pas changé
curl --compressed -s -o /dev/null -w "%{http_code}\n" -H "X-API-Key: VOTRE_CLE" \
-H "If-None-Match: $ETAG" "https://api.levent.live/api/all-stations"Conventions
| Grandeur | Unité / format |
|---|---|
| Vent moyen, rafales (stations) | nœuds (kn), 1 décimale |
| Direction du vent | degrés 0–359, direction d’où vient le vent (0 = nord, 90 = est) |
| Température, humidité, pression | °C · % · hPa, 1 décimale |
| Hauteurs de houle · période · direction | m · s · degrés, d’où vient la houle |
| Hauteurs de marée | m au-dessus du zéro des cartes du port |
| Heures | ISO 8601 en UTC (ex. 2026-10-15T12:36:00.000Z) |
| Coordonnées | degrés décimaux WGS84 (lat, lon) |
| Prévisions (/forecast) | km/h par défaut (format Open-Meteo) : demandez wind_speed_unit=kn |
- Identifiants : utilisez
stableId(<source>_<id>, ex.meteofrance_29075001), unique dans toute l’API. Le champidbrut peut exister dans plusieurs sources (ex.1475chez Holfuy et chez Pioupiou). tsest l’heure de la mesure (UTC), pas l’heure de collecte ; il peut êtrenullpour une station hors ligne.cachedAtest l’heure à laquelle Le Vent a reconstruit la liste.isOnlineest évalué par chaque source (de 30 min à plusieurs heures pour les réseaux horaires ou tri-horaires) : pour un affichage « temps réel », vérifiez aussi l’âge dets.- Valeurs absentes :
nullpour les grandeurs facultatives (température, humidité, pression, altitude). Quand une source ne mesure pas les rafales (BoM, une partie des METAR / SYNOP),gustvautwindou 0. - Nouvelles sources : la liste des valeurs de
sources’allonge régulièrement. Traitez une valeur inconnue comme une source générique, sans erreur. - Champs additionnels : de nouveaux champs facultatifs peuvent apparaître ; ignorez ceux que vous ne connaissez pas. Un champ existant ne change ni de nom ni d’unité dans la v1.
Stations vent
/api/all-stationsToutes les stations vent avec leur dernière mesure, normalisées dans le schéma Station. La liste est reconstruite toutes les 2 minutes à partir de toutes les sources.
sourcebboxonline{
"stations": [
{
"id": "29075001",
"stableId": "meteofrance_29075001",
"name": "Brest",
"lat": 48.453833,
"lon": -4.391167,
"wind": 8.4,
"gust": 11.9,
"direction": 240,
"source": "meteofrance",
"ts": "2026-10-15T12:42:00.000Z",
"isOnline": true,
"temperature": 18.6,
"humidity": 81,
"pressure": 1021.9,
"altitude": null
},
{
"id": "10045",
"stableId": "meteogalicia_10045",
"name": "Mabegondo",
"…": "…",
"attribution": "Fonte: MeteoGalicia – Xunta de Galicia"
}
],
"count": 13189,
"sources": { "meteofrance": 179, "holfuy": 1162, "netatmo": 2665, "kv-stations": 5582, "…": 0 },
"cachedAt": "2026-10-15T12:51:07.636Z",
"refreshInterval": 120
}ETag. Renvoyez-le dans If-None-Match : tant que la liste n’a pas été reconstruite, la réponse est un 304 sans corps. Pour quelques stations ou une zone, préférez /api/stations-lite.L’objet sources compte les stations par flux amont : kv-stations regroupe les services météo nationaux (MET Norway, AEMET, DWD, SYNOP…) et windguru / gowind-native restent à 0 (flux arrêtés). Pour un décompte par source, comptez le champ source des stations.
Sélection légère de stationsnouveau
/api/stations-literecommandéLes mêmes stations que /api/all-stations, mais seulement celles qui vous intéressent, avec seulement les champs utiles. Idéal pour un tableau de bord, un écran TV, un widget ou un site de club. Les filtres se combinent ; au moins un des filtres ids, bbox, near, source ou since est requis.
idsstableId séparés par des virgules. Réponse dans l’ordre demandé ; les identifiants introuvables sont listés dans missing. Un id brut (ex. 29075001) est accepté mais peut correspondre à plusieurs sources.bboxneardistanceKm.radiussourcesinceonlinefieldsname,wind,gust,direction,ts. stableId est toujours inclus, ainsi que attribution quand la source l’exige.limittruncated: true si la réponse est coupée.curl --compressed -H "X-API-Key: VOTRE_CLE" \ "https://api.levent.live/api/stations-lite?ids=meteofrance_29075001,holfuy_1062,pioupiou_110&fields=name,wind,gust,direction,ts,isOnline"
{
"stations": [
{ "stableId": "meteofrance_29075001", "name": "Brest", "wind": 8.4, "gust": 11.9,
"direction": 240, "ts": "2026-10-15T12:42:00.000Z", "isOnline": true },
{ "stableId": "holfuy_1062", "name": "Pilotage BREST", "wind": 7.6, "gust": 9.1,
"direction": 235, "ts": "2026-10-15T12:45:00.000Z", "isOnline": true }
],
"count": 2,
"cachedAt": "2026-10-15T13:04:30.112Z",
"refreshInterval": 120,
"missing": ["pioupiou_110"]
}ETag ne dépend que de la version de la liste et de votre requête : en interrogeant toutes les 1–2 minutes avec If-None-Match, vous recevez un 304 immédiat tant que rien n’a changé. Erreurs de paramètres : 400 avec error et hint.Historique station
/api/all-stations?history={stableId}Les mesures récentes d’une station. La source est déduite du préfixe de l’identifiant. Le pas de temps dépend de la source (1 à 10 min pour la plupart des balises et services nationaux, 30 min à 3 h pour METAR / SYNOP).
historyrequishours{
"stationId": "meteofrance_29075001",
"name": "Brest",
"source": "meteofrance",
"hours": 24,
"count": 240,
"observations": [
{ "ts": "2026-10-15T10:54:00.000Z", "wind": 10.5, "gust": 14.8, "direction": 200, "temperature": null }
],
"attribution": "…"
}attribution n’est présent que pour les sources qui l’exigent. observations peut être vide (station sans historique, ou station ajoutée sans mesure, source custom). 502 si la source ne répond pas : réessayez plus tard.
Bouées houlographes
/api/all-buoys~470 bouées de 15 réseaux : CANDHIS (France), NOAA NDBC, Cefas, Rijkswaterstaat, Irish Lights, Marine Institute, ISPRA, Arpae, SMHI, FMI, Vegagerðin, MET Norway, IMOS / AODN, Queensland, South Island Waves. Rafraîchi toutes les 5 minutes.
sourceregionbbox{
"buoys": [
{
"id": "01101",
"name": "Leucate",
"lat": 42.9167,
"lon": 3.125,
"region": "mediterranee",
"depth": 40,
"hm0": 0.2,
"hmax": 0.3,
"tp": 3.1,
"direction": 18,
"spread": 26,
"seaTemp": 21.4,
"status": "TOTALE",
"lastUpdate": "2026-10-15T12:30:00.000Z",
"source": "candhis",
"attribution": null
}
],
"count": 470,
"sources": { "candhis": 22, "ndbc": 190, "aodn": 61, "rws": 48, "…": 0 },
"cachedAt": "2026-10-15T12:50:49.443Z",
"refreshInterval": 300
}Historique bouée
/api/all-buoys?history={id}Environ 7 jours de mesures brutes (pas de 10 à 60 min selon le réseau). Les identifiants CANDHIS sont numériques (02911), les autres réseaux sont préfixés (ndbc_41002, rws_a12…).
historyrequis{
"buoyId": "rws_a12",
"name": "A12",
"source": "rws",
"region": "Pays-Bas",
"count": 1005,
"observations": [
{ "timestamp": "2026-10-15T12:40:00.000Z", "hm0": 2.5, "hmax": null, "tp": 7.7, "direction": null, "seaTemp": null }
],
"attribution": "Rijkswaterstaat — Waterinfo / WaterWebservices (CC0)"
}Attention : l’horodatage des observations de bouées s’appelle timestamp (et non ts). Les grandeurs non mesurées par un réseau valent null.
Marées
/api/tide?lat={lat}&lon={lon}/api/tide?port={code}/api/tide?list=true&scope=worldPleines et basses mers avec coefficients. Hors des ports français du SHOM, Le Vent calcule les marées de ~2 000 ports à partir de constantes harmoniques publiées (TICON-4, NOAA, Kartverket, modèle EOT20), ainsi qu’un coefficient « équivalent SHOM ».
lat, londistanceKm.maxKmscopeworld (ports calculés par Le Vent), fr (ports SHOM) ou all. Avec lat/lon, défaut all.portcst) ou nom d’un port de la liste.listtrue : liste des ports (cst, name, lat, lon, region, country) selon scope (défaut fr).dateduration# Port le plus proche de Plymouth (Royaume-Uni), 2 jours curl --compressed -H "X-API-Key: VOTRE_CLE" \ "https://api.levent.live/api/tide?lat=50.36&lon=-4.14&maxKm=50&scope=world&duration=2"
{
"port": { "cst": "TC_DEVONPORT_DEV_GBR_BODC", "name": "Devonport", "lat": 50.3684, "lon": -4.1852,
"region": "royaume-uni", "country": "GB", "countryName": "Royaume-Uni", "source": "TICON-4" },
"distanceKm": 3.3,
"tides": [
{ "type": "high", "date": "2026-10-15", "time": "08:48", "datetime": "2026-10-15T07:48:00.000Z",
"height": 5.1, "coefficient": 73 },
{ "type": "low", "date": "2026-10-15", "time": "15:09", "datetime": "2026-10-15T14:09:00.000Z",
"height": 1.44, "coefficient": null }
],
"nextHighTide": { "time": "2026-10-15T20:03:00.000Z", "height": 4.85, "coefficient": 68 },
"nextLowTide": { "time": "2026-10-15T14:09:00.000Z", "height": 1.44 },
"todayCoefficient": 73,
"coefficientSource": "computed",
"coefficientReason": null,
"coefficientNote": "Coefficient calculé par Le Vent (équivalent SHOM), non officiel",
"source": "TICON-4",
"sourceLabel": "Marées : TICON-4 (DGFI-TUM, CC BY 4.0) via Neaps — calcul Le Vent, ne pas utiliser pour la navigation",
"model": false,
"fallback": false,
"datum": "LAT",
"timezone": "Europe/London",
"attribution": "Neaps tide database (…). Source: Hart-Davis, M., Dettmering, D., Seitz, F. (2025), TICON-4 (…). Licensed CC BY 4.0 (…)",
"fetchedAt": "2026-10-15T12:53:34.846Z"
}date, timestringJour et heure locale du port (fuseau timezone).datetimestringMême instant en UTC (ISO 8601) : à utiliser pour les calculs.heightnumberHauteur en m au-dessus du zéro des cartes (datum : LAT dans la plupart des pays, MLLW aux États-Unis).coefficientnumber | nullSur les pleines mers uniquement (20–120).coefficientSource'shom' | 'computed' | nullshom : coefficient officiel ; computed : calculé par Le Vent (équivalent SHOM, non officiel) ; null : pas de coefficient.coefficientReason'diurnal' | 'small-tide' | nullPourquoi il n’y a pas de coefficient : marée à dominante diurne, ou marnage trop faible (Méditerranée…).coefficientNotestring | nullPhrase prête à afficher à côté du coefficient.model, fallbackbooleanEstimation de modèle (EOT20) loin de tout marégraphe ; prédiction de secours quand le SHOM est indisponible.attribution, sourceLabelstringCrédit complet (licence CC BY) et version courte : à afficher avec les marées.scope=world ou contactez-nous. Une indisponibilité de la source peut être signalée par une réponse 200 contenant un champ error : testez-le.Prévisions
/api/forecastPrévisions horaires et quotidiennes (vent, météo, vagues) au format Open-Meteo, servies depuis le cache partagé de Le Vent. Les coordonnées sont arrondies à 0,01° (~1 km).
modelarome (défaut — Météo-France AROME/ARPEGE, 4 j, France et alentours), ecmwf (ECMWF IFS 0,25°, 10 j, monde), gfs (NOAA GFS, 16 j), icon (DWD ICON-EU / ICON, 7 j), marine (vagues et houle, 7 j). Indiquez toujours le modèle.latitude, longituderequishourlydailywind_speed_unitkmh (défaut), kn, ms, mph.timezoneGMT (défaut, = UTC), Europe/Paris ou auto. Les heures renvoyées sont locales à ce fuseau, sans décalage (ex. 2026-10-15T14:00).forecast_days# Vent prévu à Brest (ECMWF), en nœuds, heures UTC, 2 jours curl --compressed -H "X-API-Key: VOTRE_CLE" \ "https://api.levent.live/api/forecast?model=ecmwf&latitude=48.38&longitude=-4.49&hourly=wind_speed_10m,wind_gusts_10m,wind_direction_10m&wind_speed_unit=kn&timezone=GMT&forecast_days=2"
429 au-delà de 300 requêtes/min par IP, 503 + Retry-After quand le quota journalier est atteint. Les modèles ne changent que toutes les 1 à 6 h : gardez une prévision au moins 30 min en cache. En-tête X-Cache : HIT / MISS / STALE. Crédit à afficher : « Prévisions : Open-Meteo.com (CC BY 4.0) » et le modèle (Météo-France, ECMWF, NOAA, DWD).Vent animé mondial (grilles)
/api/wind-world?model=ecmwfsans cléVent à 10 m prévu sur une grille mondiale, toutes les 3 h jusqu’à +120 h, pour animer une carte. Modèles : ecmwf (défaut, 0,25°), gfs (0,5°), icon_eu (0,125°, Europe). Endpoint public : pas de clé nécessaire.
| Requête | Réponse |
|---|---|
| ?model=ecmwf | Index JSON : run, runTime, grid, overview, tileCells, tilesX, tilesY, frames [{ step, validTime }], attribution |
| ?model=ecmwf&run=R&step=S&tile=X_Y | Tuile binaire WWND (64×64 cellules, pleine résolution), immuable |
| ?model=ecmwf&run=R&step=S&overview=1 | Grille binaire globale grossière (1°) |
| ?model=ecmwf&format=web&t=H | JSON prêt pour WindGL, échéance la plus proche de « heure courante + H » ; repli GFS si ECMWF manque (en-têtes X-Wind-Model, X-Wind-Run, X-Wind-Valid-Time) |
Format binaire WWND v1 (little-endian, servi en gzip) : en-tête de 40 octets — "WWND", u16 version, u16 flags (bit 0 : 360°, bit 1 : canal vitesse), u16 nx, u16 ny, f32 lon0, f32 lat0, f32 dLon, f32 dLat, f32 scale (m/s par unité), u32 validTime, u32 runTime — puis Int16 u[nx·ny], Int16 v[nx·ny] (lignes du sud au nord, colonnes d’ouest en est, −32768 = manquant).
Les tuiles d’un run ne changent jamais (cache 7 jours) ; relisez l’index toutes les 10–30 min. Crédits : ECMWF (CC BY 4.0), NOAA GFS (domaine public), DWD ICON-EU.
Webcams
/api/webcams~700 webcams de spots (côtes et lacs) en ligne : tableau JSON d’objets id, name, location, region, latitude, longitude (attention : pas lat/lon), imageUrl, streamUrl (HLS ou lecteur YouTube, sinon null), source (exploitant), refreshInterval (s), lastCapture, et pour certaines provider, country, linkUrl, attribution.
linkUrl quand il existe).Sources & fréquences
Valeur du champ source, nombre de stations (production, 15 octobre 2026) et fréquence à laquelle Le Vent relit la source. Le pas des mesures elles-mêmes va de 1 min (balises) à 3 h (SYNOP).
| Source | source | Stations | Zone | Relue | Crédit |
|---|---|---|---|---|---|
| Météo-France | meteofrance | ~180 | France, Corse, Réunion, Mayotte | 6 min | Météo-France — Licence Ouverte Etalab 2.0 |
| MET Norway | metnorway | ~730 | Norvège, Svalbard | 10 min | MET Norway — NLOD 2.0 / CC BY 4.0 |
| AEMET | aemet | ~710 | Espagne | 30 min (relevés horaires) | Fuente: AEMET |
| MeteoGalicia | meteogalicia | ~140 | Galice | 10 min | Fonte: MeteoGalicia – Xunta de Galicia |
| Meteocat | meteocat | ~160 | Catalogne | 15 min (créneaux de 30 min) | Font: Servei Meteorològic de Catalunya |
| IPMA | ipma | ~115 | Portugal, Madère, Açores | 5 min (relevés horaires) | IPMA |
| MeteoSwiss | meteoswiss | ~155 | Suisse | 15 min | MeteoSwiss |
| DWD | dwd | ~190 | Allemagne | 1 h | Deutscher Wetterdienst |
| SMHI | smhi | ~180 | Suède | 30 min | SMHI — CC BY 4.0 |
| FMI | fmi | ~150 | Finlande | 15 min | FMI — CC BY 4.0 |
| DMI | dmi | ~90 | Danemark | 15 min | DMI |
| GeoSphere Austria | geosphere | ~145 | Autriche | 10 min | GeoSphere Austria |
| HungaroMet (OMSZ) | omsz | ~140 | Hongrie | 15 min | HungaroMet |
| IMGW-PIB | imgw | ~315 | Pologne | 30 min | IMGW-PIB |
| DHMZ | dhmz | ~75 | Croatie | 30 min | DHMZ |
| ARSO | arso | ~16 | Slovénie | 30 min | ARSO |
| IRM / KMI | rmi | ~27 | Belgique | 30 min | IRM / KMI |
| Met Éireann | meteirann | ~18 | Irlande | 1 h | Met Éireann |
| Bureau of Meteorology | bom | ~600 | Australie (sans rafales) | 15 min | BoM via DWD open data — CC BY 4.0 |
| SYNOP OMM | synop | ~430 | Afrique, Asie, Pacifique, Amérique latine | 30 min (relevés 1–3 h) | Services météo nationaux (GTS) via DWD / WIS2 / IEM |
| METAR | metar | ~690 | Aéroports du monde | 20 min | aviationweather.gov (NOAA) |
| IEM ASOS | iem | ~1 140 | États-Unis, Brésil, Afrique, Australie | 30 min | Iowa Environmental Mesonet |
| NOAA NDBC / CO-OPS | ndbc | ~12 | Bouées et ports NOAA (Amériques, Manche) | 5–10 min | NOAA — domaine public |
| Source | source | Stations | Zone | Relue |
|---|---|---|---|---|
| Netatmo | netatmo | ~2 660 | Stations personnelles près des côtes et plans d’eau | 7 min |
| Weathercloud | weathercloud | ~2 120 | Stations personnelles (côtes, lacs, îles) | 7 min |
| Holfuy | holfuy | ~1 160 | Balises spots (Europe) | 10 min |
| Pioupiou (OpenWindMap) | pioupiou | ~650 | Balises communautaires | 5 min |
| kwind | kwind | ~100 | Balises spots (Europe) | 3 min |
| Infoclimat | infoclimat | ~45 | Réseau StatIC + SYNOP (France) | 5 min |
| Wind France | windfrance | ~19 | Bretagne, Atlantique | 2 min |
| APRS | aprs | ~19 | Stations radioamateurs (APRS-IS) | temps réel |
| Diabox | diabox | ~5 | Capteurs de clubs / ports | 5 min |
| Weameter | weameter | ~4 | Lacanau, Pauillac, Montamer, Leucate | 2 min |
| Fildair | fildair | 1 | Mèze (étang de Thau) | 3 min |
windguru,gowind-native: sources désactivées (flux gowind.fr supprimé le 23 juin 2026), plus aucune station.custom: station ajoutée par Le Vent sans mesure (nom et position seulement, toujours hors ligne).- En cours d’intégration, peuvent apparaître :
metoffice(Royaume-Uni),italia(réseaux publics italiens),asia(Japon, Hong Kong, Singapour, Taïwan),eccc(Canada),ccomet(côtes anglaises),inmet(Brésil).
Licences & crédits
Les mesures appartiennent à leurs producteurs. Le Vent les collecte, convertit (unités, arrondis, UTC) et regroupe ; ce ne sont pas des produits officiels de ces organismes. En utilisant l’API, vous vous engagez à :
- Afficher le champ
attributionquand il est présent (stations, historiques, bouées, marées) : c’est la mention exigée par la licence de la source (CC BY 4.0, NLOD, etc.). - Citer la source et Le Vent partout où les données sont affichées, par ex. « Données : MET Norway via Le Vent (levent.live) ».
- Respecter les réseaux privés et communautaires (Netatmo, Weathercloud, Holfuy, Pioupiou / OpenWindMap, kwind, Wind France, Diabox, Weameter, Fildair, Infoclimat, APRS) : sauf licence ouverte publiée par le réseau lui-même (vérifiez ses conditions), leurs données ne sont pas en libre réutilisation. Usage personnel, associatif ou d’affichage uniquement ; pas de revente, d’archivage massif ni de redistribution en flux sans accord du réseau.
- Ne pas présenter ces mesures, marées ou prévisions comme des données de sécurité ou de navigation.
rws — Rijkswaterstaat (Pays-Bas) · CC0irishlights — Commissioners of Irish Lights (Irlande) · CC BY 4.0ispra — ISPRA — Rete Ondametrica Nazionale (Italie) · CC BY 4.0arpae — Arpae Emilia-Romagna (Italie) · CC BY 4.0smhi — SMHI (Suède) · CC BY 4.0fmi — FMI — Ilmatieteen laitos (Finlande) · CC BY 4.0vegagerdin — Vegagerðin (Islande) · CC BY 4.0aodn — IMOS / AODN (Australie) · CC BY 4.0siw — University of Canterbury — South Island Waves (Nouvelle-Zélande) · CC BY 4.0Crédits complets des bouées et des marées (TICON-4, NOAA, Kartverket, EOT20, Neaps) : page Sources.
Schéma des objets
idstringIdentifiant brut chez la source (ex. 29075001)stableIdstringIdentifiant unique : <source>_<id> (ex. meteofrance_29075001)namestringNom de la stationlat, lonnumberPosition (degrés décimaux, WGS84)windnumberVent moyen, nœuds (1 décimale)gustnumberRafale max, nœuds (1 décimale) ; = wind ou 0 si non mesuréedirectionnumberDirection d’où vient le vent, 0–359°sourcestringSource (voir Sources)tsstring | nullHeure de la mesure, ISO 8601 UTCisOnlinebooleanMesure récente selon la sourcetemperaturenumber | nullTempérature de l’air, °Chumiditynumber | nullHumidité relative, %pressurenumber | nullPression, hPaaltitudenumber | nullAltitude, mattributionstring (facultatif)Mention exigée par la licence de la source, à afficherdistanceKmnumber (stations-lite)Distance au point near, kmtsstringHeure de la mesure, ISO 8601 UTCwind, gustnumberNœudsdirectionnumberDegréstemperaturenumber | null°CidstringIdentifiant (CANDHIS : 02911 ; autres : <réseau>_<id>)name, lat, lonstring, numberNom et positionregionstring | nullRégion (CANDHIS : bretagne, mediterranee… ; autres : pays ou État)depthnumber | nullProfondeur, mhm0number | nullHauteur significative, mhmaxnumber | nullHauteur maximale, mtpnumber | nullPériode pic, sdirectionnumber | nullDirection d’où vient la houle, °spreadnumber | nullÉtalement directionnel, °seaTempnumber | nullTempérature de l’eau, °Cstatusstring | nullonline / offline (CANDHIS : état de diffusion, ex. TOTALE)lastUpdatestring | nullHeure de la dernière mesure, ISO 8601 UTCsourcestringRéseauattributionstring | nullMention exigée par la licence du réseauCodes de réponse
Les erreurs sont du JSON : { "error": "…" }, parfois avec hint.
| Code | Signification | Cause |
|---|---|---|
| 200 | OK | Requête réussie |
| 304 | Not Modified | If-None-Match identique à l’ETag courant : rien de nouveau |
| 400 | Bad Request | Paramètre invalide (stations-lite, tide, forecast) |
| 401 | Unauthorized | Clé API absente |
| 403 | Forbidden | Clé invalide, origine navigateur non autorisée pour la clé, ou domaine bloqué |
| 404 | Not Found | Station, bouée, port ou fichier introuvable |
| 429 | Too Many Requests | Limite de la clé dépassée (attendre Retry-After secondes) |
| 500 | Internal Server Error | Erreur interne |
| 502 | Bad Gateway | La source amont ne répond pas (historiques, prévisions) |
| 503 | Service Unavailable | Liste pas encore prête après un redémarrage, ou quota de prévisions atteint |
Limites, cache & bonnes pratiques
Chaque clé a une limite par minute (120 par défaut), comptée sur des fenêtres fixes d’une minute. Chaque réponse indique X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset (secondes avant la remise à zéro). Au-delà : 429 avec Retry-After. Les réponses 304 comptent comme des requêtes, mais ne coûtent presque rien.
| Donnée | Change | Interroger au plus |
|---|---|---|
| Stations (liste, stations-lite) | toutes les 2 min (cachedAt) | 1 fois / 1–2 min, avec If-None-Match |
| Historique d’une station | au rythme de la source | 1 fois / 5–10 min par station |
| Bouées | toutes les 5 min | 1 fois / 5 min |
| Historique d’une bouée | 10–60 min | 1 fois / 30 min |
| Marées | jamais (prédictions) | 1 fois / jour par port |
| Prévisions | nouveau run toutes les 1–6 h | 1 fois / 30–60 min par point |
| Vent animé (index) | nouveau run toutes les 6–12 h | 1 fois / 10–30 min ; tuiles immuables |
| Webcams (liste) | rarement | 1 fois / heure |
- Acceptez la compression (
Accept-Encoding: br, gzip, automatique sauf avec curl sans--compressed) : 8 fois moins de données. - Ne téléchargez pas les 13 000 stations pour en afficher quelques-unes :
/api/stations-liteavecids,nearoubbox, etfields. - Pour un site public, interrogez l’API depuis votre serveur et servez vos visiteurs depuis votre cache : une requête toutes les 2 minutes suffit, quel que soit votre trafic.
- Gérez
429(attendreRetry-After) et5xx(réessayer avec un délai croissant) ; gardez la dernière réponse valide en cas d’erreur.
Exemples complets
// Tableau de bord : quelques stations rafraîchies toutes les 2 minutes, avec ETag
const API = "https://api.levent.live/api";
const KEY = "VOTRE_CLE"; // côté serveur, ou clé limitée à vos origines
const ids = ["meteofrance_29075001", "holfuy_1062", "pioupiou_1475"];
let etag = null;
let stations = [];
async function refresh() {
const res = await fetch(`${API}/stations-lite?ids=${ids.join(",")}&fields=name,wind,gust,direction,ts,isOnline`, {
headers: { "X-API-Key": KEY, ...(etag ? { "If-None-Match": etag } : {}) },
});
if (res.status === 304) return; // rien de nouveau
if (res.status === 429) { // limite atteinte : attendre
const wait = Number(res.headers.get("Retry-After") || 60);
return new Promise(r => setTimeout(r, wait * 1000));
}
if (!res.ok) throw new Error(`HTTP ${res.status}`);
etag = res.headers.get("ETag");
const data = await res.json();
stations = data.stations;
if (data.missing?.length) console.warn("Stations introuvables :", data.missing);
for (const s of stations) {
const age = Math.round((Date.now() - Date.parse(s.ts)) / 60000);
console.log(`${s.name} : ${s.wind} nds (${s.gust}) ${s.direction}° — il y a ${age} min`);
}
}
await refresh();
setInterval(() => refresh().catch(console.error), 120_000);import csv
import requests
API = "https://api.levent.live/api"
r = requests.get(
f"{API}/all-stations",
headers={"X-API-Key": "VOTRE_CLE"},
params={"history": "meteofrance_29075001", "hours": 24},
timeout=30,
)
r.raise_for_status()
data = r.json()
with open("historique.csv", "w", newline="") as f:
w = csv.writer(f)
w.writerow(["ts_utc", "vent_nds", "rafales_nds", "direction_deg", "temperature_c"])
for o in data["observations"]:
w.writerow([o["ts"], o["wind"], o["gust"], o["direction"], o["temperature"]])
print(f"{data['name']} : {data['count']} relevés sur {data['hours']} h → historique.csv")curl --compressed -H "X-API-Key: VOTRE_CLE" \ "https://api.levent.live/api/all-buoys?region=mediterranee"
Changelog
- Nouvel endpoint /api/stations-lite : sélection par ids, bbox (antiméridien compris), near + radius, source, since, online, fields, limit ; ETag dépendant de la requête.
- /api/all-stations : liste complète pré-compressée (brotli ~0,46 Mo au lieu de ~0,57 Mo gzip), ETag et 304 sans calcul ; online=1 accepté.
- Historique station par stableId : name et attribution renvoyés (le nom valait l’identifiant). hours borné à 1–168.
- Historique bouée : champ attribution.
- En-têtes X-RateLimit-Reset et Retry-After (429), lisibles en CORS avec X-RateLimit-* et ETag.
- GET /api (description JSON) accessible sans clé ; spécification OpenAPI 3.1 ; documentation mise à jour (marées, prévisions, vent animé, webcams, licences).
- Nouvelles sources : bom (Australie), synop (Afrique, Asie, Pacifique, Amérique latine).
- METAR : champ ts = heure d’observation.
- Nouvelles sources : metnorway, aemet, meteogalicia, meteocat ; champ facultatif attribution sur les stations.
- Marées de ~2 000 ports dans le monde (?lat=&lon=, scope=world) avec coefficient calculé et champs coefficientSource / coefficientReason / coefficientNote.
- Sources windguru et gowind-native désactivées (flux amont supprimé le 23 juin 2026).
Prêt à construire ?
Clé gratuite pour les projets personnels, associatifs et les clubs.
Demander une clé API