Gares ferroviaires¶
L'API publie le référentiel des gares de voyageurs SNCF : 2782 gares, chacune avec son code UIC, sa position et son rattachement administratif. C'est la seule partie de l'API qui n'appartient à personne — pas de groupe, pas de clé, pas de droits.
Ce qui distingue cet endpoint¶
| Reste de l'API | Gares ferroviaires | |
|---|---|---|
| Périmètre | /groups/<group_id>/… |
aucun groupe |
| Authentification | clé d'API ou session requise | aucune |
| Origine de la donnée | le GTFS de votre réseau et les remontées terrain | le jeu de données ouvert SNCF gares-de-voyageurs |
| Change quand | en continu, pendant le service | quand la SNCF révise son jeu de données, et que le référentiel est rechargé à la main |
La conséquence à garder en tête : rien ici n'est temps réel, et rien ici n'est propre à votre réseau. C'est un index, fait pour être lu avant tout le reste — typiquement pour désigner par code UIC la gare à laquelle correspond un arrêt de votre réseau.
Les deux endpoints¶
| Endpoint | Rôle |
|---|---|
GET /api/v4/rail-stations |
Cherche dans le référentiel par nom ou par proximité |
GET /api/v4/rail-stations/<uic> |
Lit une gare à partir d'un de ses codes UIC |
Chercher par nom¶
q est cherché n'importe où dans le nom de la gare, sans tenir compte de la casse, des accents ni des séparateurs. chateauroux trouve Châteauroux, et saint germain trouve Saint-Germain-en-Laye Bel-Air – Fourqueux. Il n'y a rien à normaliser de votre côté.
import httpx
response = httpx.get(
"https://api.pysae.com/api/v4/rail-stations",
params={"q": "Châteauroux"},
)
response.raise_for_status()
for station in response.json()["items"]:
print(station["uic"], station["name"])
La réponse porte la page et son total, comme tout endpoint paginé de l'API :
{
"items": [
{
"uic": ["87597005"],
"name": "Châteauroux",
"short_label": "CTX",
"segments_drg": ["A"],
"lat": 46.809737,
"lon": 1.699536,
"insee_code": "36044",
"source_ref": "0054eed7-a134-4fca-b217-d65e4d2ea153"
}
],
"total": 1,
"page": 1,
"page_size": 50
}
Chercher par proximité¶
near=<latitude>,<longitude> ordonne les résultats par distance croissante et ajoute distance_meters à chacun. radius, en mètres, borne la recherche ; il vaut 10 km par défaut et est ignoré si near est absent.
GET /api/v4/rail-stations?near=48.880185,2.355151&radius=3000 renvoie les gares à moins de 3 km de Paris Gare du Nord, la plus proche d'abord.
Les deux filtres se combinent : q et near ensemble renvoient les gares dont le nom correspond, dans le rayon, ordonnées par distance.
Une gare, plusieurs codes UIC¶
uic est une liste, et non une valeur unique : c'est le point qui surprend à l'intégration. La SNCF attribue plusieurs codes à une même gare quand plusieurs réseaux la desservent : Paris Gare du Nord en porte trois, Avignon TGV deux. Les conséquences :
- N'importe lequel des codes d'une gare la résout.
GET /api/v4/rail-stations/87271007etGET /api/v4/rail-stations/87271031renvoient tous deux Paris Gare du Nord. - Un code appartient à une seule gare. Aucun code UIC n'est partagé, donc en résoudre un n'est jamais ambigu.
segments_drgest une liste pour la même raison. Le segment de fréquentation DRG (Ale plus fréquenté,Cle moins) est donné par code, donc une gare à plusieurs codes peut porter plusieurs segments.
Stocker un seul code de votre côté suffit à désigner une gare, à condition de lire uic comme une liste au moment de comparer.
Rattacher un arrêt de votre réseau à une gare¶
Le rattachement transforme l'index ci-dessus en donnée de service : il désigne, pour un arrêt de votre GTFS, la gare dont il affiche les départs, et il délimite les gares dont les données ferroviaires sont ingérées pour votre réseau. Contrairement au référentiel, cette partie est propre à chaque groupe et portée par la fonctionnalité payante rail_data : sans elle, les endpoints répondent 403 avec le code LOCKED_FEATURE.
GET /api/v4/groups/<group_id>/rail/station-links liste les rattachements du groupe. Chaque lien porte l'arrêt (stop_id, avec stop_name en libellé), la gare (uic) et un indicateur is_orphan : true quand l'arrêt n'existe pas — ou plus — dans le GTFS actuellement publié du groupe. Un lien orphelin n'est jamais rejeté ni supprimé d'office : vos arrêts sont réimportés à chaque GTFS, et le lien doit survivre à un réimport qui fait momentanément disparaître son arrêt. À vous d'afficher l'indicateur et de corriger ou retirer le lien.
Chaque lien porte aussi un ingestion_status, qui dit où en sont les données ferroviaires de la gare : ready quand ses départs sont interrogeables, pending pendant que la gare est en cours d'ingestion, not_found quand aucun train du feed national courant ne la dessert. Rattacher une gare encore absente du magasin ferroviaire répond immédiatement avec pending et prépare ses données en asynchrone — l'affaire de quelques minutes en général ; re-listez les liens jusqu'à ce qu'il passe ready, et affichez « préparation en cours » plutôt qu'un tableau des départs vide entre-temps. not_found n'est pas une erreur : le lien est conservé, et le rafraîchissement quotidien le réévalue à chaque nouveau feed SNCF.
Lire le tableau des départs d'une gare rattachée¶
C'est ce à quoi sert le rattachement : GET /api/v4/groups/<group_id>/rail/departures?stop_id=<stop_id> renvoie les trains au départ des gares rattachées à cet arrêt de votre réseau, horaires théoriques et temps réel confondus. Même fonctionnalité payante rail_data que les rattachements : sans elle, 403 LOCKED_FEATURE.
L'arrêt est désigné par son stop_id dans votre GTFS — pas par un code UIC. Un arrêt rattaché à plusieurs gares renvoie les départs de toutes, dans une seule liste.
La fenêtre¶
from et to sont des instants absolus, en ISO 8601 ou en epoch secondes, comme partout ailleurs dans l'API. Les deux bornes sont incluses.
| Ce que vous passez | Fenêtre appliquée |
|---|---|
| rien | maintenant → maintenant + 1 h |
from seul |
from → from + 1 h |
to seul |
to - 1 h → to |
| les deux | tel quel, 24 h au maximum |
Une fenêtre inversée ou plus large que 24 h est refusée avec un 400 INVALID_RAIL_DEPARTURES_WINDOW : au-delà, vous demandez un catalogue horaire, pas un tableau des départs.
La réponse¶
Une liste triée par scheduled_departure croissant — l'horaire théorique, celui sur lequel la fenêtre filtre, pour que l'ordre ne bouge pas quand les estimations évoluent.
| Champ | Rôle |
|---|---|
scheduled_departure |
L'horaire théorique. Toujours présent |
estimated_departure |
L'horaire estimé par le temps réel, null en son absence |
delay_seconds |
L'écart signé entre les deux, négatif pour un train en avance |
status |
scheduled, on_time, delayed, early, canceled, skipped, added |
destination |
Ce qu'il faut afficher : stop_headsign, sinon trip_headsign, sinon le nom du dernier arrêt du train |
route_type |
Le mode, route_type GTFS |
platform |
La voie, si la source la publie |
disruptions |
Les alertes temps réel qui couvrent ce train, sa ligne, la gare ou tout le réseau |
service_date |
Le jour de service (YYYYMMDD), qui n'est pas le jour calendaire pour un train partant après minuit |
Deux pièges à connaître :
status: scheduledsignifie « pas de temps réel », pas « à l'heure ». Quand aucune entité temps réel ne couvre le train, le tableau est servi sur ses seuls horaires théoriques :estimated_departure,delay_secondsrestentnulletdisruptionsest vide. L'absence de temps réel dégrade l'affichage, elle ne fait jamais échouer l'appel — et elle se fait train par train, pas tableau par tableau.- Aucun filtre par mode. Tous les modes desservant la gare sont renvoyés, autocars de substitution
Car TER(route_type3) compris : ils font partie du service que le voyageur doit voir. Filtrez côté client surroute_typesi vous ne voulez que les trains.
platform est optionnel de bout en bout : il vient du platform_code du GTFS de la source, que le feed national SNCF ne publie pas. Attendez-vous à null sur les données SNCF, et n'en faites pas une colonne obligatoire de votre affichage.
Un arrêt rattaché à aucune gare répond 200 avec une liste vide — c'est un état de configuration, pas une erreur. Idem pour une gare dont les données ne sont pas encore ingérées : lisez ingestion_status sur le rattachement pour distinguer « en préparation » de « aucun train ».
Bonnes pratiques¶
- Mettez en cache ce que vous lisez. Le référentiel est statique entre deux rechargements manuels ; le réinterroger à chaque action utilisateur n'apporte rien.
- Indexez sur le code UIC, pas sur le nom. Les noms sont retouchés par la SNCF ; les codes sont l'identifiant stable.
source_refpermet de retrouver l'enregistrement d'origine dans le jeu de données source, pour audit. - Un code inconnu répond 404, avec le code
RAIL_STATION_NOT_FOUND— à distinguer d'une recherche vide, qui est un 200 avectotal: 0. - Ne mettez pas le tableau des départs en cache comme le référentiel. Les flux temps réel ferroviaires se rafraîchissent toutes les deux minutes environ : interroger
departuresplus souvent que ça renvoie les mêmes estimations.