{"openapi":"3.1.0","info":{"title":"Ou s'entrainer ? — API des pistes d'athletisme francaises","version":"2026-08-23","summary":"Recherche dans les 7 134 installations d'athletisme recensees en France.","description":"Annuaire libre des installations d'athletisme francaises : revetement, developpement, couloirs, agres, conditions d'acces, coordonnees.\n\n**Deux regles de contrat a connaitre avant d'interpreter une reponse.**\n\n1. `acces_libre` vaut `true` ou `null`, jamais `false`. 5 549 des 7 134 installations n'ont pas d'information d'acces ; un blanc n'est pas un refus. C'est pourquoi `free_access=false` renvoie une 400.\n2. `agres_declares` vient de l'exploitant ; `agres_probables` est deduit d'une orthophoto par un contributeur. Les filtres de discipline portent sur le premier, sauf `certainty=probable|any`.\n\nLes donnees sont declaratives : ce qu'une commune ne declare pas n'y figure pas. Verifiez les conditions d'acces avant de vous deplacer.","license":{"name":"Licence Ouverte 2.0","url":"https://github.com/etalab/licence-ouverte/blob/master/LO.md"},"contact":{"url":"https://pistes-athle.com/"}},"servers":[{"url":"https://pistes-athle-api.athle.workers.dev","description":"Serveur de recherche : parametres de requete actifs."},{"url":"https://pistes-athle.com","description":"Miroir statique : facettes et index compact."}],"externalDocs":{"url":"https://pistes-athle.com/llms.txt","description":"Orientation generale du corpus (convention llms.txt)."},"paths":{"/api/tracks":{"get":{"operationId":"searchTracks","summary":"Rechercher des installations d'athletisme","description":"Tous les parametres se combinent en conjonction (ET).\n\n**Disponible uniquement sur le serveur de recherche** (voir `servers`). Sur le miroir statique GitHub Pages, la chaine de requete est ignoree par l'hebergeur : cette URL y renvoie le document de capacites `/api/tracks.json`, qui indique quoi appeler a la place.","parameters":[{"name":"city","in":"query","required":false,"description":"Commune, en clair ou en slug (`Nantes`, `nantes`). Associer `department` pour lever les homonymes.","schema":{"type":"string"},"example":"Nantes"},{"name":"department","in":"query","required":false,"description":"Code INSEE du departement (`44`, `2A`, `971`).","schema":{"type":"string"},"example":"44"},{"name":"lat","in":"query","required":false,"description":"Latitude WGS84 du point de recherche. Exige `lon`.","schema":{"type":"number"},"example":47.21},{"name":"lon","in":"query","required":false,"description":"Longitude WGS84 du point de recherche. Exige `lat`.","schema":{"type":"number"},"example":-1.55},{"name":"radius","in":"query","required":false,"description":"Rayon de recherche en km autour de (`lat`, `lon`). Defaut 10, maximum 100. Sans `lat`/`lon`, ignore.","schema":{"type":"integer"},"example":20},{"name":"track_length","in":"query","required":false,"description":"Developpement de l'anneau en metres : valeur exacte (`400`) ou intervalle (`300-400`). Alias : `length`. Ne porte que sur les 2 255 sites dont le ministere declare la longueur, jamais sur les estimations.","schema":{"type":"string"},"example":"400"},{"name":"lanes_min","in":"query","required":false,"description":"Nombre minimal de couloirs. Attention : `couloirs` n'est renseigne que sur 113 sites sur 7 134 ; ce filtre exclut de fait tous les autres.","schema":{"type":"integer"},"example":6},{"name":"surface","in":"query","required":false,"description":"Revetement : `synthetic`, `asphalt`, `cinder`, `sand`, `grass`, `natural`, `indoor`.","schema":{"type":"string"},"example":"synthetic"},{"name":"free_access","in":"query","required":false,"description":"`true` : les sites declares en acces libre. `unknown` : les 5 549 dont l'acces n'est pas renseigne. `false` est **refuse** (400) — un blanc n'est pas un non, et repondre par une liste serait inventer.","schema":{"type":"string"},"example":"true"},{"name":"has_reviews","in":"query","required":false,"description":"`true` : les installations qu'au moins un contributeur a decrites. `false` : celles que personne n'a encore vues — 7 128 sur 7 134. Contrairement a `free_access`, le `false` est ici legitime : l'absence d'avis est un fait de notre propre base, pas un silence du recensement.","schema":{"type":"boolean"}},{"name":"certainty","in":"query","required":false,"description":"`declared` (defaut) : les disciplines filtrent sur les agres declares. `probable` : sur les agres deduits d'une orthophoto. `any` : les deux.","schema":{"type":"string"}},{"name":"long_jump","in":"query","required":false,"description":"Presence d'un agres « longueur ».","schema":{"type":"boolean","enum":[true]}},{"name":"triple_jump","in":"query","required":false,"description":"Presence d'un agres « triple ».","schema":{"type":"boolean","enum":[true]}},{"name":"high_jump","in":"query","required":false,"description":"Presence d'un agres « hauteur ».","schema":{"type":"boolean","enum":[true]}},{"name":"pole_vault","in":"query","required":false,"description":"Presence d'un agres « perche ».","schema":{"type":"boolean","enum":[true]}},{"name":"shot_put","in":"query","required":false,"description":"Presence d'un agres « poids ».","schema":{"type":"boolean","enum":[true]}},{"name":"discus","in":"query","required":false,"description":"Presence d'un agres « disque ».","schema":{"type":"boolean","enum":[true]}},{"name":"hammer","in":"query","required":false,"description":"Presence d'un agres « marteau ».","schema":{"type":"boolean","enum":[true]}},{"name":"javelin","in":"query","required":false,"description":"Presence d'un agres « javelot ».","schema":{"type":"boolean","enum":[true]},"example":true},{"name":"steeplechase","in":"query","required":false,"description":"Presence d'un agres « steeple ».","schema":{"type":"boolean","enum":[true]}},{"name":"limit","in":"query","required":false,"description":"Nombre de resultats par page. Defaut 50, maximum 500.","schema":{"type":"integer"}},{"name":"page","in":"query","required":false,"description":"Page de resultats, a partir de 1.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Liste des installations correspondantes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Parametre invalide. `free_access=false` tombe toujours ici, par choix de contrat.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"parameter":{"type":"string"},"hint":{"type":"string"}}}}}}}}},"/api/tracks.json":{"get":{"operationId":"getCapabilities","summary":"Document de capacites : ce que cet hote sait faire","description":"Toujours disponible, y compris sur l'hebergement statique. Dit si la recherche par parametres est servie ici, et liste les points d'entree statiques a defaut.","responses":{"200":{"description":"Document de capacites.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/index.json":{"get":{"operationId":"getIndex","summary":"Index compact des 7 134 installations, en un fichier","description":"1,0 Mo contre 1,5 Mo pour `data/tracks.json` : uniquement les champs sur lesquels on filtre. Permet a un agent de faire lui-meme n'importe quelle conjonction, sans serveur de recherche. Les cles sont abregees ; `keymap` donne la correspondance.","responses":{"200":{"description":"Index complet.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tracks/{id}.json":{"get":{"operationId":"getTrack","summary":"Une installation par son identifiant national","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"example":"I505020004"}],"responses":{"200":{"description":"L'installation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Track"}}}},"404":{"description":"Identifiant inconnu."}}}},"/api/tracks/department/{code}.json":{"get":{"operationId":"listByDepartment","summary":"Installations d'un departement","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","enum":["00","1","10","11","12","13","14","15","16","17","18","19","2","21","22","23","24","25","26","27","28","29","2A","2B","3","30","31","32","33","34","35","36","37","38","39","4","40","41","42","43","44","45","46","47","48","49","5","50","51","52","53","54","55","56","57","58","59","6","60","61","62","63","64","65","66","67","68","69","7","70","71","72","73","74","75","76","77","78","79","8","80","81","82","83","84","85","86","87","88","89","9","90","91","92","93","94","95","971","972","973","974","975","976","977","978","986","987","988"]},"description":"Code INSEE","example":"44"}],"responses":{"200":{"description":"Installations d'un departement","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/tracks/city/{department}/{city}.json":{"get":{"operationId":"listByCity","summary":"Installations d'une commune","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[{"name":"department","in":"path","required":true,"schema":{"type":"string"}},{"name":"city","in":"path","required":true,"schema":{"type":"string"},"description":"Slug de la commune","example":"nantes"}],"responses":{"200":{"description":"Installations d'une commune","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/tracks/discipline/{discipline}.json":{"get":{"operationId":"listByDiscipline","summary":"Installations declarant une discipline","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[{"name":"discipline","in":"path","required":true,"schema":{"type":"string","enum":["discus","hammer","high_jump","javelin","long_jump","pole_vault","shot_put","steeplechase","triple_jump"]},"description":"Nom de parametre de la discipline","example":"javelin"}],"responses":{"200":{"description":"Installations declarant une discipline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/tracks/discipline/{discipline}/{department}.json":{"get":{"operationId":"listByDisciplineAndDepartment","summary":"Croisement discipline x departement","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[{"name":"discipline","in":"path","required":true,"schema":{"type":"string","enum":["discus","hammer","high_jump","javelin","long_jump","pole_vault","shot_put","steeplechase","triple_jump"]},"description":"Nom de parametre de la discipline","example":"pole_vault"},{"name":"department","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Croisement discipline x departement","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/tracks/length/{metres}.json":{"get":{"operationId":"listByLength","summary":"Installations d'un developpement donne","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[{"name":"metres","in":"path","required":true,"schema":{"type":"string","enum":["3","5","20","37","40","50","55","60","61","70","80","90","94","100","105","110","115","120","126","130","132","140","141","146","150","154","160","165","166","170","175","177","180","190","198","200","205","206","207","209","210","212","213","215","216","217","218","220","224","225","228","230","233","235","236","240","242","245","247","248","250","253","254","255","258","260","262","270","275","278","280","288","290","292","300","310","315","316","320","326","330","331","333","339","340","345","346","347","348","350","351","353","355","356","357","360","362","364","365","366","370","371","372","373","375","378","380","382","385","386","387","390","395","396","397","398","399","400","402","405","407","410","415","420","423","440","530","650","661","4000","4300"]},"description":"Developpement en metres","example":"400"}],"responses":{"200":{"description":"Installations d'un developpement donne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/tracks/surface/{surface}.json":{"get":{"operationId":"listBySurface","summary":"Installations d'un revetement","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[{"name":"surface","in":"path","required":true,"schema":{"type":"string","enum":["synthetic","asphalt","cinder","sand","grass","natural","indoor"]},"description":"Revetement","example":"synthetic"}],"responses":{"200":{"description":"Installations d'un revetement","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/tracks/lanes/{n}.json":{"get":{"operationId":"listByLanes","summary":"Installations d'au moins N couloirs","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[{"name":"n","in":"path","required":true,"schema":{"type":"string"},"description":"Nombre minimal de couloirs","example":"6"}],"responses":{"200":{"description":"Installations d'au moins N couloirs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/tracks/lanes/{n}/{department}.json":{"get":{"operationId":"listByLanesAndDepartment","summary":"Croisement couloirs x departement","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[{"name":"n","in":"path","required":true,"schema":{"type":"string"},"description":"Nombre minimal de couloirs","example":"6"},{"name":"department","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Croisement couloirs x departement","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/tracks/free-access.json":{"get":{"operationId":"listFreeAccess","summary":"Installations declarees en acces libre","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[],"responses":{"200":{"description":"Installations declarees en acces libre","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/tracks/reviewed.json":{"get":{"operationId":"listReviewed","summary":"Installations decrites par un contributeur","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[],"responses":{"200":{"description":"Installations decrites par un contributeur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}},"/api/geo/{lat}/{lon}.json":{"get":{"operationId":"listByCell","summary":"Cellule geographique de 0,1 degre","description":"Facette pre-calculee, servie par l'hebergement statique. N'existe que si elle contient au moins un resultat.","parameters":[{"name":"lat","in":"path","required":true,"schema":{"type":"string"},"description":"Latitude arrondie au pas de 0.1","example":"47.2"},{"name":"lon","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Cellule geographique de 0,1 degre","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"404":{"description":"Aucune installation pour cette facette."}}}}},"components":{"schemas":{"Track":{"type":"object","required":["id","nom","ville","latitude","longitude","url"],"properties":{"id":{"type":"string","description":"Identifiant national de l'installation.","example":"I505020004"},"nom":{"type":"string"},"ville":{"type":"string"},"departement":{"type":"string"},"code_postal":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"distance_km":{"type":["number","null"],"description":"Renseigne seulement si la requete portait `lat`/`lon`."},"piste":{"type":"boolean"},"longueur_piste_m":{"type":["integer","null"],"description":"Developpement declare par le ministere."},"longueur_probable_m":{"type":["integer","null"],"description":"Estimation deduite d'OpenStreetMap, jamais mesuree. A ne pas confondre avec `longueur_piste_m`."},"couloirs":{"type":["integer","null"]},"revetement":{"type":["string","null"],"enum":["synthetique","bitume","cendree","sable","gazon","naturel","interieur",null]},"acces_libre":{"type":["boolean","null"],"description":"`true` si declare en acces libre, `null` si le recensement ne dit rien. **Jamais `false`** : l'absence d'information n'est pas un refus."},"agres_declares":{"type":"array","items":{"type":"string","enum":["disque","hauteur","javelot","longueur","marteau","perche","poids","steeple","triple"]}},"agres_probables":{"type":"array","items":{"type":"string"},"description":"Deduits d'une orthophoto par un contributeur. `saut_indetermine` / `lancer_indetermine` signalent un agres dont la discipline est inconnue."},"nb_avis":{"type":"integer","description":"Nombre d'avis rediges par des contributeurs. Zero est un fait, pas un blanc : la base sait si quelqu'un a decrit ce site."},"note_moyenne":{"type":["number","null"],"description":"Moyenne des notes, si au moins un avis en porte une."},"url":{"type":"string","format":"uri","description":"Fiche HTML de l'installation, avec son JSON-LD."}}},"SearchResponse":{"type":"object","required":["query","count","total","source","license","results"],"properties":{"query":{"type":"object","description":"Les parametres compris, rejoues."},"count":{"type":"integer","description":"Resultats dans cette page."},"total":{"type":"integer","description":"Resultats pour la requete entiere."},"source":{"type":"string"},"license":{"type":"string","format":"uri"},"results":{"type":"array","items":{"$ref":"#/components/schemas/Track"}}}}}}}
