{
    "titre": "API turf.bzh v1",
    "version": "1.6.0",
    "genere_le": "2026-11-05",
    "base_url": "https://www.turf.bzh/api",
    "resume": "Acces programmatique aux donnees hippiques turf.bzh (programme, partants exacts, cotes PMU en direct, arrivees, indicateurs premium) et a ChatBZH. Reservee aux abonnes actifs titulaires de la Licence API (paiement unique). Une cle, deux usages : les endpoints DONNEES sont illimites (rate limit technique 60/min, 10 000/jour) ; POST /chat consomme les credits IA du compte. Aucune reponse ne garantit un gain : jeu responsable. Depuis le 03/08/2026 : une journee entiere de partants en un appel (/v1/journees/{date}/partants), des exports mensuels de la base entiere (/v1/exports), et un dictionnaire des champs avec leur taux de remplissage reel (/v1/schema). Depuis le 08/09/2026, chaque reponse dit ou en est votre quota : bloc meta.quota (limite_minute, restant_minute, limite_jour, restant_jour et les secondes avant chaque remise a zero) et en-tetes X-RateLimit-*.",
    "sections": [
        {
            "id": "a-lire-en-premier",
            "titre": "À lire en premier",
            "blocs": [
                {
                    "t": "p",
                    "v": "Ce document est généré automatiquement depuis le code de l'API : le contrat OpenAPI pour les adresses et leurs paramètres, le catalogue des colonnes pour les champs, et les taux de remplissage mesurés chaque nuit. Il ne peut donc pas décrire une version de l'API qui n'est pas celle en service."
                },
                {
                    "t": "liste",
                    "v": [
                        "Base des URL : https://www.turf.bzh/api",
                        "Toutes les dates s'écrivent AAAA-MM-JJ. Une date future est refusée en 422.",
                        "Toutes les réponses sont du JSON UTF-8, enveloppées dans data et meta.",
                        "Aucune réponse ne garantit un gain. Chaque taux publié porte son échantillon."
                    ]
                },
                {
                    "t": "note",
                    "v": "Pour un assistant : lisez la section des adresses pour savoir quoi appeler, puis le dictionnaire des champs pour savoir ce que vaut chaque colonne. La section des pièges évite les erreurs qui ne se voient pas."
                },
                {
                    "t": "p",
                    "v": "Acces programmatique aux donnees hippiques turf.bzh (programme, partants exacts, cotes PMU en direct, arrivees, indicateurs premium) et a ChatBZH. Reservee aux abonnes actifs titulaires de la Licence API (paiement unique). Une cle, deux usages : les endpoints DONNEES sont illimites (rate limit technique 60/min, 10 000/jour) ; POST /chat consomme les credits IA du compte. Aucune reponse ne garantit un gain : jeu responsable. Depuis le 03/08/2026 : une journee entiere de partants en un appel (/v1/journees/{date}/partants), des exports mensuels de la base entiere (/v1/exports), et un dictionnaire des champs avec leur taux de remplissage reel (/v1/schema). Depuis le 08/09/2026, chaque reponse dit ou en est votre quota : bloc meta.quota (limite_minute, restant_minute, limite_jour, restant_jour et les secondes avant chaque remise a zero) et en-tetes X-RateLimit-*."
                },
                {
                    "t": "p",
                    "v": "Version 1.1.0 (11/09/2026) : les endpoints qui servent des partants acceptent le parametre champs et rendent par defaut toutes les colonnes exploitables de la base. Seize indicateurs qui figuraient au catalogue de /v1/tops sans etre lisibles sur le partant le sont desormais, ELO_Proprio et ELO_Eleveur compris. Les colonnes ajoutees le sont a la fin, les positions d'un CSV existant ne bougent pas. Correction de documentation du meme jour : Taux_Victoire, Taux_Place et Taux_Incident sont des fractions entre 0 et 1, et non des pourcentages comme /v1/schema l'annoncait ; Taux_Place compte la victoire comme une place, alors que nombre_place ne compte que les places hors victoire."
                },
                {
                    "t": "p",
                    "v": "Version 1.2.0 (12/09/2026) : les non partants ne sont plus servis comme des partants. Un cheval declare forfait figure bien dans la base, avec Rank = NP, et les deux endpoints qui servent des partants ne le filtraient pas : 3 768 lignes et 2 741 courses sur les 8 530 mesurees du 1er janvier au 8 juin 2026, soit une course sur trois. Chaque partant porte desormais partant (booleen), statut_partant et, sur un forfait, source_statut. Chaque course porte nombre_partants_initial (le peloton engage, forfaits compris), nombre_partants_reel (ceux qui prennent le depart) et nombre_non_partants, avec leurs numeros. Ces deux nombres sont comptes ligne a ligne et non deduits de la colonne nombre_partants, qui reste servie sous le nom nombre_partants_declare : sur les courses avec forfait, elle vaut le peloton engage 85,6 % du temps et le peloton reel 10,0 % seulement, et l'ecart est signale quand il existe. Pour la journee en cours, /v1/courses/{date}/{rc} interroge le flux PMU en direct, seule source des forfaits de derniere minute ; la base, elle, ne porte que ceux declares tot. Le parametre non_partants (inclus, exclus, seuls) filtre la liste sans toucher aux comptes. Signale par un client le 11/09/2026."
                },
                {
                    "t": "p",
                    "v": "Version 1.3.0 (12/10/2026) : les Stats Premium des favoris, une ligne par course : /v1/journees/{date}/stats-premium pour une journee, /v1/stats-premium?du=&au= pour une periode de 31 jours au plus, /v1/courses/{date}/{rc}/stats-premium pour une course et la liste de ses courses de reference. Ce sont les chiffres de la colonne Stats Premium du programme du jour et de l'onglet Stats Premium de chaque page de course : reussite au gagnant et au place des 3 favoris, rapports moyens Simple gagnant et Simple place, nombre de courses de reference et de favoris observes, perimetre retenu. Demande d'un abonne le 12/10/2026. Depuis le 16/10/2026 (version 1.4.0) : six champs calcules sur chaque partant de /v1/courses/{date}/{rc} et /v1/journees/{date}/partants avec champs=tout (le defaut) : delta_poids (ecart de poids en kg depuis la derniere sortie), delta_valeur (ecart de valeur de handicap, meme discipline seulement), poids_prec, valeur_prec, date_prec et disc_prec. Galop seulement, null si inconnu, connus avant le depart. Aucun champ retire ni renomme ; champs=base et champs=indicateurs sont inchanges."
                },
                {
                    "t": "p",
                    "v": "Version 1.5.0 (02/11/2026) : /v1/journees/{date}/cotes (depuis le 01/11/2026) sert en un appel les cotes en direct de toutes les courses d'une journee, avec la cote du matin, la probabilite du marche, la Cote BZH et l'ecart entre les deux, en trois vues (partants, courses, value), et pour une journee passee depuis le 27/07/2026 la derniere cote relevee jusqu'a 2 minutes apres l'heure prevue du depart, avec l'arrivee. Depuis debut novembre 2026, /cotes, /cotes/historique et /v1/journees/{date}/cotes disent de quelle masse vient la cote (masse, masse_cote : point_de_vente, ou en_ligne quand la masse des points de vente ne publiait pas encore de cote exploitable), et les rapports d'une course du jour portent meta.complet_motif (statut_pmu ou delai). Aucun champ retire ni renomme."
                },
                {
                    "t": "p",
                    "v": "Version 1.6.0 (03/11/2026) : /v1/journees/{date}/d4 sert le statut D4 des chevaux de trot de la journee, comme la page Selection Trot D4 (statut de ferrure, courses sans D4, rang dans la serie, dernier et premier D4, risque de faute et taux de fautes attendu a la cote), du 01/02/2025 au lendemain. Avec champs=tout, chaque partant porte en plus Alloc_Precedente, Place_Precedente et Rapport_Alloc (la derniere course du cheval, connue avant le depart), en fin de liste des colonnes de la base. Aucun champ retire ni renomme ; champs=base et champs=indicateurs sont inchanges."
                }
            ]
        },
        {
            "id": "authentification",
            "titre": "Authentification",
            "blocs": [
                {
                    "t": "p",
                    "v": "Cle personnelle tbz_live_... a generer sur https://www.turf.bzh/api-cle.php"
                },
                {
                    "t": "code",
                    "v": "curl -H \"Authorization: Bearer tbz_live_VOTRE_CLE\" \\\n  \"https://www.turf.bzh/api/v1/statut\""
                },
                {
                    "t": "liste",
                    "v": [
                        "Bearer est la forme recommandée.",
                        "L'en-tête X-Api-Key est accepté.",
                        "Le paramètre ?api_key= est toléré : pratique pour un tableur ou un navigateur, mais il laisse la clé dans les journaux.",
                        "La clé est nominative et porte votre quota : ne la partagez pas."
                    ]
                }
            ]
        },
        {
            "id": "quotas",
            "titre": "Quotas",
            "blocs": [
                {
                    "t": "p",
                    "v": "Les adresses de données sont illimitées en volume ; seules deux limites techniques s'appliquent, à la minute et à la journée. POST /v1/chat, lui, consomme les crédits IA du compte."
                },
                {
                    "t": "p",
                    "v": "Chaque réponse 200 porte un bloc meta.quota et six en-têtes X-RateLimit-* : limite et restant sur la minute, limite et restant sur la journée, et le nombre de SECONDES avant chaque remise à zéro. C'est un délai d'attente, pas un horodatage. Les mêmes valeurs accompagnent un 429, où quota rejoint retry_after et scope dans error."
                },
                {
                    "t": "note",
                    "v": "Quand le compteur est indisponible, rien n'est émis plutôt qu'un chiffre faux : testez la présence du bloc, pas sa valeur."
                }
            ]
        },
        {
            "id": "erreurs",
            "titre": "Erreurs",
            "blocs": [
                {
                    "t": "p",
                    "v": "Toute erreur rend un objet error portant code, message, status et doc. Le message est en français et dit quoi faire, pas seulement ce qui ne va pas."
                },
                {
                    "t": "tableau",
                    "entetes": [
                        "Statut",
                        "code",
                        "Ce qui s'est passe",
                        "Quoi faire"
                    ],
                    "lignes": [
                        [
                            "401",
                            "unauthorized",
                            "clé absente, mal formée ou révoquée",
                            "vérifier l'en-tête Authorization"
                        ],
                        [
                            "403",
                            "forbidden",
                            "clé valide mais droit absent (Licence API, abonnement)",
                            "vérifier l'état du compte sur /v1/me"
                        ],
                        [
                            "404",
                            "not_found",
                            "la ressource n'existe pas à cette date",
                            "la réponse liste souvent ce qui existe ce jour-là"
                        ],
                        [
                            "422",
                            "invalid_params",
                            "un paramètre est invalide",
                            "le message nomme les valeurs acceptées"
                        ],
                        [
                            "429",
                            "rate_limited",
                            "limite à la minute ou à la journée atteinte",
                            "dormir retry_after secondes, puis réessayer"
                        ],
                        [
                            "503",
                            "upstream_unavailable",
                            "source indisponible (base, flux PMU)",
                            "réessayer plus tard ; la réponse ne sert jamais une donnée à moitié vraie"
                        ]
                    ]
                },
                {
                    "t": "note",
                    "v": "Un paramètre mal écrit n'est jamais ignoré en silence : il répond 422 en nommant les valeurs acceptées. Servir autre chose que ce qui est demandé sans le dire serait pire qu'une erreur."
                }
            ]
        },
        {
            "id": "adresses",
            "titre": "Les 41 adresses",
            "blocs": [
                {
                    "t": "p",
                    "v": "Chemins relatifs à la base des URL. Les paramètres marqués requis font partie du chemin ; les autres se passent en paramètres de requête."
                }
            ],
            "routes": [
                {
                    "methode": "GET",
                    "chemin": "/v1/schema",
                    "resume": "Dictionnaire des champs et taux de remplissage",
                    "description": "Pour chaque champ servi : le nom expose, le nom en base, le type, l'unite, une description, et le taux de remplissage reel mesure sur toute la table. Sur 80 colonnes, 38 sont renseignees a 100 % et 14 le sont a moins de 65 % : Rapport_SG a 8,5 %, Cote_BZH a 50,3 %. Cinq champs changent de nom entre la base et l'API : Course devient code_course, Numero devient num, Cheval devient name, Driver devient jockey_driver, Entraineur devient trainer. A lire avant de batir une hypothese.",
                    "groupe": "Compte",
                    "parametres": [
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur."
                        }
                    ]
                },
                {
                    "methode": "POST",
                    "chemin": "/v1/chat",
                    "resume": "Poser une question a ChatBZH (consomme les credits IA du compte)",
                    "description": "Reponse synchrone (30-180 s possibles). Refus 402 AVANT l'appel si solde insuffisant ou si l'estimation depasse max_credits. Forfaits automatiques : application de methode 60 cr, backtest 100 cr.",
                    "groupe": "Donnees",
                    "parametres": []
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/chevaux",
                    "resume": "Recherche d'un cheval par nom",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "recherche",
                            "ou": "query",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "limit",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 5,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/chevaux/{id}/historique",
                    "resume": "Dernieres courses d'un cheval (max 50 par appel)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "id",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "limit",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 10,
                            "description": ""
                        },
                        {
                            "nom": "discipline",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "debut",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Borne basse de la periode, au format YYYY-MM-DD. Ajoute le 03/08/2026 : rend exprimable « ce cheval sur l'hiver 2025 », qui imposait sinon de tout tirer et de filtrer chez soi."
                        },
                        {
                            "nom": "fin",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Borne haute de la periode, au format YYYY-MM-DD. Ajoute le 03/08/2026 : rend exprimable « ce cheval sur l'hiver 2025 », qui imposait sinon de tout tirer et de filtrer chez soi."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur : une ligne par course courue par le cheval."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/chevaux/{id}/lectures",
                    "resume": "Lectures expertes actives du jour pour un cheval",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "id",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "date",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/chevaux/{id}/renifleur",
                    "resume": "Toutes les notes du Renifleur sur un cheval",
                    "description": "L'historique des notes ecrites sur ce cheval, de la plus recente a la plus ancienne. nb_notes vaut 0 si le cheval n'a jamais ete repere sur la periode conservee, soit 400 jours. Contenu editorial exclusif turf.bzh, ce n'est PAS un signal de pari. Mesure sur 2 411 rentrees : les chevaux reperes terminent dans les trois premiers 35,9 % du temps contre 27,8 % pour l'ensemble des partants, mais a cote egale l'ecart n'est pas significatif et le retour est de 0,72 EUR pour 1 EUR joue. Chaque reponse porte un champ avertissement qui le rappelle.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "id",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "n_last",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 10,
                            "description": "Nombre de notes a retourner, 1 a 40. Defaut 10."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/chevaux/{id}/stats",
                    "resume": "Stats agregees d'un cheval",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "id",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "periode_jours",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{code_course}/rapports",
                    "resume": "Rapports definitifs d'une course, les deux masses PMU (collecte, et le jour meme en direct)",
                    "description": "Lit les rapports collectes chaque nuit (tout l'historique, meta.source = collecte) et, depuis le 11/10/2026, le flux du PMU en direct pour une course du jour ou de la veille avant 05:00, des la publication des rapports (meta.source = direct, avec meta.lu_le, meta.complet, meta.complet_motif, meta.masses et meta.statut_pmu : complet vaut true quand les deux masses sont lues et que le PMU a declare l'arrivee complete, complet_motif = statut_pmu, ou, a defaut de ce signal, quand les deux masses sont lues 90 minutes apres le depart, complet_motif = delai). Avant la publication : 404 not_found avec error.reason (pas_encore_courue, arrivee_pas_encore_definitive, rapports_pas_encore_publies, aucun_rapport_publie, course_annulee, course_inconnue), error.retry_after, error.disponible_vers et l'en-tete Retry-After ; 503 upstream_unavailable (reason pmu_indisponible) si le flux du PMU ne repond pas. Chaque ligne porte DEUX montants : rapport_pour_1_euro, ce que le PMU publie, et rapport_pour_la_mise_de_base, ce qu'un ticket encaisse reellement. La mise de base n'est pas la meme partout (1 EUR au simple gagnant en ligne, 2 EUR au point de vente, 3 EUR au Multi et au 2 sur 4) : servir un seul des deux obligerait chaque consommateur a refaire la multiplication.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "code_course",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "masse",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "en_ligne",
                                "point_de_vente"
                            ],
                            "defaut": null,
                            "description": "Masse PMU servie. Le flux nu rend le point de vente, ?specialisation=INTERNET la masse en ligne (types prefixes E_). Elles ne paient pas pareil : releve du 20/07/2026, couple place 15-7 a 17,80 EUR au point de vente contre 30,10 EUR en ligne. Sans ce parametre, les deux sont servies."
                        },
                        {
                            "nom": "pari",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre sur le type de pari, sans distinction de masse : TRIO retient aussi E_TRIO. Exemples : SIMPLE_GAGNANT, COUPLE_PLACE, DEUX_SUR_QUATRE, TRIO, TIERCE, QUARTE_PLUS, QUINTE_PLUS, MULTI, MINI_MULTI."
                        },
                        {
                            "nom": "payants",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "0",
                                "1"
                            ],
                            "defaut": null,
                            "description": "1 = ne garder que les rapports qui ont paye. Par defaut TOUT ce que le PMU a publie est servi, y compris les rapports a zero : ils prouvent que la formule etait proposee et que personne ne l'a trouvee, ce qui n'est pas une absence."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "csv"
                            ],
                            "defaut": null,
                            "description": "csv pour un tableau (UTF-8 BOM, separateur point-virgule)."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}",
                    "resume": "Fiche course + partants exacts (fonctionne sur tout l'historique)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur : une ligne par partant. Refuse en 422 sur une course ambigue (deux reunions au meme code) : precisez hippodrome, un tableau ne peut pas porter l'avertissement."
                        },
                        {
                            "nom": "hippodrome",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Dix courses de l'historique, reparties sur trois journees (2025-11-15, 2025-11-16, 2026-07-17), portent le meme code RxCy sous deux hippodromes, soit 0,036 % des codes. Sans ce parametre la reponse melange les deux pelotons et porte ambigu: true, avec le nom de l'hippodrome dont le peloton est complet."
                        },
                        {
                            "nom": "champs",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "base",
                                "indicateurs",
                                "tout"
                            ],
                            "defaut": "tout",
                            "description": "Jeu de colonnes rendu. base = les colonnes servies avant le 11/09/2026, meme ordre, pour un script deja ecrit. indicateurs = base plus l'identite proprietaire et eleveur et les seize indicateurs du catalogue /v1/tops qui manquaient sur le partant (ELO_Proprio, ELO_Eleveur, Sigma_Horse, IMDC, Synergie_JCh, Turf_Points, TPch_90, Moy_TPch_90, Rang_J, TPJ_90, Taux_Incident, nombre_victoire, nombre_place, Gains_Totaux, Gains_Course, distanceRecord_sec). tout = toute la base exploitable, et c'est le defaut. Les colonnes ajoutees le sont a la fin : les positions d'un CSV existant ne bougent pas. Le dictionnaire complet, avec le jeu de chaque champ et son taux de remplissage, est sur /v1/schema. Depuis le 03/11/2026, tout ajoute Alloc_Precedente, Place_Precedente et Rapport_Alloc (la derniere course du cheval, connue avant le depart) en fin de liste des colonnes de la base."
                        },
                        {
                            "nom": "non_partants",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "inclus",
                                "exclus",
                                "seuls"
                            ],
                            "defaut": "inclus",
                            "description": "Que faire des chevaux qui ne prennent pas le depart. inclus = tous les chevaux, chacun portant partant (booleen) et statut_partant (partant ou non_partant) ; c'est le defaut, pour qu'un script deja ecrit garde le meme nombre de lignes. exclus = seulement ceux qui partent. seuls = seulement les forfaits. Les comptes de la course (nombre_partants_initial, nombre_partants_reel, nombre_non_partants, numeros_non_partants) sont les memes quel que soit le mode : le filtre ne change que les lignes rendues."
                        },
                        {
                            "nom": "non_partants_direct",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": "1",
                            "description": "Interroger le flux PMU en direct pour connaitre les forfaits de derniere minute. ACTIF par defaut sur cet endpoint, et il ne coute qu'un seul appel sortant, mutualise par un cache de 45 secondes. Il ne se declenche que sur une course du jour non encore courue : sur une date passee la base porte le releve definitif. Mettre 0 pour une reponse sans aucun appel sortant, au prix des forfaits tardifs. Si le flux PMU ne repond pas, la reponse sort quand meme avec ce que la base connait, et non_partants_direct passe a false."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/analyse",
                    "resume": "Classement multi-features (rank_partants) + LigneBZH du jour",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/arrivee",
                    "resume": "Arrivee + rapports (quasi temps reel le jour J)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/cotes",
                    "resume": "Cotes PMU en direct, ecart depuis le matin et sur quelques minutes",
                    "description": "Pour chaque partant : cote (temps reel), cote_ref (cote de reference de la matinee), evolution_ouverture / evolution_ouverture_pct / sens_ouverture (ecart avec la cote du matin, le seul recul qui couvre la journee entiere), cote_5min_ago / evolution_5min (ecart avec une mesure plus ancienne) et comparaison_age_sec qui donne l'age REEL de cette mesure en secondes. Le champ se nomme cote_5min_ago pour raison de compatibilite, mais l'ecart peut porter sur plus de 5 minutes : lisez comparaison_age_sec avant d'annoncer une duree. Ces deux champs valent null tant qu'aucune mesure assez ancienne n'existe pour la course. tendance et tendance_pct viennent du PMU et mesurent l'ecart depuis son dernier rapport, dont la date n'est pas publiee : ne leur attribuez aucune duree. Depuis debut novembre 2026, masse (point_de_vente, ou en_ligne quand la masse des points de vente n'a rien rendu d'exploitable) est servi sur la reponse et repris sur chaque partant, donc en derniere colonne du CSV.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur : une ligne par partant, cote du moment comprise."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/cotes/historique",
                    "resume": "Serie complete des cotes de la course, du matin au depart",
                    "description": "La courbe, la ou /cotes ne donne que l'instantane et /cotes/mouvements une fenetre de deux heures. Chaque entree de mesures porte t (horodatage unix), heure (Europe/Paris), cotes (cote du moment par numero) et cotes_reference (cote de reference du matin). Un numero absent d'un releve n'avait pas de cote a cet instant : non-partant, ou marche pas encore ouvert (le PMU renvoie 0 dans ce cas, nous ne le publions pas comme une cote car il fausserait toute moyenne ; la cellule CSV est vide). Un releve ou aucun numero n'avait de cote n'apparait pas. Le flux PMU ne publie pas de serie : celle-ci est collectee par turf.bzh depuis le 27/07/2026, une course anterieure repond 404 et le passe n'est pas rattrapable. La cadence se resserre a l'approche du depart (releve sur les Quinte+ du 27/07 au 05/09/2026 : toutes les 30 a 35 min au-dela de 2 h, toutes les 15 min environ entre 2 h et 30 min, puis toutes les 5 a 10 min jusqu'au depart). Le dernier releve a ou avant T-30 tombe en pratique entre T-40 et T-45. En format=csv la sortie est en forme longue, une ligne par mesure et par partant, colonnes date;code_course;t;heure;num;cote;cote_ref;masse. Chaque mesure porte masse (point_de_vente ou en_ligne) depuis debut novembre 2026, null pour les releves anterieurs.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur, en forme longue : une ligne par releve et par partant."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/cotes/mouvements",
                    "resume": "Plus gros mouvements de cote sur une fenetre glissante",
                    "description": "Chaque ligne porte cote, cote_avant, delta, delta_pct et sens, plus cote_ouverture / delta_ouverture / delta_ouverture_pct pour le recul depuis le matin. La reponse contient fenetre_reelle_sec : la duree effectivement couverte, qui peut depasser le parametre fenetre si les mesures intermediaires manquent. Une cote qui baisse signale de l'argent qui rentre sur le cheval, ce n'est pas une prevision.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "fenetre",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 5,
                            "description": ""
                        },
                        {
                            "nom": "limit",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 5,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/dossier",
                    "resume": "Le dossier complet d'une course en un seul appel",
                    "description": "Tout ce que turf.bzh sait de la course {rc} du {date}, assemble cote serveur : la fiche et ses partants, les indicateurs calcules, le classement, LigneBZH, les ecarts, le carnet du Renifleur, EcurieBZH, les cotes PMU en direct et leurs mouvements pour une course du jour, les rapports definitifs pour une course passee, et l'historique recent de chaque partant. Remplace sept appels de course plus un appel par cheval : sur un peloton de quatorze, vingt et un appels deviennent un seul. Il compte pour UN appel de quota, comme n'importe quelle autre route. Aucune section n'est bloquante sauf la course elle-meme : une section indisponible revient en disponible=false avec sa raison, le reste est servi. Le champ meta.appels_economises dit combien d'appels cette reponse a remplaces.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "inclure",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Liste de sections separees par des virgules, parmi indicateurs, classement, ligne_bzh, ecarts, renifleur, ecuriebzh, cotes, mouvements, arrivee, rapports, historique. Omis, le dossier sert les sections qui ont un sens pour la date demandee (les cotes en direct pour aujourd'hui, les rapports definitifs pour une course passee). La valeur tout force les onze sections."
                        },
                        {
                            "nom": "historique",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 3,
                            "description": "Nombre de dernieres sorties rendues par partant, de 0 a 10 (defaut 3). C'est la partie qui coute une requete par cheval : 0 supprime la section et allege la reponse."
                        },
                        {
                            "nom": "hippodrome",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Dix courses de la base partagent leur code RxCy avec une autre reunion le meme jour. Ce parametre leve l'ambiguite, comme sur /v1/courses/{date}/{rc}."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "csv",
                                "xlsx"
                            ],
                            "defaut": null,
                            "description": "Omis, la reponse est le JSON complet. csv rend UNE ligne par partant, les champs de course repetes sur chaque ligne et les sections rabattues sur le cheval qu'elles decrivent (prefixe par le nom de la section) : la forme qu'un tableur sait filtrer. xlsx rend un classeur, un onglet par section plus un onglet Partants a plat et un onglet Course. Ce que ces deux formats ne peuvent pas porter (l'historique detaille de chaque cheval, les structures imbriquees) reste dans le JSON, qui fait foi."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/ecarts",
                    "resume": "Ecarts de victoires/places (par cheval et par numero)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/ecuriebzh",
                    "resume": "EcurieBZH : ecuries engagees dans une course qui sortent de l'ordinaire",
                    "description": "Les ecuries ayant au moins un cheval engage dans la course {rc} du {date} et qui sortent de leurs habitudes, avec le detail de leurs deplacements du jour. Lecture descriptive, jamais un pronostic (champ avertissement).",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/indicateurs",
                    "resume": "Features calculees par partant (ELO trends, forme, affinites, synergie, IMDC...)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "champs",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "base",
                                "indicateurs",
                                "tout"
                            ],
                            "defaut": "tout",
                            "description": "Jeu de colonnes rendu. base = les colonnes servies avant le 11/09/2026, meme ordre, pour un script deja ecrit. indicateurs = base plus l'identite proprietaire et eleveur et les seize indicateurs du catalogue /v1/tops qui manquaient sur le partant (ELO_Proprio, ELO_Eleveur, Sigma_Horse, IMDC, Synergie_JCh, Turf_Points, TPch_90, Moy_TPch_90, Rang_J, TPJ_90, Taux_Incident, nombre_victoire, nombre_place, Gains_Totaux, Gains_Course, distanceRecord_sec). tout = toute la base exploitable, et c'est le defaut. Les colonnes ajoutees le sont a la fin : les positions d'un CSV existant ne bougent pas. Le dictionnaire complet, avec le jeu de chaque champ et son taux de remplissage, est sur /v1/schema. Depuis le 03/11/2026, tout ajoute Alloc_Precedente, Place_Precedente et Rapport_Alloc (la derniere course du cheval, connue avant le depart) en fin de liste des colonnes de la base."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "csv"
                            ],
                            "defaut": null,
                            "description": "Sortie CSV (UTF-8 BOM, separateur ;) pour tableurs"
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/renifleur",
                    "resume": "Carnet de notes du Renifleur sur une course",
                    "description": "Deux blocs. carnet_de_course : le resume redige par Le Renifleur apres l'arrivee de cette course et le cheval retenu pour la prochaine fois, null si la course n'a pas encore ete debriefee. deja_reperes : les partants engages qui avaient ete reperes a leur derniere sortie, avec la note d'alors, sa date, l'hippodrome et le numero porte ce jour-la. Contenu editorial exclusif turf.bzh, ce n'est PAS un signal de pari. Mesure sur 2 411 rentrees : les chevaux reperes terminent dans les trois premiers 35,9 % du temps contre 27,8 % pour l'ensemble des partants, mais a cote egale l'ecart n'est pas significatif et le retour est de 0,72 EUR pour 1 EUR joue. Chaque reponse porte un champ avertissement qui le rappelle.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/courses/{date}/{rc}/stats-premium",
                    "resume": "Stats Premium des favoris d'une course et ses courses de reference",
                    "description": "Les chiffres de l'onglet Stats Premium de la page de la course (source = page_course), memes champs qu'une ligne de /v1/journees/{date}/stats-premium, plus courses_reference_liste : date, code_course, hippodrome, distance et lien de chaque course de reference. Le jour meme, ils sont identiques a ceux du programme ; sur une journee passee, ils peuvent en differer legerement si la base a recu entre-temps des arrivees anterieures a la course. En CSV (format=csv), le tableau rendu est celui des courses de reference. Ajoute le 12/10/2026.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "rc",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "csv"
                            ],
                            "defaut": null,
                            "description": "Sortie CSV (UTF-8 BOM, separateur ;) pour tableurs"
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/ecuriebzh",
                    "resume": "EcurieBZH : ecuries qui sortent de leurs habitudes (jour courant)",
                    "description": "Lecture DESCRIPTIVE du comportement des ecuries engagees au programme du jour, compare a leurs habitudes des dix-huit derniers mois : trajet inhabituel / plus loin que jamais, trois chevaux dans la meme course, premiere venue sur un hippodrome, monte confiee ou reprise, retour d'un cheval, premiere sortie chez un entraineur. Ce n'est PAS un pronostic : une ecurie qui se deplace loin, aligne plusieurs chevaux ou decouvre un hippodrome ne gagne pas plus souvent pour autant, le champ avertissement le rappelle. Reponse : ecuries[] (nom + deplacements {hippodrome, heure, faits}), chaque fait portant le libelle, la phrase redigee et les km. nb = nombre d'ecuries concernees, date = jour analyse. Donnee proprietaire turf.bzh, la meme qui alimente le pictogramme et l'onglet EcurieBZH du tableau des partants.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "ecurie",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Nom d'une ecurie / entraineur (ex: 'S. Roger') pour n'interroger que celle-ci. Vide = toutes les ecuries hors habitude de la journee."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/exports",
                    "resume": "Liste des exports mensuels",
                    "description": "La base entiere, en CSV compresse, un fichier par mois, avec taille, nombre de lignes et empreinte SHA-256. La reponse donne le nombre de fichiers et, pour chacun, sa taille, son nombre de lignes et sa derniere date. Le mois en cours porte partiel: true, il est incomplet et sa derniere journee n'a pas encore ses cotes de depart. A preferer a toute extraction massive.",
                    "groupe": "Donnees",
                    "parametres": []
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/exports/{fichier}",
                    "resume": "Telechargement d'un export mensuel",
                    "description": "Rend le fichier gzip. Le nom doit avoir la forme partants-AAAA-MM.csv.gz ; la liste est sur /v1/exports. Le telechargement passe par l'API et reste donc soumis a la cle.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "fichier",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Nom du fichier, tel que donne par /v1/exports."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/journees/{date}/cotes",
                    "resume": "Cotes en direct de toutes les courses d'une journee, en un seul appel",
                    "description": "Pilotage des cotes de la journee. Pour chaque partant : cote PMU du dernier releve (cote_heure, source_cote : direct = lue au PMU pendant l'appel, cache = lue au PMU dans la minute, releve = collecte turf.bzh), cote du matin et evolution, probabilite implicite du marche (marge du PMU retiree), Cote BZH et probabilite du modele ramenee aux seuls partants, ecart_value_pct = proba_bzh x cote - 1, note IA. Les releves anterieurs a 8 h 30 sont ignores. A chaque appel, jusqu'a direct courses dont le depart approche sont relues au PMU, les plus proches d'abord ; les autres portent le dernier releve de la collecte. Sur une journee passee (collecte depuis le 27/07/2026), la cote est la derniere relevee avant le depart, et rang_arrivee, cote_finale et rapport_sg permettent de mesurer un seuil. vue=courses rend une ligne par course (favori, choix du modele, plus forte baisse, nombre de chevaux retenus, meilleur ecart, gagnant). vue=value rend les partants qui passent les filtres ecart_min, cote_bzh_max, cote_min et cote_max. masse_cote (derniere colonne) dit de quelle masse vient la cote du moment : point_de_vente, ou en_ligne quand la masse des points de vente n'a rien rendu d'exploitable ; vide pour les releves anterieurs a debut novembre 2026. Un ecart est une piste de lecture, pas une garantie de gain.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Jour demande, au format YYYY-MM-DD : aujourd'hui ou une date passee."
                        },
                        {
                            "nom": "vue",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "partants (defaut, une ligne par partant), courses (une ligne par course) ou value (partants qui passent les filtres)."
                        },
                        {
                            "nom": "courses",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "toutes (defaut) ou a_venir (courses pas encore parties ; sur une journee passee, a_venir rend une liste vide)."
                        },
                        {
                            "nom": "direct",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Nombre maximal de courses relues au PMU pendant l'appel, de 0 a 10. Defaut 6."
                        },
                        {
                            "nom": "ecart_min",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "ecart_value_pct minimum, en pourcentage : proba_bzh x cote - 1, avec proba_bzh = 1 / Cote BZH ramenee aux partants qui en ont une. Defaut 20."
                        },
                        {
                            "nom": "cote_bzh_max",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Cote BZH maximale d'un cheval retenu, 0 = sans limite. Defaut 10."
                        },
                        {
                            "nom": "cote_min",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Cote du moment minimale, 0 = sans limite. Defaut 0."
                        },
                        {
                            "nom": "cote_max",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Cote du moment maximale, 0 = sans limite. Defaut 0."
                        },
                        {
                            "nom": "discipline",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre : plat, galop, trot, trot attele, trot monte, obstacle, haies, steeple, cross, ou le code d'une lettre (P, A, M, H, S, C)."
                        },
                        {
                            "nom": "hippodrome",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre partiel, insensible a la casse."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur ; memes colonnes d'une journee a l'autre."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/journees/{date}/d4",
                    "resume": "Statut D4 des chevaux de trot de la journee, une ligne par cheval concerne",
                    "description": "Pour chaque course de trot en France (attele et monte), les partants deferres des 4 pieds ou qui ne le sont plus, avec ce qu'affiche la page Selection Trot D4. Par cheval : statut (frais = 1re D4, enchaine = 2e ou 3e D4, habitue = 4e D4 de suite ou plus, plus_d4 = D4 a la course precedente mais pas aujourd'hui, inconnu = D4 aujourd'hui, ferrure precedente inconnue), courses_sans_d4_avant (1re D4 seulement), rang_serie_d4, dernier_d4_place et dernier_d4_date, premier_d4_connu (aucun D4 sur au moins 8 courses connues), risque_faute (eleve ou faible seulement si l'ecart avec l'attendu est significatif et d'au moins 10 %, habituel sinon), taux_faute_profil_pct et taux_faute_attendu_pct (taux de disqualifies du profil depuis fevrier 2025, et taux attendu pour le profil a cotes egales, constant pour le profil), nb_chevaux_profil, note_ia, cote, arrivee. Un statut de serie exige que la course precedente enregistree soit confirmee par la musique du jour ; sinon un cheval D4 sort en inconnu. Du 01/02/2025 au lendemain ; le jour meme et le lendemain, le programme du PMU est lu a l'appel comme sur la page (ferrure de derniere minute, non-partants, cote du moment, courses du lendemain : meta.source = base+flux ou flux) ; sans reponse du PMU, meta.source = base. Une liste vide avec meta.source vide veut dire que rien n'a pu etre calcule, pas qu'aucun cheval n'est D4. data est la liste des lignes. Les non-partants connus sont ecartes ; meta.compteurs donne le nombre de chevaux par statut, sans les partants non classes d'une course courue. Un statut de ferrure ne designe pas un gagnant : les premiers D4 connus commettent plus de fautes que leur cote ne l'annonce, sans gagner plus souvent qu'elle ne l'annonce.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Jour demande, au format YYYY-MM-DD : du 2025-02-01 au lendemain."
                        },
                        {
                            "nom": "statut",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Un ou plusieurs statuts separes par des virgules : frais, enchaine, habitue, plus_d4, inconnu. Sans ce parametre, tous les statuts."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur ; memes colonnes d'une journee a l'autre."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/journees/{date}/ecuriebzh",
                    "resume": "EcurieBZH pour une journee passee (archive datee)",
                    "description": "Le meme panorama que /v1/ecuriebzh, mais pour une journee passee archivee (fichier ecuries_<date>.json depose chaque matin). Utile pour juger sur pieces : ce jour-la, ces ecuries sortaient de leurs habitudes. 404 si aucune archive n'est disponible pour la date demandee.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "ecurie",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Nom d'une ecurie / entraineur pour n'interroger que celle-ci. Vide = toutes."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/journees/{date}/partants",
                    "resume": "Tous les partants d'une journee, en un seul appel",
                    "description": "Sert la journee entiere : tous les partants de toutes les courses, avec la cote de depart, les indicateurs et le rang d'arrivee. C'est l'endpoint des etudes sur plusieurs jours. Reconstituer la base course par course demande environ 28 000 appels, soit trois jours compte tenu du plafond de 10 000 appels quotidiens ; par journee, 548 appels et une dizaine de minutes. Les plages de dates sont refusees : bouclez sur les dates, ou prenez /v1/exports. La cote est vide pour la journee en cours, et pour la toute derniere journee de la base : elle arrive au rafraichissement du lendemain matin. /v1/statut donne la derniere date exploitable.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Jour demande, au format YYYY-MM-DD."
                        },
                        {
                            "nom": "discipline",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre : plat, trot attele, trot monte, obstacle, ou le code d'une lettre (P, A, M, H, S, C)."
                        },
                        {
                            "nom": "hippodrome",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre partiel, insensible a la casse."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur ; memes colonnes d'une journee a l'autre."
                        },
                        {
                            "nom": "champs",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "base",
                                "indicateurs",
                                "tout"
                            ],
                            "defaut": "tout",
                            "description": "Jeu de colonnes rendu. base = les colonnes servies avant le 11/09/2026, meme ordre, pour un script deja ecrit. indicateurs = base plus l'identite proprietaire et eleveur et les seize indicateurs du catalogue /v1/tops qui manquaient sur le partant (ELO_Proprio, ELO_Eleveur, Sigma_Horse, IMDC, Synergie_JCh, Turf_Points, TPch_90, Moy_TPch_90, Rang_J, TPJ_90, Taux_Incident, nombre_victoire, nombre_place, Gains_Totaux, Gains_Course, distanceRecord_sec). tout = toute la base exploitable, et c'est le defaut. Les colonnes ajoutees le sont a la fin : les positions d'un CSV existant ne bougent pas. Le dictionnaire complet, avec le jeu de chaque champ et son taux de remplissage, est sur /v1/schema. Depuis le 03/11/2026, tout ajoute Alloc_Precedente, Place_Precedente et Rapport_Alloc (la derniere course du cheval, connue avant le depart) en fin de liste des colonnes de la base."
                        },
                        {
                            "nom": "non_partants",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "inclus",
                                "exclus",
                                "seuls"
                            ],
                            "defaut": "inclus",
                            "description": "Que faire des chevaux qui ne prennent pas le depart. inclus = tous les chevaux, chacun portant partant (booleen) et statut_partant (partant ou non_partant) ; c'est le defaut, pour qu'un script deja ecrit garde le meme nombre de lignes. exclus = seulement ceux qui partent. seuls = seulement les forfaits. Les comptes de la course (nombre_partants_initial, nombre_partants_reel, nombre_non_partants, numeros_non_partants) sont les memes quel que soit le mode : le filtre ne change que les lignes rendues."
                        },
                        {
                            "nom": "non_partants_direct",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": "0",
                            "description": "Interroger le flux PMU en direct pour la journee EN COURS. Inactif par defaut : une journee compte jusqu'a une quarantaine de courses, soit autant d'appels sortants pour une seule requete. Sur une journee passee il n'apprend rien, la base porte alors le releve definitif, et le parametre est ignore. Mettre 1 pour l'activer : les courses non encore courues sont relevees en parallele, avec un cache de 45 secondes et un plafond de 25 appels par requete (au-dela, la note de reponse le dit). Pour une course precise, /v1/courses/{date}/{rc} le fait d'office et ne coute qu'un appel."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/journees/{date}/stats-premium",
                    "resume": "Stats Premium des favoris d'une journee, une ligne par course",
                    "description": "Les Stats Premium des favoris de toutes les courses d'une journee. Une ligne par course : date, code_course, hippodrome, pays, heure, prix, discipline, distance, partants (declares au programme), annulee, courses_reference (nombre de courses comparables retenues), favoris_observes, reussite_gagnant_pct et reussite_place_pct (part des courses de reference ou l'un des 3 favoris du PMU, non-partants exclus, a gagne ou a fini place), rapport_moyen_sg et rapport_moyen_sp (pour 1 EUR, sur les courses de reference), niveau (1 a 4, l'echelle de comparaison retenue : 1 = meme hippodrome, meme distance, meme categorie ; 4 = toutes reunions, distance proche), perimetre (en clair), source et lien. Sans course de reference, les chiffres sont vides, comme sur la page. source = programme : les chiffres de la colonne Stats Premium du programme du jour, figes le matin, ceux de son export Excel ; source = calcul : le meme moteur avec les memes criteres, quand le programme de cette journee n'a pas ete fige. Pas de triche avec le futur : pour une course du jour D, seules des courses anterieures a D servent de reference. Journee servie : toute date passee, le jour meme et le lendemain (programme publie la veille). Une journee sans course rend une liste vide, avec meta.journee_sans_course = true. 503 avec error.reason = programme_indisponible ou base_indisponible si le PMU ou la base ne repondent pas. Ajoute le 12/10/2026.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Jour demande, au format YYYY-MM-DD."
                        },
                        {
                            "nom": "hippodrome",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre partiel, insensible a la casse."
                        },
                        {
                            "nom": "discipline",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre : plat, trot attele, trot monte, obstacle, haies, steeple, cross, ou le code d'une lettre (P, A, M, H, S, C)."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "csv"
                            ],
                            "defaut": null,
                            "description": "Sortie CSV (UTF-8 BOM, separateur ;) pour tableurs"
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/me",
                    "resume": "Etat du compte (licence, abonnement, cle, credits IA, usage API)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": []
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/methodes",
                    "resume": "Liste des methodes BZH du compte (appliquer/backtester : via POST /v1/chat, forfaits 60/100 cr)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": []
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/performances",
                    "resume": "Taux de couverture mesure de nos selections, et palmares",
                    "description": "Le taux de couverture est la part des courses ou la combinaison gagnante d'un pari etait entierement contenue dans nos N premiers chevaux. Il est mesure sur TOUTES les courses de la periode ou le PMU a publie cette formule, jamais sur une selection des meilleures. Chaque ligne porte le nombre de combinaisons a jouer (tickets) et leur cout (engage_eur) : un taux sans son prix ne veut rien dire. Ce n'est ni un rendement ni une promesse ; le meta porte l'avertissement, qui n'est pas decoratif. Meme source que la page /meilleures-performances.php.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "fenetre",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "7j",
                                "14j",
                                "30j",
                                "90j",
                                "annee"
                            ],
                            "defaut": "30j",
                            "description": ""
                        },
                        {
                            "nom": "famille",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre : SIMPLE_GAGNANT, COUPLE_GAGNANT, COUPLE_PLACE, DEUX_SUR_QUATRE, TRIO, TIERCE, QUARTE_PLUS, QUINTE_PLUS, MULTI, MINI_MULTI."
                        },
                        {
                            "nom": "palmares",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "0",
                                "1"
                            ],
                            "defaut": null,
                            "description": "1 pour joindre les plus gros rapports couverts. Absent par defaut : la mesure pese moins que la vitrine."
                        },
                        {
                            "nom": "n",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 10,
                            "description": "Lignes de palmares, 1 a 100."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "csv"
                            ],
                            "defaut": null,
                            "description": "csv pour un tableau (UTF-8 BOM, separateur point-virgule)."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/personnes",
                    "resume": "Recherche jockey/driver/entraineur/proprietaire/eleveur (semantique + fallback)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "recherche",
                            "ou": "query",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "type",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "jockey",
                                "driver",
                                "entraineur",
                                "proprietaire",
                                "eleveur"
                            ],
                            "defaut": "jockey",
                            "description": ""
                        },
                        {
                            "nom": "limit",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 5,
                            "description": ""
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/personnes/{type}/{id}/stats",
                    "resume": "Stats d'un jockey, entraineur, proprietaire ou eleveur (periode, discipline ; hippodrome pour les jockeys)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "type",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [
                                "jockey",
                                "driver",
                                "entraineur",
                                "proprietaire",
                                "eleveur"
                            ],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "id",
                            "ou": "path",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "periode_jours",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 90,
                            "description": ""
                        },
                        {
                            "nom": "discipline",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "hippodrome",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "debut",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Borne basse de la periode, au format YYYY-MM-DD. Ajoute le 03/08/2026. Des qu'une de ces deux bornes est fournie, periode_jours cesse de s'appliquer et le champ period_days de la reponse porte la duree reellement couverte."
                        },
                        {
                            "nom": "fin",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Borne haute de la periode, au format YYYY-MM-DD. Ajoute le 03/08/2026. Des qu'une de ces deux bornes est fournie, periode_jours cesse de s'appliquer et le champ period_days de la reponse porte la duree reellement couverte."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/programme",
                    "resume": "Programme du jour (reunions, courses, heures, Quinte+)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "filter",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "all",
                                "upcoming",
                                "completed"
                            ],
                            "defaut": "all",
                            "description": ""
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur : une ligne par course du programme."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/quinte",
                    "resume": "La course du Quinte+ du jour (source officielle turf.bzh)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": []
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/rapports",
                    "resume": "Rapports definitifs collectes d'une journee entiere",
                    "description": "Meme source et memes champs que la route par course, sur toute une journee : environ 340 rapports sur 40 courses. Le meta porte nb_courses, paris_presents et les bornes de la collecte. Ne sert que les journees archivees : la journee en cours, et la veille avant 05:00, renvoient 404 avec error.reason = journee_pas_encore_archivee et l'heure de l'archivage (Retry-After) ; demandez alors les courses une par une.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Defaut : aujourd'hui. Une date future renvoie 422."
                        },
                        {
                            "nom": "code_course",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "masse",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "en_ligne",
                                "point_de_vente"
                            ],
                            "defaut": null,
                            "description": "Masse PMU servie. Le flux nu rend le point de vente, ?specialisation=INTERNET la masse en ligne (types prefixes E_). Elles ne paient pas pareil : releve du 20/07/2026, couple place 15-7 a 17,80 EUR au point de vente contre 30,10 EUR en ligne. Sans ce parametre, les deux sont servies."
                        },
                        {
                            "nom": "pari",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre sur le type de pari, sans distinction de masse : TRIO retient aussi E_TRIO. Exemples : SIMPLE_GAGNANT, COUPLE_PLACE, DEUX_SUR_QUATRE, TRIO, TIERCE, QUARTE_PLUS, QUINTE_PLUS, MULTI, MINI_MULTI."
                        },
                        {
                            "nom": "payants",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "0",
                                "1"
                            ],
                            "defaut": null,
                            "description": "1 = ne garder que les rapports qui ont paye. Par defaut TOUT ce que le PMU a publie est servi, y compris les rapports a zero : ils prouvent que la formule etait proposee et que personne ne l'a trouvee, ce qui n'est pas une absence."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "csv"
                            ],
                            "defaut": null,
                            "description": "csv pour un tableau (UTF-8 BOM, separateur point-virgule)."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/resultats",
                    "resume": "Arrivees et rapports des courses terminees d'une journee (aujourd'hui ou une date passee)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "date",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Journee servie. Defaut : aujourd'hui. Toute date passee presente en base est acceptee ; une date future renvoie 422."
                        },
                        {
                            "nom": "code_course",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "hippodrome",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre sur le nom de l'hippodrome, recherche partielle et insensible a la casse (ex: enghien). 40 caracteres maximum."
                        },
                        {
                            "nom": "arrivee",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "complete",
                                "top5"
                            ],
                            "defaut": "complete",
                            "description": "complete (defaut) = ordre d'arrivee entier ; top5 = les cinq premiers seulement"
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/stats-premium",
                    "resume": "Stats Premium des favoris sur une periode de 31 jours au plus",
                    "description": "Les memes lignes que /v1/journees/{date}/stats-premium, sur toutes les journees de du a au (bornes comprises, 31 jours au plus). Une periode n'est jamais servie incomplete : si des journees jamais affichees au programme restent a calculer (environ 20 secondes de calcul par appel), la reponse est 503, error.code = calcul_en_cours, avec journees_pretes, journees_a_completer et Retry-After ; relancez la meme adresse, les journees calculees sont gardees. Si le programme du PMU d'une journee est indisponible : 503, error.reason = programme_indisponible, avec journees_sans_programme. Si la base des courses ne repond pas (mise a jour en cours) : 503, error.reason = base_indisponible. Une journee ou le PMU ne publie aucune course est servie vide et listee dans meta.journees_sans_course. Ajoute le 12/10/2026.",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "du",
                            "ou": "query",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Premier jour, YYYY-MM-DD."
                        },
                        {
                            "nom": "au",
                            "ou": "query",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Dernier jour, YYYY-MM-DD, au plus 30 jours apres du et au plus tard le lendemain."
                        },
                        {
                            "nom": "hippodrome",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre partiel, insensible a la casse."
                        },
                        {
                            "nom": "discipline",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Filtre : plat, trot attele, trot monte, obstacle, haies, steeple, cross, ou le code d'une lettre (P, A, M, H, S, C)."
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [
                                "csv"
                            ],
                            "defaut": null,
                            "description": "Sortie CSV (UTF-8 BOM, separateur ;) pour tableurs"
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/statut",
                    "resume": "Fraicheur de la base (healthcheck) : fresh / stale / empty",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": []
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/tops",
                    "resume": "Top N du jour par indicateur (34 indicateurs du catalogue)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "indicateur",
                            "ou": "query",
                            "requis": true,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "n",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 10,
                            "description": ""
                        },
                        {
                            "nom": "date",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "discipline",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur : une ligne par cheval du classement."
                        }
                    ]
                },
                {
                    "methode": "GET",
                    "chemin": "/v1/value-bets",
                    "resume": "Value bets du jour (composite Cote_BZH_fiable)",
                    "description": "",
                    "groupe": "Donnees",
                    "parametres": [
                        {
                            "nom": "n",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": 10,
                            "description": ""
                        },
                        {
                            "nom": "date",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": ""
                        },
                        {
                            "nom": "format",
                            "ou": "query",
                            "requis": false,
                            "valeurs": [],
                            "defaut": null,
                            "description": "Mettre csv pour une sortie tableur : une ligne par candidat."
                        }
                    ]
                }
            ]
        },
        {
            "id": "non-partants",
            "titre": "Qui prend le départ",
            "blocs": [
                {
                    "t": "p",
                    "v": "Point à lire avant tout calcul sur un peloton. Un cheval déclaré forfait n'est pas absent de la base : il y figure comme les autres, avec Rank = NP. Jusqu'au 12/09/2026, les deux adresses qui servent des partants ne le distinguaient pas. Portée mesurée sur les 8 530 courses courues du 1er janvier au 8 juin 2026 : 3 768 lignes portent ce code, sur 2 741 courses, soit 32,1 % de la période."
                },
                {
                    "t": "tableau",
                    "entetes": [
                        "Champ",
                        "Sur",
                        "Ce que c'est"
                    ],
                    "lignes": [
                        [
                            "partant",
                            "chaque partant",
                            "booléen. false : ce cheval ne prend pas le départ. En CSV, 1 ou 0."
                        ],
                        [
                            "statut_partant",
                            "chaque partant",
                            "partant ou non_partant."
                        ],
                        [
                            "source_statut",
                            "un forfait",
                            "base ou pmu_direct, d'où vient l'information."
                        ],
                        [
                            "nombre_partants_initial",
                            "la course",
                            "le peloton engagé, forfaits compris."
                        ],
                        [
                            "nombre_partants_reel",
                            "la course",
                            "ceux qui prennent le départ. initial = réel + non partants, sans exception."
                        ],
                        [
                            "nombre_non_partants",
                            "la course",
                            "les forfaits connus à l'instant de l'appel."
                        ],
                        [
                            "numeros_non_partants",
                            "la course",
                            "leurs numéros, triés."
                        ],
                        [
                            "nombre_partants_declare",
                            "la course",
                            "le chiffre annoncé par la source, tel quel."
                        ]
                    ]
                },
                {
                    "t": "p",
                    "v": "N'UTILISEZ PAS nombre_partants pour compter les chevaux au départ. Sur les 2 741 courses à forfait de la période mesurée, cette colonne vaut le peloton engagé 85,6 % du temps et le peloton réel 10,0 % seulement. Les deux nombres servis sont comptés ligne à ligne et non déduits d'elle ; le chiffre annoncé est servi à côté sous nombre_partants_declare, et note_partants_declare signale l'écart quand il existe, soit 398 courses sur 8 530 (4,7 %)."
                },
                {
                    "t": "p",
                    "v": "Les autres codes de Rank ne désignent pas des forfaits. D disqualifié, A arrêté, T tombé, R et N s'appliquent à des chevaux qui ont pris le départ. NP est le seul code de forfait. Les effectifs de chaque code figurent dans la description du champ Rank, au dictionnaire."
                },
                {
                    "t": "p",
                    "v": "Le jour J, la base ne suffit pas. Le code NP arrive tôt pour les forfaits déclarés à l'avance, et seulement avec l'ingestion de l'arrivée pour les autres, donc après la course. Relevé du 08/06/2026 : 4 forfaits posés sur 678 lignes encore sans résultat, pour une journée qui en comptera entre 26 et 52. /v1/courses/{date}/{rc} interroge donc le flux PMU en direct PAR DÉFAUT sur une course du jour non encore courue : c'est la seule source d'un forfait de dernière minute. Sur /v1/journees/{date}/partants c'est en option, non_partants_direct=1, parce qu'une journée compte jusqu'à une quarantaine de courses."
                },
                {
                    "t": "code",
                    "v": "# le peloton réel d'une course du jour\nGET /v1/courses/{date}/{rc}?non_partants=exclus\n\n# les seuls forfaits, pour un rapprochement\nGET /v1/courses/{date}/{rc}?non_partants=seuls\n\n# la journée entière, avec le relevé PMU en direct\nGET /v1/journees/{date}/partants?non_partants_direct=1"
                },
                {
                    "t": "note",
                    "v": "Le filtre non_partants ne change que la liste rendue : les cinq nombres de course et les numéros des forfaits sont identiques dans les trois modes. Si le flux PMU ne répond pas, la réponse sort quand même avec le relevé de la base et non_partants_direct passe à false."
                }
            ]
        },
        {
            "id": "champs",
            "titre": "Le dictionnaire des champs",
            "blocs": [
                {
                    "t": "p",
                    "v": "Le catalogue des colonnes servies sur un partant, tel qu'il vit dans le code. Le paramètre champs choisit le jeu : base rend les 45 colonnes servies avant le 11/09/2026 dans le même ordre, indicateurs y ajoute l'identité propriétaire et éleveur et les 16 indicateurs du catalogue /v1/tops, tout rend l'ensemble et c'est le défaut. Les colonnes ajoutées le sont à la fin : les positions d'un CSV existant ne bougent pas."
                },
                {
                    "t": "p",
                    "v": "La portée dit si la valeur est propre au cheval ou commune à toute la course. Sur /v1/courses/{date}/{rc}, les valeurs de portée course sont hissées dans l'en-tête de la réponse au lieu d'être répétées sur chaque ligne."
                },
                {
                    "t": "note",
                    "v": "Les taux de remplissage portent sur la table entière et sont recalculés chaque nuit ; dernière mesure le 2026-11-05T05:55:38+01:00. Un taux bas n'est pas une anomalie : il dit que la source ne publie cette information que dans certains cas. Vérifiez-le avant de bâtir une hypothèse sur un champ."
                }
            ],
            "champs": [
                {
                    "champ": "date",
                    "colonne": "date",
                    "jeu": "base",
                    "portee": "course",
                    "type": "date",
                    "unite": "YYYY-MM-DD",
                    "description": "Jour de la course."
                },
                {
                    "champ": "code_course",
                    "colonne": "Course",
                    "jeu": "base",
                    "portee": "course",
                    "type": "texte",
                    "unite": "RxCy",
                    "description": "Code reunion et course, par exemple R1C3. Attention : dix courses de l'historique, reparties sur trois journees (2025-11-15, 2025-11-16, 2026-07-17), portent le meme code sous deux hippodromes differents, soit 0,036 % des codes. Sur celles-la, la reponse porte ambigu: true et un des deux pelotons est incomplet en base. Utilisez le parametre hippodrome pour les separer."
                },
                {
                    "champ": "hippodrome",
                    "colonne": "hippodrome",
                    "jeu": "base",
                    "portee": "course",
                    "type": "texte",
                    "unite": null,
                    "description": "Nom de l'hippodrome."
                },
                {
                    "champ": "num",
                    "colonne": "Numero",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Numero du partant, celui qu'on coche sur un ticket."
                },
                {
                    "champ": "idcheval",
                    "colonne": "idcheval",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Identifiant stable du cheval. A preferer au nom : deux chevaux peuvent porter le meme nom."
                },
                {
                    "champ": "name",
                    "colonne": "Cheval",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Nom du cheval."
                },
                {
                    "champ": "Sexe",
                    "colonne": "Sexe",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": "H/F/M",
                    "description": "Sexe du cheval."
                },
                {
                    "champ": "age",
                    "colonne": "age",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "annees",
                    "description": "Age du cheval le jour de la course."
                },
                {
                    "champ": "jockey_driver",
                    "colonne": "Driver",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Jockey au plat et a l'obstacle, driver au trot."
                },
                {
                    "champ": "trainer",
                    "colonne": "Entraineur",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Entraineur."
                },
                {
                    "champ": "idjockey",
                    "colonne": "idjockey",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Identifiant stable du jockey ou driver."
                },
                {
                    "champ": "identraineur",
                    "colonne": "identraineur",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Identifiant stable de l'entraineur."
                },
                {
                    "champ": "Cote",
                    "colonne": "Cote",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "pour 1 euro",
                    "description": "LA COTE DE DEPART, pas celle du matin. Verification sur la base : la somme des inverses des cotes d'une course a une mediane de 1,189, soit un prelevement de 18,9 %, ce qui est la signature d'un pool ferme au depart ; et sur 27 198 gagnants ayant aussi un rapport, l'ecart median entre les deux est nul. Vide pour la journee en cours (valeur non rafraichie) et pour la toute derniere journee de la base (la cote de depart arrive au rafraichissement du lendemain)."
                },
                {
                    "champ": "Cote_BZH",
                    "colonne": "Cote_BZH",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "pour 1 euro",
                    "description": "Cote estimee par turf.bzh a partir des chances du cheval. Ce n'est pas une cote de marche."
                },
                {
                    "champ": "Note_IA",
                    "colonne": "Note_IA",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Note de synthese, forme courte."
                },
                {
                    "champ": "Note_IA_Decimale",
                    "colonne": "Note_IA_Decimale",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "sur 20",
                    "description": "Note de synthese sur vingt."
                },
                {
                    "champ": "ELO_Cheval",
                    "colonne": "ELO_Cheval",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Classement ELO du cheval."
                },
                {
                    "champ": "ELO_Jockey",
                    "colonne": "ELO_Jockey",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Classement ELO du jockey ou driver."
                },
                {
                    "champ": "ELO_Entraineur",
                    "colonne": "ELO_Entraineur",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Classement ELO de l'entraineur."
                },
                {
                    "champ": "IA_Gagnant",
                    "colonne": "IA_Gagnant",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "probabilite",
                    "description": "Chance estimee de gagner. C'est le bouton IA GAGNANT du tableau des partants."
                },
                {
                    "champ": "IA_Couple",
                    "colonne": "IA_Couple",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "probabilite",
                    "description": "Chance estimee de figurer dans les deux premiers. C'est le bouton IA COUPLE du tableau des partants. Servie par l'API depuis le 09/09/2026."
                },
                {
                    "champ": "IA_Trio",
                    "colonne": "IA_Trio",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "probabilite",
                    "description": "Chance estimee de figurer dans les trois premiers. C'est le bouton IA TRIO du tableau des partants. Servie par l'API depuis le 09/09/2026."
                },
                {
                    "champ": "IA_Multi",
                    "colonne": "IA_Multi",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "probabilite",
                    "description": "Chance estimee de figurer dans les quatre premiers. C'est le bouton IA MULTI du tableau des partants. Servie par l'API depuis le 09/09/2026."
                },
                {
                    "champ": "IA_Quinte",
                    "colonne": "IA_Quinte",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "probabilite",
                    "description": "Chance estimee de figurer dans les cinq premiers. C'est le bouton IA QUINTE du tableau des partants."
                },
                {
                    "champ": "ferrure",
                    "colonne": "ferrure",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Ferrure annoncee (D4 deferre des quatre, DA deferre anterieurs, DP deferre posterieurs...)."
                },
                {
                    "champ": "Musique",
                    "colonne": "Musique",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Musique du cheval, ses dernieres performances."
                },
                {
                    "champ": "Rank",
                    "colonne": "Rank",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Rang d'arrivee. Valeurs numeriques 1, 2, 3... pour les chevaux classes. Codes non numeriques REELLEMENT presents en base, avec leurs effectifs mesures au 03/08/2026 : D 31 174, NP 12 405, A 3 209, T 1 474, R 35, N 2. Vide sur 3 144 lignes, quand la source ne publie pas la place (gros pelotons etrangers, ou course pas encore depouillee). Le sens exact de D et de R n'est pas tranche dans nos sources : ne les interpretez pas, traitez-les comme non classe. NP est le seul code qui signale un cheval qui N'A PAS pris le depart : D, A, T, R et N designent des chevaux qui sont partis. Depuis le 12/09/2026 vous n'avez plus a le deduire, le champ partant le dit, et sur une course du jour il tient compte des forfaits de derniere minute releves en direct sur le flux PMU, que la base ne connait pas encore."
                },
                {
                    "champ": "supplemente",
                    "colonne": "supplemente",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Cheval engage en supplement."
                },
                {
                    "champ": "ExFav",
                    "colonne": "ExFav",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Etait favori lors d'une sortie precedente."
                },
                {
                    "champ": "Poids",
                    "colonne": "Poids",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "kg",
                    "description": "Poids porte. Sans objet au trot attele."
                },
                {
                    "champ": "Valeur",
                    "colonne": "Valeur",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": null,
                    "description": "Valeur handicap officielle."
                },
                {
                    "champ": "Place_Corde",
                    "colonne": "Place_Corde",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Place a la corde. Sans objet dans les disciplines sans corde."
                },
                {
                    "champ": "avis_entraineur",
                    "colonne": "avis_entraineur",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Avis publie par l'entraineur, quand il y en a un."
                },
                {
                    "champ": "Taux_Victoire",
                    "colonne": "Taux_Victoire",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "fraction de 0 a 1",
                    "description": "Taux de victoire du cheval. CE N'EST PAS UN POURCENTAGE : c'est une fraction entre 0 et 1, et 0,21 se lit 21 %. Le champ etait documente en pourcentage jusqu'au 11/09/2026, a tort. Formule verifiee sur la base entiere ce jour-la : nombre_victoire divise par Courses_courues, exacte sur 266 483 lignes sur 266 483. Les deux termes sortent avec le jeu tout : un taux sans son effectif ne se lit pas."
                },
                {
                    "champ": "Taux_Place",
                    "colonne": "Taux_Place",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "fraction de 0 a 1",
                    "description": "Taux de place du cheval, LA VICTOIRE COMPRISE, comme le turfiste l'entend. Fraction entre 0 et 1, pas un pourcentage. Formule verifiee sur la base entiere le 11/09/2026 : nombre_victoire plus nombre_place, divise par Courses_courues, exacte sur 265 589 lignes sur 266 483, soit 99,7 %. Attention en consequence : nombre_place ne compte QUE les places hors victoire."
                },
                {
                    "champ": "Popularite",
                    "colonne": "Popularite",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": null,
                    "description": "Popularite du cheval aupres des parieurs : nombre de turfistes qui l'ont mis a suivre depuis sa derniere course."
                },
                {
                    "champ": "prec_popularite",
                    "colonne": "prec_popularite",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": null,
                    "description": "Popularite lors de la sortie precedente."
                },
                {
                    "champ": "Evo_Popul",
                    "colonne": "Evo_Popul",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": null,
                    "description": "Evolution de la popularite depuis la sortie precedente."
                },
                {
                    "champ": "Rapport_SG",
                    "colonne": "Rapport_SG",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "euros pour 1 euro",
                    "description": "Rapport du Simple gagnant. Renseigne uniquement pour le gagnant, et seulement quand la source le publie : c'est la colonne la moins remplie de la base."
                },
                {
                    "champ": "Rapport_SP",
                    "colonne": "Rapport_SP",
                    "jeu": "base",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "euros pour 1 euro",
                    "description": "Rapport du Simple place, pour les chevaux places."
                },
                {
                    "champ": "discipline",
                    "colonne": "discipline",
                    "jeu": "base",
                    "portee": "course",
                    "type": "texte",
                    "unite": "code",
                    "description": "P plat, A trot attele, M trot monte, H haies, S steeple, C cross."
                },
                {
                    "champ": "distance",
                    "colonne": "distance",
                    "jeu": "base",
                    "portee": "course",
                    "type": "entier",
                    "unite": "metres",
                    "description": "Distance de la course."
                },
                {
                    "champ": "allocation",
                    "colonne": "allocation",
                    "jeu": "base",
                    "portee": "course",
                    "type": "entier",
                    "unite": "euros",
                    "description": "Allocation totale de la course. Sert a mesurer le niveau : un cheval qui passe de 100 000 a 20 000 euros descend de categorie."
                },
                {
                    "champ": "heure",
                    "colonne": "heure",
                    "jeu": "base",
                    "portee": "course",
                    "type": "texte",
                    "unite": "HH:MM",
                    "description": "Heure de depart, heure de Paris."
                },
                {
                    "champ": "nombre_partants",
                    "colonne": "nombre_partants",
                    "jeu": "base",
                    "portee": "course",
                    "type": "entier",
                    "unite": null,
                    "description": "Nombre de partants annonce par la source. C'est le peloton ENGAGE, forfaits compris : sur les 2 741 courses a forfait mesurees de janvier a juin 2026, il vaut le total des lignes 2 345 fois (85,6 %) et le total moins les non partants 275 fois seulement (10,0 %). Ne vous en servez donc pas pour compter les chevaux au depart : depuis le 12/09/2026 la reponse porte nombre_partants_initial et nombre_partants_reel, comptes ligne a ligne, et ce chiffre-ci est servi tel quel sous le nom nombre_partants_declare. Il peut aussi differer du nombre de lignes rendues quand la source ne publie pas tout le peloton : 398 courses sur les 8 530 mesurees (4,7 %)."
                },
                {
                    "champ": "owner",
                    "colonne": "Proprietaire",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Proprietaire du cheval. Colonne ajoutee retroactivement le 25/08/2026 (jointure sur l'historique) : elle n'est pas renseignee a 100 %, voyez le taux de remplissage sur /v1/schema avant d'en tirer une conclusion."
                },
                {
                    "champ": "breeder",
                    "colonne": "Eleveur",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Eleveur, ou naisseur, du cheval. Meme ajout retroactif que le proprietaire, meme reserve sur le taux de remplissage."
                },
                {
                    "champ": "idproprio",
                    "colonne": "idproprio",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Identifiant stable du proprietaire, calcule comme idjockey (empreinte du nom). A preferer au nom pour appeler /v1/personnes."
                },
                {
                    "champ": "ideleveur",
                    "colonne": "ideleveur",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Identifiant stable de l'eleveur, calcule comme idjockey. A preferer au nom pour appeler /v1/personnes."
                },
                {
                    "champ": "ELO_Proprio",
                    "colonne": "ELO_Proprio",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Classement ELO du proprietaire, sur la meme echelle que les autres ELO. Il figurait deja au catalogue de /v1/tops sans etre lisible sur le partant : servi ici depuis le 11/09/2026."
                },
                {
                    "champ": "ELO_Eleveur",
                    "colonne": "ELO_Eleveur",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Classement ELO de l'eleveur, sur la meme echelle que les autres ELO. Meme correction que l'ELO proprietaire, meme date."
                },
                {
                    "champ": "Sigma_Horse",
                    "colonne": "Sigma_Horse",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": null,
                    "description": "Fiabilite de l'estimation ELO du cheval : plus elle est haute, plus le classement repose sur un historique fourni. Le composite ELO_Cheval_fiable de /v1/tops ne retient que les chevaux au-dessus de 60."
                },
                {
                    "champ": "IMDC",
                    "colonne": "IMDC",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Montee (+) ou descente (-) de categorie depuis la sortie precedente, cinq points par echelon (Course F vers Course E = +5, Course F vers Course D = +10). LISEZ CECI AVANT DE VOUS EN SERVIR : la base stocke 0 aussi bien quand le cheval reste dans sa categorie que quand l'indice n'est pas calculable (maiden, handicap, a reclamer, internationale, course a rating, ou cheval debutant). Sur 202 732 partants mesures, 51,6 % des IMDC a zero ne sont PAS calculables. Croisez avec Classe_Groupe avant de conclure."
                },
                {
                    "champ": "Turf_Points",
                    "colonne": "Turf_Points",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "points",
                    "description": "Points turf du cheval, indicateur de forme du catalogue /v1/tops."
                },
                {
                    "champ": "TPch_90",
                    "colonne": "TPch_90",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "points",
                    "description": "Points turf du cheval sur les 90 derniers jours."
                },
                {
                    "champ": "Moy_TPch_90",
                    "colonne": "Moy_TPch_90",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "points",
                    "description": "Moyenne des points turf du cheval sur 90 jours."
                },
                {
                    "champ": "Rang_J",
                    "colonne": "Rang_J",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "rang",
                    "description": "Rang du jockey ou driver au classement. Plus le nombre est petit, mieux c'est : /v1/tops trie cet indicateur en ordre croissant."
                },
                {
                    "champ": "TPJ_90",
                    "colonne": "TPJ_90",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "points",
                    "description": "Points turf du jockey ou driver sur les 90 derniers jours."
                },
                {
                    "champ": "Synergie_JCh",
                    "colonne": "Synergie_JCh",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "pourcentage",
                    "description": "Synergie entre le driver et le cheval. Renseignee sur un peu plus de quatre lignes sur dix : lisez le taux sur /v1/schema avant d'en faire un critere eliminatoire."
                },
                {
                    "champ": "distanceRecord_sec",
                    "colonne": "distanceRecord_sec",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "secondes",
                    "description": "Record chronometrique du cheval ramene a la distance. Plus le chiffre est bas, mieux c'est."
                },
                {
                    "champ": "Taux_Incident",
                    "colonne": "Taux_Incident",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "fraction de 0 a 1",
                    "description": "Taux d'incident du cheval. Fraction, pas un pourcentage, et arrondie a deux decimales : incident divise par Courses_courues, verifie sur la base le 11/09/2026. Plus le chiffre est bas, mieux c'est. Dix lignes sur 286 850 depassent 1, un cheval pouvant cumuler plusieurs incidents sur une meme course."
                },
                {
                    "champ": "nombre_victoire",
                    "colonne": "nombre_victoire",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Nombre de victoires du cheval sur son historique. C'est le numerateur de Taux_Victoire."
                },
                {
                    "champ": "nombre_place",
                    "colonne": "nombre_place",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Nombre de places du cheval HORS victoires. Ce n'est donc pas a lui seul le numerateur de Taux_Place : celui-ci vaut nombre_victoire plus nombre_place. Verifie sur la base le 11/09/2026."
                },
                {
                    "champ": "Gains_Totaux",
                    "colonne": "Gains_Totaux",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "euros",
                    "description": "Gains cumules du cheval sur toute sa carriere."
                },
                {
                    "champ": "Gains_Course",
                    "colonne": "Gains_Course",
                    "jeu": "indicateurs",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "euros",
                    "description": "Gains moyens du cheval par course. Formule verifiee sur la base entiere le 11/09/2026 : Gains_Totaux divise par Courses_courues, exacte sur 266 483 lignes sur 266 483. Vous pouvez donc le recalculer vous-meme si vous preferez une autre fenetre."
                },
                {
                    "champ": "Courses_courues",
                    "colonne": "Courses_courues",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Nombre de courses courues par le cheval. C'est le DENOMINATEUR commun de Taux_Victoire, Taux_Place, Taux_Incident et Gains_Course, les quatre formules ayant ete verifiees sur la base entiere le 11/09/2026. Un taux de 0,50 sur deux courses et un taux de 0,50 sur quarante ne disent pas la meme chose : c'est ce champ qui fait la difference."
                },
                {
                    "champ": "incident",
                    "colonne": "incident",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "entier",
                    "unite": null,
                    "description": "Nombre d'incidents releves sur l'historique du cheval. C'est le numerateur de Taux_Incident, dont le denominateur est Courses_courues."
                },
                {
                    "champ": "Repos",
                    "colonne": "Repos",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "jours",
                    "description": "Nombre de jours ecoules depuis la sortie precedente."
                },
                {
                    "champ": "Classe_Groupe",
                    "colonne": "Classe_Groupe",
                    "jeu": "tout",
                    "portee": "course",
                    "type": "texte",
                    "unite": null,
                    "description": "Classe ou groupe de la course (Classe 2, Classe 3, A reclamer, Internationale...). A lire avec IMDC : c'est elle qui dit si la categorie est comparable d'une sortie a l'autre."
                },
                {
                    "champ": "Moy_Alloc",
                    "colonne": "Moy_Alloc",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "euros",
                    "description": "Allocation moyenne des dernieres courses du cheval. Se croise avec allocation pour mesurer une montee ou une descente de niveau en valeur, la ou IMDC la mesure en echelons."
                },
                {
                    "champ": "Moy_TPch_365",
                    "colonne": "Moy_TPch_365",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "points",
                    "description": "Moyenne des points turf du cheval sur 365 jours."
                },
                {
                    "champ": "TPJ_365",
                    "colonne": "TPJ_365",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "points",
                    "description": "Points turf du jockey ou driver sur 365 jours."
                },
                {
                    "champ": "Moy_TPJ_365",
                    "colonne": "Moy_TPJ_365",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Moyenne des points turf du jockey ou driver sur 365 jours."
                },
                {
                    "champ": "Moy_TPJ_90",
                    "colonne": "Moy_TPJ_90",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Moyenne des points turf du jockey ou driver sur 90 jours."
                },
                {
                    "champ": "PC",
                    "colonne": "PC",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": null,
                    "description": "Colonne PC de la base, servie telle quelle. Nous ne publions pas de definition pour celle-ci tant qu'elle n'est pas etablie de source sure : si vous vous en servez, mesurez-la vous-meme avant de lui faire confiance."
                },
                {
                    "champ": "ferrure_prec",
                    "colonne": "ferrure_prec",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Ferrure de la sortie precedente (FERRE, DEFERRE_ANTERIEURS, DEFERRE_POSTERIEURS, PROTEGE_ANTERIEURS...). A lire avec changement_ferrure."
                },
                {
                    "champ": "changement_ferrure",
                    "colonne": "changement_ferrure",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "texte",
                    "unite": "Oui/Non",
                    "description": "La ferrure change-t-elle par rapport a la sortie precedente."
                },
                {
                    "champ": "changement_driver",
                    "colonne": "changement_driver",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "texte",
                    "unite": "Oui/Non",
                    "description": "Le driver ou jockey change-t-il par rapport a la sortie precedente."
                },
                {
                    "champ": "Evo_Distance",
                    "colonne": "Evo_Distance",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "texte",
                    "unite": "Hausse/Baisse/Identique",
                    "description": "Evolution de la distance par rapport a la sortie precedente."
                },
                {
                    "champ": "Evo_Poids",
                    "colonne": "Evo_Poids",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "texte",
                    "unite": "Hausse/Baisse/Identique",
                    "description": "Evolution du poids porte par rapport a la sortie precedente. Sans objet au trot attele."
                },
                {
                    "champ": "Alloc_Precedente",
                    "colonne": "Alloc_Precedente",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "entier",
                    "unite": "euros",
                    "description": "Allocation de la derniere course du cheval, en euros. Vide quand aucune sortie precedente n'est connue. Connue avant le depart : elle ne dit rien de la course du jour. A lire avec allocation (celle du jour) et Rapport_Alloc."
                },
                {
                    "champ": "Place_Precedente",
                    "colonne": "Place_Precedente",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "texte",
                    "unite": null,
                    "description": "Place obtenue par le cheval a sa derniere course : un rang (1, 2, 3...) ou une lettre, D pour disqualifie, A ou T pour un arret ou une chute. Vide quand aucune sortie precedente n'est connue. C'est la place de la course d'avant, jamais celle du jour."
                },
                {
                    "champ": "Rapport_Alloc",
                    "colonne": "Rapport_Alloc",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "ratio",
                    "description": "Allocation du jour divisee par Alloc_Precedente : sous 0,90 le cheval descend de categorie, au-dessus de 1,10 il monte. Verifie sur 16 876 lignes de septembre 2026 : c'est exactement allocation / Alloc_Precedente. Vide quand Alloc_Precedente est vide."
                },
                {
                    "champ": "delta_poids",
                    "colonne": "delta_poids",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "kg",
                    "description": "Ecart de poids depuis la derniere sortie : poids du jour moins celui de la derniere course non NP du cheval, en kilos, arrondi a 0,1 (negatif : il porte moins). Toutes disciplines confondues pour la sortie precedente. Galop seulement. Null si l'une des deux valeurs manque. Calcule par turf.bzh, connu avant le depart."
                },
                {
                    "champ": "delta_valeur",
                    "colonne": "delta_valeur",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Ecart de valeur de handicap depuis la derniere sortie, arrondi a 0,1 (positif : le handicapeur juge le cheval meilleur). Calcule seulement si la derniere course est dans la meme discipline (P, H, S ou C) ; null sinon, et hors handicap. Galop seulement. Calcule par turf.bzh, connu avant le depart."
                },
                {
                    "champ": "poids_prec",
                    "colonne": "poids_prec",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "kg",
                    "description": "Poids porte a la derniere sortie non NP du cheval, en kilos. Galop seulement. Null si inconnu. Calcule par turf.bzh."
                },
                {
                    "champ": "valeur_prec",
                    "colonne": "valeur_prec",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "decimal",
                    "unite": "points",
                    "description": "Valeur de handicap de la derniere sortie non NP, publiee seulement si cette course est dans la meme discipline que celle du jour. Galop seulement. Null sinon. Calcule par turf.bzh."
                },
                {
                    "champ": "date_prec",
                    "colonne": "date_prec",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "date",
                    "unite": "YYYY-MM-DD",
                    "description": "Date (AAAA-MM-JJ) de la derniere sortie non NP du cheval avant la course. Galop seulement. Null si inconnue. Calcule par turf.bzh."
                },
                {
                    "champ": "disc_prec",
                    "colonne": "disc_prec",
                    "jeu": "tout",
                    "portee": "partant",
                    "type": "texte",
                    "unite": "code",
                    "description": "Discipline de la derniere sortie non NP (P, H, S, C, A ou M). Galop seulement. Null si inconnue. Calcule par turf.bzh."
                }
            ]
        },
        {
            "id": "csv",
            "titre": "Sortie tableur",
            "blocs": [
                {
                    "t": "p",
                    "v": "Ajoutez format=csv pour recevoir un fichier au lieu du JSON : UTF-8 avec marque d'ordre (Excel français), séparateur point-virgule, une ligne par enregistrement. Les booléens s'écrivent 1 ou 0, jamais une cellule vide, pour qu'un faux ne se confonde pas avec une donnée manquante. Le seul /dossier accepte aussi format=xlsx."
                },
                {
                    "t": "liste",
                    "v": [
                        "/v1/chevaux/{id}/historique",
                        "/v1/courses/{date}/{code_course}/rapports",
                        "/v1/courses/{date}/{rc}",
                        "/v1/courses/{date}/{rc}/cotes",
                        "/v1/courses/{date}/{rc}/cotes/historique",
                        "/v1/courses/{date}/{rc}/dossier",
                        "/v1/courses/{date}/{rc}/indicateurs",
                        "/v1/courses/{date}/{rc}/stats-premium",
                        "/v1/journees/{date}/cotes",
                        "/v1/journees/{date}/d4",
                        "/v1/journees/{date}/partants",
                        "/v1/journees/{date}/stats-premium",
                        "/v1/performances",
                        "/v1/programme",
                        "/v1/rapports",
                        "/v1/schema",
                        "/v1/stats-premium",
                        "/v1/tops",
                        "/v1/value-bets"
                    ]
                },
                {
                    "t": "note",
                    "v": "Liste construite à partir du contrat OpenAPI : elle ne peut pas vieillir. Si une adresse y manque alors qu'elle sert un CSV, c'est le contrat qui est en retard, pas cette liste."
                }
            ]
        },
        {
            "id": "pieges",
            "titre": "Les pièges, mesurés",
            "blocs": [
                {
                    "t": "p",
                    "v": "Chacun a coûté du temps à quelqu'un. Ils sont ici avec leur portée mesurée, pas en généralités."
                },
                {
                    "t": "liste",
                    "v": [
                        "La cote du jour n'est pas dans la colonne Cote. Elle est vide pour la journée en cours et pour la toute dernière journée de la base : elle arrive au rafraîchissement du lendemain matin. Pour le jour même, appelez /cotes. /v1/statut donne la dernière date exploitable.",
                        "Dix courses de l'historique partagent leur code RxCy avec une autre réunion le même jour (2025-11-15, 2025-11-16, 2026-07-17), soit 0,036 % des codes. La réponse porte alors ambigu: true et un avertissement ; ajoutez hippodrome= pour n'obtenir qu'un peloton. En CSV la demande est refusée en 422, un tableau ne pouvant pas porter l'avertissement.",
                        "Le PMU publie deux montants pour le même pari, en_ligne et point_de_vente, et ils ne paient pas pareil. Chaque ligne de /rapports porte rapport_pour_1_euro, ce que le PMU publie, et rapport_pour_la_mise_de_base, ce qu'un ticket encaisse.",
                        "Les rapports à zéro ne sont pas une absence : ils prouvent que la formule était proposée et que personne ne l'a trouvée. Filtrer par défaut sur les payants biaise à la hausse tout taux de réussite calculé ensuite.",
                        "Taux_Victoire, Taux_Place et Taux_Incident sont des fractions entre 0 et 1, pas des pourcentages : 0,21 se lit 21 %. Taux_Place compte la victoire comme une place, alors que nombre_place ne compte que les places hors victoire.",
                        "Les non partants : voir la section dédiée. C'est le piège le plus coûteux, parce qu'il ne se voit pas."
                    ]
                }
            ]
        },
        {
            "id": "cadre",
            "titre": "Cadre d'usage",
            "blocs": [
                {
                    "t": "liste",
                    "v": [
                        "Aucune réponse de cette API ne garantit un gain, et aucune ne doit être présentée comme telle. Tout taux publié porte son échantillon.",
                        "Les données restent soumises aux conditions d'usage de turf.bzh. La clé est nominative : ne la redistribuez pas.",
                        "Le jeu comporte des risques : endettement, isolement, dépendance. Interdit aux mineurs. Jouez avec modération."
                    ]
                }
            ]
        }
    ]
}
