Démarrer

L'API est en lecture seule et renvoie du JSON. Elle expose uniquement les équipes des clubs que vous suivez dans votre espace (« Mes clubs »), ainsi que leurs matchs, compétitions, classements et effectifs.

  1. Créez un compte et passez au forfait Pro ou Business.
  2. Dans Mon compte → Clés API, générez une clé (elle n'est affichée qu'une fois).
  3. Transmettez-la dans l'en-tête Authorization de chaque requête.
curl https://www.sport-manager.fr/api/me/teams \
  -H "Authorization: Bearer VOTRE_CLE_API" \
  -H "Accept: application/json"

Forfaits et quotas

ForfaitAPIQuotaWebhooks
Gratuit Non — —
Pro Oui 60 requêtes / minute —
Business Oui 300 requêtes / minute Jusqu'à 5

Au-delà du quota, l'API répond 429 Too Many Requests avec l'en-tête Retry-After. Le nombre d'appels par clé est affiché dans « Mon compte ».

Endpoints

Toutes les URL sont relatives à https://www.sport-manager.fr/api. Les propriétés sont en camelCase et les valeurs nulles sont conservées.

Méthode et cheminDescriptionParamètres
GET /me/teamsÉquipes des clubs suivis—
GET /me/teams/{id}Détail d'une équipe—
GET /me/teams/{teamId}/resultsDerniers résultats de l'équipeseason, limit (100 max)
GET /me/teams/{teamId}/fixturesProchains matchslimit (100 max)
GET /me/teams/{teamId}/standingsClassements des compétitions de l'équipeseason
GET /me/teams/{teamId}/squadEffectif (contrats actifs)season
GET /me/games/{id}Détail d'un match—
GET /me/standings/{competitionId}Classement d'une compétition—
GET /me/competitions/{id}/calendarCalendrier complet (journées et matchs)—
GET /me/players/{id}Fiche joueur (statistiques par compétition, sélections)—
GET /me/teams/{teamId}/player-stats BusinessStatistiques des joueurs de l'équipe : apparitions, titularisations, buts, penalties, passes décisives, contre-son-camp, cartonsseason
GET /me/competitions/{id}/scorers BusinessClassement des buteurs de la compétition (toutes équipes)limit (20 par défaut, 100 max)
GET /me/games/{id}/sheet BusinessFeuille de match : compositions des deux équipes et événements (buts avec passeur, cartons, remplacements)—

Les statistiques joueurs sont calculées à partir des feuilles de match des matchs terminés : elles ne concernent que les compétitions dont les compositions et événements sont saisis.

