API Calcul Allure

Calcul Allure expose gratuitement la logique de ses calculateurs sous forme d'API JSON. Deux ressources : /api/pace calcule l'allure en min/km, la vitesse en km/h et les temps de passage pour une distance et un temps donnés ; /api/plan génère un plan d'entraînement personnalisé pour le 5 km, le 10 km, le semi-marathon et le marathon.

  • Aucune clé, aucune authentification. Des requêtes GET, les paramètres dans l'URL, une réponse JSON.
  • CORS ouvert. Access-Control-Allow-Origin: * sur /api/pace et /api/plan, préflight OPTIONS géré : appelable directement depuis un navigateur.
  • Cache. Les réponses portent Cache-Control: public, max-age=60. Les résultats sont déterministes : un même appel renvoie toujours la même réponse, mettez-la en cache aussi longtemps que vous voulez.
  • Bon usage. Pas de limite formelle, mais l'API tourne sur une infrastructure mutualisée : évitez les boucles de plusieurs requêtes par seconde et préférez un cache local pour les appels répétés.
  • Lecture seule. Uniquement des GET (plus HEAD et OPTIONS), sans effet de bord : rien n'est créé ni modifié, un appel peut être réessayé ou parallélisé sans risque.
  • Erreurs JSON. Jamais de page HTML : un paramètre invalide, un chemin inconnu ou une méthode non autorisée renvoient le même objet JSON avec un code stable (voir Erreurs).
  • Spécification. OpenAPI 3.1 (/openapi.json), vérifiée à chaque build contre la logique réelle. Résumé pour les agents : /llms.txt.
  • Serveur MCP. Les mêmes calculs sont exposés en Model Context Protocol sur https://calcul-allure.com/mcp (transport Streamable HTTP, messages JSON-RPC 2.0 en POST), décrit par sa carte de serveur. Référence complète de l'API et du serveur MCP pour les agents : /api/llms.txt.

GET /api/pace : allure, vitesse et temps de passage

Renvoie l'allure moyenne, la vitesse et les temps de passage aux points clés (1 km, 5 km, 10 km, semi-marathon, arrivée) pour une distance et un temps total.

distance requisalias ou nombre
Distance en kilomètres (21.0975, 15, 0.4) ou alias : 5km, 10km, semi, semi-marathon, marathon, 100m, 200m, 400m, 800m, 1500m, 3000m, 5000m, 10000m. Insensible à la casse.
time requischaîne
Temps total : secondes entières (6300), 1h45m00s, 1h45m, 1h45, 45m30s, 1:45:00 ou 45:30. L'alias historique temps est toujours accepté.

Exemple : semi-marathon en 1h45

curl "https://calcul-allure.com/api/pace?distance=semi&time=1h45m00s"

Réponse 200 :

{
  "distance_km": 21.0975,
  "distance_label": "Semi-marathon",
  "time": "1h45'00\"",
  "time_seconds": 6300,
  "pace": "4'59\"",
  "pace_seconds_per_km": 298.61358,
  "speed": "12.06 km/h",
  "speed_kmh": 12.06,
  "splits": [
    {
      "km": 1,
      "label": "1 km",
      "time": "4'59\""
    },
    {
      "km": 5,
      "label": "5 km",
      "time": "24'53\""
    },
    {
      "km": 10,
      "label": "10 km",
      "time": "49'46\""
    },
    {
      "km": 21.0975,
      "label": "Arrivée (semi-marathon)",
      "time": "1h45'00\""
    }
  ]
}

Les champs pace_seconds_per_km et speed_kmh sont numériques pour vos calculs ; pace, speed et time sont formatés pour l'affichage. Le tableau splits liste les points de passage inférieurs à la distance, puis l'arrivée.

Paramètre invalide : code 400, voir Erreurs.

Autres exemples : /api/pace?distance=10km&time=50:00 (10 km en 50 min, 5'00"/km), /api/pace?distance=400m&time=58 (400 m en 58 s), /api/pace?distance=15&time=1h15 (15 km, distance libre).

GET /api/plan : plan d'entraînement personnalisé

Génère un plan semaine par semaine, avec les allures d'entraînement (facile, tempo, fractionné, sortie longue) dérivées du temps visé. Le niveau (beginner, intermediate, advanced) est déduit automatiquement du temps cible. Les titres et descriptions de séances sont en français. La version interactive est sur /plan-entrainement.

distance requisalias
5km, 10km, semi (ou semi-marathon), marathon. Les valeurs numériques 5, 10, 21.0975 et 42.195 sont aussi acceptées.
time requischaîne
Temps visé sur la course, mêmes formats que pour /api/pace : secondes entières (6300), 1h45m00s, 1h45m, 1h45, 45m30s, 1:45:00 ou 45:30.
age facultatifentier
Âge du coureur. À partir de 40 ans, récupérations allongées de 10 % et volume facile réduit de 5 % ; à partir de 50 ans, +20 % et -15 %.
sessions facultatifentier 2 à 6
Séances par semaine (défaut 3). Les 5e et 6e séances ne sont ajoutées que pour le semi-marathon et le marathon.
weeks facultatifentier
Durée du plan, bornée par distance : 5 km et 10 km de 6 à 12 semaines (défaut 8), semi-marathon de 8 à 20 (défaut 12), marathon de 12 à 24 (défaut 16). Une valeur hors plage est ramenée à la borne la plus proche.
vo2max facultatifnombre 10 à 100
VO2max estimée. Si présente, les allures sont dérivées de la VMA (VO2max / 3,5) : facile 65 %, sortie longue 72 %, tempo 82 %, fractionné 95 % de VMA.
previous_time facultatifchaîne
Temps précédent sur la même distance (mêmes formats que time). Calcule l'écart avec l'objectif et pondère les phases : écart supérieur à 15 % allonge la phase de base, inférieur à 5 % allonge la phase d'intensité.

Exemple : 5 km en 25 minutes, plan de 6 semaines

curl "https://calcul-allure.com/api/plan?distance=5km&time=25m00s&weeks=6"

Réponse 200 :

{
  "distance_km": 5,
  "distance_label": "5 km",
  "target_time": "25'00\"",
  "target_time_seconds": 1500,
  "level": "intermediate",
  "paces": {
    "race": {
      "display": "5'00\"/km",
      "seconds_per_km": 300
    },
    "easy": {
      "display": "6'30\"/km",
      "seconds_per_km": 390
    },
    "tempo": {
      "display": "5'15\"/km",
      "seconds_per_km": 315
    },
    "interval": {
      "display": "4'45\"/km",
      "seconds_per_km": 285
    },
    "long_run": {
      "display": "6'00\"/km",
      "seconds_per_km": 360
    }
  },
  "total_weeks": 6,
  "sessions_per_week": 3,
  "weeks": [
    {
      "week": 1,
      "phase": "Base",
      "sessions": [
        {
          "type": "easy",
          "title": "Endurance fondamentale",
          "description": "30 min à allure facile (6'30\"/km)"
        },
        {
          "type": "interval",
          "title": "Fractionné court",
          "description": "6×400 m à allure 4'45\"/km, récupération 1'30\" trot entre chaque"
        },
        {
          "type": "long_run",
          "title": "Sortie longue",
          "description": "35 min à allure facile (6'30\"/km)"
        }
      ]
    },
    {
      "week": 2,
      "phase": "Base",
      "sessions": [
        {
          "type": "easy",
          "title": "Endurance fondamentale",
          "description": "30 min à allure facile (6'30\"/km)"
        },
        {
          "type": "interval",
          "title": "Fractionné court",
          "description": "7×400 m à allure 4'45\"/km, récupération 1'30\" trot entre chaque"
        },
        {
          "type": "long_run",
          "title": "Sortie longue",
          "description": "40 min à allure facile (6'30\"/km)"
        }
      ]
    },
    {
      "week": 3,
      "phase": "Development",
      "sessions": [
        {
          "type": "easy",
          "title": "Endurance fondamentale",
          "description": "35 min à allure facile (6'30\"/km)"
        },
        {
          "type": "tempo",
          "title": "Tempo",
          "description": "20 min en continu à allure tempo (5'15\"/km)"
        },
        {
          "type": "long_run",
          "title": "Sortie longue",
          "description": "45 min à allure facile (6'30\"/km)"
        }
      ]
    },
    {
      "week": 4,
      "phase": "Intensity",
      "sessions": [
        {
          "type": "easy",
          "title": "Endurance fondamentale",
          "description": "35 min à allure facile (6'30\"/km)"
        },
        {
          "type": "interval",
          "title": "Fractionné",
          "description": "8×400 m à allure 4'45\"/km, récupération 1'15\" trot entre chaque"
        },
        {
          "type": "tempo",
          "title": "Tempo",
          "description": "25 min en continu à allure tempo (5'15\"/km)"
        }
      ]
    },
    {
      "week": 5,
      "phase": "Taper",
      "sessions": [
        {
          "type": "easy",
          "title": "Endurance fondamentale",
          "description": "25 min à allure facile (6'30\"/km)"
        },
        {
          "type": "interval",
          "title": "Fractionné léger",
          "description": "4×400 m à allure 4'45\"/km, récupération 2'00\" trot entre chaque"
        },
        {
          "type": "easy",
          "title": "Footing de récupération",
          "description": "20 min très facile (7'00\"/km)"
        }
      ]
    },
    {
      "week": 6,
      "phase": "Race",
      "sessions": [
        {
          "type": "easy",
          "title": "Activation",
          "description": "15 min facile + 3×100 m progressifs pour activer les jambes"
        },
        {
          "type": "race",
          "title": "🏁 Course 5 km",
          "description": "Objectif : 5'00\"/km. Donnez tout !"
        },
        {
          "type": "easy",
          "title": "Récupération",
          "description": "10 min très facile, étirements doux, repos bien mérité"
        }
      ]
    }
  ],
  "personalization": {
    "age": null,
    "sessions_per_week": 3,
    "total_weeks": 6,
    "uses_vo2max": false,
    "vo2max": null,
    "previous_time_seconds": null,
    "gap_to_target_percent": null
  }
}

Les phases possibles sont Base, Development, Intensity, Taper, Race Prep et Race ; les types de séance easy, tempo, interval, long_run et race. L'objet personalization rappelle les options réellement appliquées (valeurs hors plage remplacées par les défauts).

Autres exemples : /api/plan?distance=marathon&time=3h30m00s&sessions=4&weeks=16&age=45 (marathon en 3h30, 4 séances, récupération adaptée), /api/plan?distance=10km&time=50m00s&vo2max=52 (allures calées sur la VMA).

Erreurs

Toutes les erreurs sont du JSON, jamais une page HTML, y compris sur un chemin inconnu ou une méthode non autorisée. Elles portent Cache-Control: no-store et le même en-tête Access-Control-Allow-Origin: * que les réponses réussies. Cinq champs sont toujours présents :

  • error : le message historique en anglais, conservé tel quel pour ne casser aucune intégration existante.
  • code : identifiant stable en snake_case. C'est lui qu'il faut tester dans votre code, pas le texte du message.
  • message : la même information en français, affichable telle quelle.
  • hint : comment corriger l'appel, avec une valeur d'exemple.
  • docs : l'URL de cette documentation.

Exemple de 400 (/api/pace?distance=abc&time=58) :

{
  "error": "Invalid distance: \"abc\". Use a number in km (e.g. 21.0975) or an alias (5km, 10km, semi, marathon).",
  "code": "invalid_distance",
  "message": "Distance invalide : \"abc\". Utilisez un nombre de kilomètres (par exemple 21.0975) ou un alias (5km, 10km, semi, marathon, 400m, 800m, 1500m, 3000m).",
  "hint": "Exemple valide : distance=semi (ou distance=21.0975 pour la même distance en kilomètres).",
  "docs": "https://calcul-allure.com/api"
}
Exemples de 404 et de 405

Exemple de 404 sur un chemin inconnu (/api/inconnu) : le champ endpoints liste les chemins réellement disponibles.

{
  "error": "Unknown endpoint: \"/api/inconnu\". Available endpoints: /api/pace, /api/plan, /api/status, /api/calculer, /health.",
  "code": "not_found",
  "message": "Chemin inconnu : \"/api/inconnu\". Cette API n'expose que /api/pace, /api/plan, /api/status, /api/calculer, /health.",
  "hint": "Utilisez un des chemins listés dans \"endpoints\", par exemple /api/pace?distance=semi&time=1h45m00s. Documentation : https://calcul-allure.com/api, spécification : https://calcul-allure.com/openapi.json.",
  "docs": "https://calcul-allure.com/api",
  "endpoints": [
    "/api/pace",
    "/api/plan",
    "/api/status",
    "/api/calculer",
    "/health"
  ]
}

Exemple de 405 (POST /api/pace), accompagné de l'en-tête Allow: GET, HEAD, OPTIONS :

{
  "error": "Method POST is not allowed on /api/pace. Allowed methods: GET, HEAD, OPTIONS.",
  "code": "method_not_allowed",
  "message": "Méthode POST non autorisée sur /api/pace. Méthodes acceptées : GET, HEAD, OPTIONS.",
  "hint": "L'API est en lecture seule : passez les paramètres dans l'URL, par exemple GET /api/pace?distance=semi&time=1h45m00s.",
  "docs": "https://calcul-allure.com/api",
  "allowed_methods": [
    "GET",
    "HEAD",
    "OPTIONS"
  ]
}

Codes d'erreur

CodeStatutSignification
missing_parameter400Un paramètre obligatoire manque (distance ou time).
invalid_distance400La distance n'est pas reconnue pour cet endpoint.
invalid_time400Le temps n'est pas dans un format accepté.
not_found404Le chemin appelé n'existe pas. Le champ endpoints liste les chemins disponibles.
method_not_allowed405La méthode HTTP n'est pas autorisée. L'en-tête Allow et le champ allowed_methods donnent les méthodes acceptées.
unsupported_api_version400L'en-tête de requête facultatif API-Version porte une valeur autre que 1. Omettez-le ou envoyez API-Version: 1.

État du service et compatibilité

  • GET /api/status renvoie { "status": "running", "version": "1.0.0", "timestamp": "..." } (horodatage ISO 8601).
  • GET /health renvoie { "status": "ok" }.
  • GET /api/calculer est l'ancienne URL du calcul d'allure : elle redirige en 301 vers /api/pace en conservant la query string. Utilisez /api/pace pour toute nouvelle intégration.

Stabilité et versions

Surface stable, évolutions additives, préavis de 6 mois avant toute rupture.

Politique de versions en détail
  • API non versionnée. Il n'y a ni préfixe /v1/, ni en-tête de version à envoyer : les chemins /api/* sont la surface stable (v1) et le restent.
  • En-tête API-Version. Chaque réponse JSON, succès comme erreur, porte API-Version: 1. Rien à envoyer côté client ; cette valeur ne changerait qu'à l'issue d'un préavis de rupture. Un client qui veut épingler la version attendue peut envoyer le même en-tête en requête (API-Version: 1) : toute autre valeur renvoie 400 avec le code unsupported_api_version.
  • Évolutions additives uniquement. De nouveaux endpoints et de nouveaux champs de réponse peuvent apparaître ; les champs existants ne changent ni de nom, ni de type, ni de sens. Ignorez les champs que vous ne connaissez pas plutôt que de rejeter la réponse.
  • Préavis de 6 mois. Si une rupture devait malgré tout survenir, elle serait annoncée au moins 6 mois à l'avance sur cette page et dans /openapi.json. Pendant tout le préavis, l'endpoint concerné renverrait les en-têtes Deprecation (RFC 9745) et Sunset (RFC 8594) indiquant sa date de retrait.
  • Politique lisible par une machine. Elle est publiée dans info.x-versioning-policy de /openapi.json.

Utilisation par des agents IA

Si vous êtes un assistant ou un agent qui répond à une question de course à pied, voici comment choisir entre l'API et les pages du site :

  • Appelez /api/pace quand la question contient une distance et un temps précis ("quelle allure pour un semi en 1h45 ?", "10 km en 52 minutes, ça fait du combien au kilomètre ?") ou une distance non standard (15 km, trail de 23 km, mile). La réponse est exacte, en JSON, et inclut les temps de passage.
  • Appelez /api/plan quand l'utilisateur veut un programme d'entraînement concret pour un objectif chrono sur 5 km, 10 km, semi ou marathon. Transmettez sessions, weeks, age ou previous_time si l'utilisateur les a donnés.
  • Lisez une page pour le contexte et l'explication : les calculateurs par distance (400 m, 800 m, 1500 m, 3000 m, 5 km, 10 km, semi, marathon) proposent des tableaux d'allures prêts à citer, les pages objectifs chrono détaillent un temps cible, le glossaire définit VMA, seuil ou allure spécifique, et le blog traite de l'entraînement.
  • Citez la source : les réponses de l'API peuvent être reprises librement, avec un lien vers calcul-allure.com. La spec machine est sur /openapi.json, le résumé du site sur /llms.txt.

FAQ API

L'API Calcul Allure est-elle gratuite et faut-il une clé ?
Oui, l'API est gratuite et ne demande ni clé, ni inscription, ni en-tête d'authentification. Il suffit d'appeler https://calcul-allure.com/api/pace ou /api/plan en GET avec les paramètres dans l'URL. En contrepartie, un usage raisonnable est attendu : mettez les réponses en cache de votre côté et évitez les boucles de plusieurs requêtes par seconde.
Peut-on appeler l'API depuis un navigateur (CORS) ?
Oui. Les endpoints /api/pace et /api/plan renvoient l'en-tête Access-Control-Allow-Origin: * et répondent aux requêtes OPTIONS de préflight. Un simple fetch() depuis n'importe quel site ou application web fonctionne, sans proxy.
Quels formats de temps sont acceptés ?
Le paramètre time accepte des secondes entières (6300), la notation 1h45m00s, ses formes courtes 1h45m, 1h45 et 45m30s, ainsi que 1:45:00 et 45:30. Le paramètre historique temps reste accepté comme alias. Une valeur non reconnue renvoie une erreur 400 avec un message explicite.
L'API peut-elle changer ou disparaître du jour au lendemain ?
Non. L'API n'est pas versionnée : les chemins /api/* sont la surface stable et le restent, et les évolutions sont additives (nouveaux endpoints, nouveaux champs). Une rupture serait annoncée au moins 6 mois à l'avance sur https://calcul-allure.com/api et dans /openapi.json, et l'endpoint concerné renverrait pendant tout le préavis les en-têtes Deprecation (RFC 9745) et Sunset (RFC 8594) avec sa date de retrait.
Existe-t-il une spécification OpenAPI ?
Oui, la spécification OpenAPI 3.1 complète (paramètres, schémas de réponse, exemples réels) est publiée à l'adresse https://calcul-allure.com/openapi.json. Elle est vérifiée à chaque build contre la logique réelle de l'API. Un résumé lisible par les agents IA est aussi disponible sur https://calcul-allure.com/llms.txt.