season accepte current (par défaut), all ou l'identifiant d'une saison (les saisons passées nécessitent un forfait incluant l'historique complet). Chaque ligne de classement et chaque camp d'un match portent isMine quand il s'agit d'une équipe d'un club suivi.

Exemple : classement d'une compétition

GET /api/me/standings/42

{
  "id": 42,
  "competition": { "id": 42, "name": "Régional 1", "season": "2026/27", "format": "championship" },
  "rows": [
    {
      "position": 1, "teamId": 7, "clubId": 3, "name": "FC Exemple",
      "played": 12, "wins": 9, "draws": 1, "losses": 2,
      "goalsFor": 28, "goalsAgainst": 11, "goalDifference": 17,
      "points": 28, "zone": { "type": "promotion", "label": "Montée", "color": "#16A34A" },
      "isMine": true
    }
  ]
}

Erreurs

Les erreurs suivent le format application/problem+json (RFC 7807) : status, title, detail.

CodeSignification
401Clé absente ou invalide.
403Forfait sans accès à l'API ou à la ressource demandée (statistiques joueurs : Business ; saisons passées : historique complet), ou clé sans la capacité de lecture.
404Ressource inexistante ou sans lien avec vos clubs suivis (son existence n'est pas révélée).
422Paramètre de requête invalide.
429Quota par minute dépassé.

Webhooks (forfait Business)

Plutôt que d'interroger l'API en boucle, recevez une requête POST en JSON dès qu'un événement concerne l'un de vos clubs. Déclarez vos URL (HTTPS uniquement) dans Mon compte → Webhooks.

ÉvénementDéclenché quand…
game.finished un résultat est publié ou corrigé — Résultat publié
game.rescheduled la date ou l'heure d'un match change, ou le match est reporté (statut postponed) — Date ou horaire modifié
standing.updated un classement change (positions, points, buts) — Classement mis à jour
pingvous cliquez sur « tester » dans Mon compte

En-têtes envoyés

X-SportManager-EventNom de l'événement
X-SportManager-DeliveryIdentifiant unique de la notification (identique en cas de nouvel essai : utilisez-le pour dédoublonner)
X-SportManager-TimestampHorodatage Unix de l'envoi
X-SportManager-Signaturesha256= suivi du HMAC SHA-256 de timestamp + "." + corps avec votre secret

Répondez par un code 2xx en moins de 10 secondes. Sinon, deux nouveaux essais ont lieu (après 1 puis 5 minutes). Après 10 échecs consécutifs, le webhook est désactivé. L'historique des envois est consultable dans Mon compte.

Exemple : game.finished

{
  "event": "game.finished",
  "id": "9b1f0c1e-3a57-4d8e-9d0a-2f6c7e1b5a44",
  "createdAt": "2026-09-27T17:05:12+02:00",
  "data": {
    "game": {
      "id": 1234, "status": "finished", "kickoffAt": "2026-09-27T15:00:00+02:00", "day": 6,
      "venue": "Stade municipal",
      "competition": { "id": 42, "name": "Régional 1", "season": "2026/27" },
      "home": { "teamId": 7, "clubId": 3, "nationalTeamId": null, "name": "FC Exemple", "score": 2, "outcome": "W", "forfeit": false },
      "away": { "teamId": 9, "clubId": 5, "nationalTeamId": null, "name": "AS Voisine", "score": 1, "outcome": "L", "forfeit": false }
    },
    "followedClubIds": [3]
  }
}

Vérifier la signature

// PHP
$body = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_SPORTMANAGER_TIMESTAMP'];
$expected = 'sha256='.hash_hmac('sha256', $timestamp.'.'.$body, getenv('SPORTMANAGER_WEBHOOK_SECRET'));

if (! hash_equals($expected, $_SERVER['HTTP_X_SPORTMANAGER_SIGNATURE'] ?? '')
    || abs(time() - (int) $timestamp) > 300) {
    http_response_code(401);
    exit;
}
// Node.js (Express, avec express.raw({ type: 'application/json' }))
const crypto = require('crypto');

app.post('/webhooks/sport-manager', (req, res) => {
  const timestamp = req.get('X-SportManager-Timestamp');
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.SPORTMANAGER_WEBHOOK_SECRET)
    .update(timestamp + '.' + req.body)
    .digest('hex');
  const received = req.get('X-SportManager-Signature') || '';

  if (expected.length !== received.length
      || !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))) {
    return res.sendStatus(401);
  }
  const event = JSON.parse(req.body);
  // … traiter event.data
  res.sendStatus(204);
});

Flux iCal (tous les forfaits)

Chaque club suivi dispose d'une URL d'abonnement au format iCalendar, à ajouter dans Google Agenda, Outlook ou Apple Calendrier (page Widgets du club, encadré « Calendrier à synchroniser »). Le flux contient jusqu'à 500 matchs : la saison en cours avec le forfait Gratuit, sinon les 12 derniers mois et tous les matchs à venir. Les scores apparaissent dans le titre dès qu'ils sont publiés.

https://www.sport-manager.fr/calendar/VOTRE_CLE_WIDGETS/slug-du-club.ics

Widgets

Classement, calendrier, fiche club, dernier et prochain match : copiez le code depuis la page Widgets de votre club.

<script src="https://www.sport-manager.fr/widget.js" async></script>

<sm-standings account="VOTRE_CLE_WIDGETS" club="slug-du-club"
  competition="slug-de-la-competition" theme="auto" rows="10" show-form="true"></sm-standings>
Les widgets s'actualisent seuls pendant les matchs en cours et s'adaptent au mode sombre avec theme="auto". Le forfait Business permet d'y injecter votre propre CSS (marque blanche).

Changements

Octobre 2026 — statistiques joueurs (Business)

Trois endpoints réservés au forfait Business : /me/teams/{teamId}/player-stats, /me/competitions/{id}/scorers et /me/games/{id}/sheet. Les autres forfaits reçoivent une erreur 403 explicite. Par ailleurs, les données des saisons passées (season=all ou identifiant) renvoient 403 pour un forfait sans historique complet.

Octobre 2026 — webhook game.rescheduled

Nouvel événement envoyé quand la date ou l'heure d'un match change, ou quand le match est reporté (status vaut alors postponed). La charge utile est identique à celle de game.finished. Cochez-le dans Mon compte → Webhooks pour le recevoir.

Octobre 2026 — décalage horaire des dates

Les dates (kickoffAt, dates de journée, createdAt des webhooks) sont exprimées à l'heure de Paris avec leur décalage réel : 2026-09-27T15:00:00+02:00 en heure d'été, +01:00 en heure d'hiver. Auparavant, la même heure était annoncée avec +00:00 : un client qui convertissait les dates dans un autre fuseau obtenait un décalage de 1 à 2 heures. L'heure affichée ne change pas ; si vous aviez compensé ce décalage de votre côté, retirez cette correction.