Créez la clé
Inscrivez-vous avec votre e-mail. La clé Free est générée tout de suite, sans carte, et vous ne la voyez qu'une fois : rangez-la là où vous gardez vos secrets.
export ODSS_KEY="odss_live_…"
API de cotes sportives · pour développeurs et plateformes
Un seul format JSON pour le football, le tennis, le basket et tous les autres sports au programme. Chaque cote porte son last_update, et la fraîcheur du flux est mesurée et publique.
curl "https://odss-api.com/api/v1/mock/odds?sport=calcio&market=1x2&limit=2"
from odss_api import OdssApi
api = OdssApi.mock()
page = api.odds(sport="calcio", market="1x2", limit=2)
import { OdssApi } from "./odss-api";
const api = OdssApi.mock();
const page = await api.odds({ sport: "calcio", market: "1x2", limit: 2 });
Vrai flux : /api/v1/odds avec l'en-tête x-api-key · SDK Python · TypeScript
{
"mock": true,
"notice": "Dati SINTETICI a scopo di sviluppo: prezzi inventati, nessun rapporto con i listini reali dei book. Feed vero: /api/v1/* con chiave.",
"count": 7, "offset": 0, "returned": 2, "state": "prematch",
"odds": [
{
"event_id": "mock_39b522d4",
"event": "Juventus - Inter",
"sport": "calcio", "league": "Serie A",
"market": "1x2",
"bookmakers": [
{
"key": "mockbook_it_1", "country": "IT", "playable_it": true,
"is_exchange": false, "family": "mockplat_a",
"outcomes": { "HOME": 2.27, "DRAW": 3.14, "AWAY": 3.06 },
"last_update": "2026-09-23T23:59:00.000Z"
},
{
"key": "mockbook_it_2", "country": "IT", "playable_it": true,
"is_exchange": false, "family": "mockplat_a",
"outcomes": { "HOME": 2.8, "DRAW": 3.45, "AWAY": 2.46 },
"suspended": [],
"last_update": "2026-09-23T23:58:23.000Z"
},
{
"key": "mockbook_it_3", "country": "IT", "playable_it": true,
"is_exchange": false, "family": "mockplat_a",
"outcomes": { "HOME": 3.9, "DRAW": 2.42 },
"suspended": ["AWAY"],
"last_update": "2026-09-23T23:57:46.000Z"
}
]
}
]
}
Le champ notice est toujours en italien, quelle que soit la langue de la page.
Âge des cotes italiennes que vous recevez, sur les dernières 24 heures. Comment nous la mesurons
Comment ça marche
Inscrivez-vous avec votre e-mail. La clé Free est générée tout de suite, sans carte, et vous ne la voyez qu'une fois : rangez-la là où vous gardez vos secrets.
export ODSS_KEY="odss_live_…"
Filtrez par sport, ligue et marché avec les noms du flux. Un paramètre qui n'existe pas renvoie 400 et vous suggère le bon.
curl "https://odss-api.com/api/v1/odds?sport=calcio&market=1x2" \
-H "x-api-key: $ODSS_KEY"
Chaque cote indique quand elle a été lue (last_update) ; chaque réponse indique combien de requêtes il vous reste et quand le quota se réinitialise.
X-RateLimit-Limit: 100000
X-RateLimit-Remaining: 99870
X-RateLimit-Reset: 1791763200
Fraîcheur
Nous ne promettons pas le temps réel : nous mesurons l'âge des cotes et le publions, pour que vous décidiez à quel point vous fier à un prix.
Toutes les 2 minutes, sur l'instantané que l'API sert, nous mesurons l'âge de chaque cote d'avant-match des books italiens (maintenant − last_update) : c'est l'âge des cotes que vous recevez, pas celui dans le moteur. p50 et p95 sont la médiane des échantillons des dernières 24 heures ; le pointillé est le cycle avec lequel le moteur relit un book.
Ce n'est pas l'uptime, que nous ne déclarons pas, ni la latence de votre requête : c'est l'âge du prix que vous recevez. Une limite, dite : last_update est la fin de la lecture du book, et dans les lectures de détail qui durent des minutes les premières lignes lues sont un peu plus anciennes que leur horodatage.
Produit
REST pour interroger et streaming pour recevoir, avec une documentation lisible aussi par les machines. L'historique des mouvements n'est pas encore actif.
Mêmes noms de sports, de marchés et d'issues pour les books ADM, étrangers et les exchanges. Un marché que nous ne savons pas mapper avec certitude sort en other:<libellé>, jamais deviné.
| bookmakers[].key | HOME | DRAW | AWAY | last_update |
|---|---|---|---|---|
| mockbook_it_1 | 2.27 | 3.14 | 3.06 | 23:59:00Z |
| mockbook_it_2 | 2.80 | 3.45 | 2.46 | 23:58:23Z |
| mockbook_it_3 | 3.90 | 2.42 | suspended | 23:57:46Z |
| mockbook_it_4 | 3.16 | 2.64 | 2.58 | 23:57:09Z |
| mockbook_it_5 | 2.43 | 2.42 | 3.66 | 23:56:32Z |
| mockbook_it_6 | 2.36 | 2.31 | 4.49 | 23:55:55Z |
| mockbook_it_7 | 2.11 | 3.79 | 2.81 | 23:55:18Z |
| mockbook_uk_1 | 1.97 | 2.87 | suspended | 23:24:41Z |
| mockbook_sharp | 4.02 | 2.17 | 3.22 | 23:54:04Z |
| mockbook_exchange | 2.89 | 3.30 | 2.44 | 23:53:27Z |
Une issue que le book cote mais n'accepte pas en ce moment est dans suspended, pas dans outcomes : « non coté » et « coté mais fermé » restent deux faits distincts.
Des dizaines d'opérateurs italiens agréés ADM, plus des books de référence internationaux et des exchanges. La liste active est sur /api/v1/bookmakers, avec une clé : aucune liste de marques à croire sur parole.
Champs de la réponse de /api/v1/bookmakers : l'endpoint n'accepte aucun paramètre. Sur /api/v1/odds, country et playable_it servent aussi de filtres.
Sur /api/v1/stream n'arrivent que les enregistrements modifiés et supprimés, pas de polling : avec state=live, le live en général en 10 à 30 secondes. L'avant-match complet n'arrive pas de façon fiable aujourd'hui (un tour complet pèse des centaines de Mo) : il arrive avec des filtres étroits, par vagues ; pour tout l'avant-match, utilisez /odds.
id: mock.42 event: odds data: {"changed":[…],"removed":[]} : ping
GET /api/v1/mock/stream Flux d'exemple, sans clé · données synthétiques
Pas encore actif : aujourd'hui /odds/history répond vide (history_enabled: false) et l'appel compte dans le quota. Une fois actif : une ligne chaque fois qu'un book change un prix, et une fois le match commencé la première ligne est la clôture.
/coverage compte les marques avec une cote valide en ce moment ; /coverage/matrix indique, book par book et sport par sport, les marchés qu'elles cotent.
Marques avec une cote valide en ce moment, par région · GET /api/v1/coverage
Les variations arrivent en POST sur votre URL, signées HMAC-SHA256 ; une grosse livraison arrive en plusieurs pages numérotées.
POST <url> X-Odss-Timestamp: <unix> X-Odss-Signature: t=<unix>,v1=<hex> X-Odss-Page: 1/3 {"page": 1, "pages": 3, "changed": […], "removed": […], "changed_total": <n>, …}
Un agent découvre les outils sans clé et sans consommer de quota ; la clé sert à les appeler.
| Méthode JSON-RPC | Clé et quota |
|---|---|
| initialize | non |
| tools/list | non |
| tools/call | oui |
Python et TypeScript sans dépendances, avec pagination et erreurs typées. OpenAPI, Postman et llms.txt pour qui intègre avec un agent.
Comparaison
Où nous nous situons face aux API globales et à la moyenne du marché. Sans noms, sans promesses.
| Caractéristique | odss-api | Moyenne du marché |
|---|---|---|
| Books ADM italiens | Oui, vérifiables. /coverage public, /bookmakers avec clé ; l'âge des cotes que vous recevez est mesuré et public (p50/p95 sur /status). | Peu, souvent par book. Conçues pour les books étrangers (US/UK/offshore) : les concessionnaires ADM, quand ils y sont, sont peu nombreux et souvent facturés par book. |
| Comment on paie | Par compte. Quota mensuel + débit/min : plus de books ou marchés par événement n'augmentent pas le coût. | Par book ou en crédits. Crédits marchés×régions : en multi-book le coût explose. |
| Cross-book | Déterministe. Un event_id partagé par tous les marchés du match : comparaison native, pas de matching heuristique. | Souvent heuristique. Cotes propriétaires ou matching non déterministe. |
| Fraîcheur | Par book, en clair. last_update ISO sur chaque book : vous savez à quel point chaque jambe est récente. | Souvent absente. Non exposée par book individuel. |
| Prête pour les agents | Oui, standards ouverts. OpenAPI 3.1, llms.txt, JSON-LD, /.well-known/api-catalog : un agent la trouve et la lit tout seul. | Rarement. Docs derrière login ou crawlers bloqués, aucun standard agentique. |
| Prix & démarrage | Tarifs publics. Free tier, Enterprise self-serve configurable. Une clé en une minute. | Souvent sur devis. Enterprise opaque, ou self-serve avec peu de books italiens, souvent facturés par book. |
| Clés ciblées | Par sport ou ligue. Ex. une clé « foot uniquement », sans limite de nombre. | Non documenté. |
Couverture
Pas un catalogue : sports, ligues, événements et books lus à l'instant sur l'endpoint public /api/v1/leagues. Ils changent avec le programme, et vous pouvez les vérifier sans clé.
Nous n'excluons aucune ligue. Nous suivons les principaux bookmakers ADM — la liste exacte est sur /api/v1/bookmakers — et montrons tout ce qu'ils cotent : si un book du flux cote un match, vous le voyez ici aussi — des grandes ligues européennes aux divisions mineures et compétitions internationales. Ce qui apparaît dépend de la saison et de la période : pas de matchs, les bookmakers ne cotent pas, donc rien ne s'affiche. La liste ci-dessous est le programme à cet instant.
Chargement du programme…
La liste nominative des books actifs à cet instant est sur GET /api/v1/bookmakers, avec les champs country, playable_it, is_exchange et source : elle exige une clé API (la Free se crée en une minute, sans carte). Sans clé, GET /api/v1/leagues — d'où viennent les compteurs ci-dessus — et GET /api/v1/coverage sont publics.
Tarifs
Le streaming SSE arrive avec Pro, les webhooks avec Enterprise. Commencez gratuitement et résiliez quand vous voulez.
Dans toutes les offres, Free compris :
Pour explorer l'API. Pour toujours, sans carte.
0 € pour toujours, sans carte
500 requêtes/mois · 30/min
Exemple : écrire et tester l'intégration, sandbox compris.
Pour projets personnels et petits bots.
19 € par mois + TVA
10 000 requêtes/mois · 60/min
Exemple : une ligue lue toutes les 5 minutes, environ 8 600 requêtes par mois.
Pour bots et intégrations en production.
79 € par mois + TVA
100 000 requêtes/mois · 120/min
Exemple : trois ligues avec le live, lues toutes les 90 secondes : environ 86 000 requêtes par mois.
Pour plateformes et gros volumes.
159 € par mois + TVA
500 000 requêtes/mois · 600/min
Exemple : dix ligues avec le live, lues toutes les 90 secondes (environ 288 000 requêtes par mois), ou le stream.
Pour plateformes, entreprises et revendeurs : configurez volume, débit et licence — le prix se met à jour tout seul et vous activez au checkout, sans négociation.
Vous autorise à afficher les données aux utilisateurs finaux de votre produit — sites, applications, tableaux de bord, widgets, comparateurs (sans elle, l'usage reste interne). Elle n'autorise pas à créer ou commercialiser des services de surebet/arbitrage, de value betting ou des plateformes équivalentes, ni à redistribuer l'API ou les données brutes : il faut pour cela une licence commerciale dédiée. Lire la licence
Les prix indiqués s'entendent hors taxes. La taxe applicable est ajoutée au moment du paiement selon votre pays et votre statut fiscal : 22 % pour l'Italie (y compris pour les entreprises disposant d'un numéro de TVA italien) ; autoliquidation, taxe 0 %, pour les entreprises d'autres États membres de l'UE disposant d'un numéro de TVA valide ; opération hors champ de la TVA italienne pour les clients hors UE. Le montant total que vous payez est celui indiqué par le récapitulatif du paiement, que vous confirmez avant de valider votre commande (§4 des Conditions). Le quota vaut 30 jours à partir de la première requête de la période.
Solutions commerciales
Les cotes normalisées sont le premier niveau. Si le produit que vous voulez vendre, ce sont les arbitrages, il vous faut un autre niveau : les surebets déjà calculées, avec le droit de les revendre compris dans l'abonnement.
Niveau 1 · self-serve
Cotes et données normalisées. Du plan Free à l'Enterprise, tarif public et activation immédiate.
Voir les tarifsNiveau 2 · plan API
Pour qui construit dessus son propre produit. Elle ne renvoie pas que les cotes : elle renvoie les surebets déjà repérées et calculées par notre moteur, recalculées à chaque cycle d'analyse. Si vous n'avez personne à qui les revendre, elle ne vous sert pas : surebett.app suffit.
950 € par mois, hors taxes · licence de revente comprise · résiliable en un clic depuis le portail.
Les champs listés sont ceux prévus lorsqu'ils sont disponibles : la réponse contient ce que le moteur a réellement calculé pour cet événement. La licence de revente est comprise dans l'abonnement : vous pouvez utiliser les surebets calculées dans un produit commercial qui vous appartient, destiné à vos utilisateurs finaux, dans les limites de l'usage déclaré et des Conditions. Elle ne comprend pas le White Label, qui reste un contrat à part.
Activation dès le paiement, résiliation en un clic depuis le portail. C'est un plan à part qui ne s'ajoute pas à un plan du catalogue : si le compte en a déjà un payant actif, il faut le résilier d'abord. En continuant vous souscrivez la Surebet API Commercial License, dans les limites de l'usage que vous avez déclaré ci-dessus, et vous acceptez les Conditions du service (§5).
Niveau 3 · sous contrat
Pour les entreprises qui ne veulent pas développer la plateforme elles-mêmes : la Surebet complète, fournie comme service à votre marque.
2 000 € par mois, hors taxes · activation et durée selon le contrat White Label.
Le logiciel, le moteur et le code source restent notre propriété et sont concédés en usage selon le contrat White Label.
La licence « Redistribution Display » des plans API vous autorise à afficher les cotes dans votre produit : elle n'autorise pas à créer ou commercialiser des services de surebet/arbitrage, de value betting ou des plateformes substantiellement équivalentes, ni à redistribuer l'API ou les données brutes. Ces usages exigent la Surebet API Commercial License ou le contrat White Label — voir les licences commerciales et les Conditions, §5.
D'autres questions ? Écrivez à [email protected] ou ouvrez un ticket : une personne vous répond, par e-mail.
Oui : l'API expose les cotes des opérateurs italiens présents dans le flux, filtrables avec le paramètre bookmakers. La liste active à cet instant est sur GET /api/v1/bookmakers, qui exige une clé API (la Free se crée en une minute, sans carte) ; sans clé, /api/v1/leagues et /api/v1/coverage sont publics. Chaque cote porte son last_update.
Oui : l'API renvoie du JSON standard, donc direction Postgres, SQLite, pandas ou Google Sheets. Avec les SDK Python et TypeScript, quelques lignes suffisent ; le plan Free (500 requêtes/mois) permet d'essayer sans carte.
Chez nous : Free 500 requêtes/mois sans carte, Hobby 19 €/mois + TVA (10 000), Starter 79 €/mois + TVA (100 000), Pro 159 €/mois + TVA (500 000), Enterprise dès 199 € + TVA. Tous les montants s'entendent hors taxes : pour un particulier italien on ajoute 22%. Les entreprises d'autres États membres de l'UE disposant d'un numéro de TVA valide relèvent de l'autoliquidation (taxe 0 %) ; pour les clients hors UE l'opération est hors champ de la TVA italienne. Le total figure toujours dans le récapitulatif du paiement, que vous confirmez avant la commande (§4 des Conditions). Même couverture sur tous les plans : vous ne payez que le volume.
L'âge des cotes que vous recevez est mesuré, pas promis : p50 et p95 des dernières 24 h sont publics sur la status page, mesurés sur l'instantané servi. Streaming SSE pour le push ; le live a son propre flux, renouvelé toutes les quelques secondes.
L'usage interne — vos modèles, bots, analyses, outils — est inclus dans tous les plans. Afficher les données aux utilisateurs finaux de votre produit exige la licence de Redistribution Display (option Enterprise) : elle n'autorise que l'affichage. Si le produit que vous voulez vendre, ce sont les surebets — arbitrage, value betting ou services équivalents —, il faut la Surebet API, un plan à part à 950 €/mois + TVA, licence de revente comprise dans l'abonnement, avec la déclaration d'usage obligatoire : voir comment l'activer. Si vous n'avez personne à qui revendre, elle ne vous sert pas : surebett.app suffit. La plateforme complète à votre marque reste le White Label, sous contrat — voir Surebet API et White Label.
Le moteur relit les books italiens en cycle continu, mais ce qui compte, c'est l'âge des cotes que vous recevez : nous le mesurons sur l'instantané servi et le publions sur la status page, avec p50 et p95 des dernières 24 heures (octobre 2026 : p50 de 11 à 14 minutes en journée, environ 18 le soir). Le contenu italien du flux se renouvelle en moyenne toutes les 7 à 12 minutes, le live toutes les quelques secondes. Pas besoin de nous croire sur parole : chaque cote de la réponse porte son last_update.
Le plan Free est permanent et a la même couverture que les plans payants : vous vérifiez ainsi les données avant de payer. S'il vous faut plus de volume pour une évaluation, écrivez à [email protected].
Même moteur, deux produits : odss-api vend les cotes brutes normalisées pour construire dessus ; surebett.app est le produit fini, avec les arbitrages déjà calculés et des mises équilibrées.
Pour les développeurs
Base URL https://odss-api.com. Authentification via l'en-tête x-api-key: odss_live_… ou Authorization: Bearer. Réponses JSON, cotes décimales européennes.
Chaque endpoint a un jumeau sous /api/v1/mock/ qui répond tout de suite, sans inscription et sans consommer de quota : même forme de réponse, mêmes paramètres, même validation stricte que le flux réel. Les cotes sont synthétiques — mock: true, en-tête X-Odss-Mock: 1, ids préfixés mock_ — elles servent à écrire et tester votre code, pas à parier.
curl "https://odss-api.com/api/v1/mock/odds?sport=calcio&limit=3"
Disponibles : /mock/odds · /mock/odds/history · /mock/sports · /mock/bookmakers · /mock/leagues · /mock/status · /mock/stream (SSE) · /mock/ticker (une trame de cotes 1X2 d'exemple toutes les 5 s, sans paramètres). Le paramètre seed rend la réponse reproductible : utilisez-le en CI plutôt que de brûler du quota à chaque exécution.
Sur le flux RÉEL, sont aussi publics sans clé /api/v1/leagues, /api/v1/coverage, /api/v1/status et /api/v1/pulse.
curl "https://odss-api.com/api/v1/odds?sport=calcio&league=serie%20a&limit=5" \
-H "x-api-key: odss_live_..."
const r = await fetch(
"https://odss-api.com/api/v1/odds?sport=calcio&league=serie%20a&limit=5",
{ headers: { "x-api-key": "odss_live_..." } }
);
const { count, odds } = await r.json();
import requests
r = requests.get(
"https://odss-api.com/api/v1/odds",
params={"sport": "calcio", "league": "serie a", "limit": 5},
headers={"x-api-key": "odss_live_..."},
)
data = r.json() # { count, offset, returned, state, odds: [...] }
Les cotes cross-book actuelles, regroupées par événement, marché et ligne. Chaque enregistrement liste les bookmakers avec leurs issues et l'horodatage de leur dernière mise à jour.
| Paramètre | Description |
|---|---|
| sport string | Filtre exact sur le sport (ex. calcio, tennis, basket). Valeurs : voir /api/v1/sports. |
| market string | Marché canonique : 1x2, ou, btts, dc, ah (handicap asiatique), eh (handicap européen), moneyline… |
| bookmakers string | Liste CSV de clés book (ex. snai,bet365). Valeurs : voir /api/v1/bookmakers. |
| league string | Filtre par sous-chaîne, insensible à la casse (ex. serie a). Valeurs : voir /api/v1/leagues. |
| event_id string | Un seul événement, par id exact. |
| state prematch | live | all | prematch (par défaut), live (in-play, avec score et minute actuels) ou all (les deux). Avec live, si le moteur in-play est éteint la liste est vide et live_enabled=false. Si la clé a un périmètre de flux (prématch seul ou live seul), un state hors périmètre renvoie 403 et all se replie sur l'état autorisé. |
| limit integer | Enregistrements par page. Défaut 500, max 5000. |
| offset integer | Index de départ pour la pagination. Défaut 0. |
| content match | player | all | match = lignes de match uniquement ; player = player props uniquement ; all (par défaut) = les deux. Les props sont inclus dans chaque offre : le paramètre restreint la réponse, il ne débloque rien. |
| player string | Sous-chaîne du nom du joueur, insensible à la casse ; implique content=player. |
| commence_from · commence_to date-time | Fenêtre sur le début de l'événement (ISO 8601), bornes incluses. Avec une fenêtre, les enregistrements sans commence_time sont exclus ; une date illisible, ou from après to, donne un 400. |
| playable_it boolean | true = dans chaque enregistrement, seulement les bookmakers jouables depuis l'Italie (licence ADM) ; false = seulement les autres. Les enregistrements restés sans bookmaker sont retirés. |
| country string | CSV des pays de licence (ISO 3166-1 alpha-2, ou world) : seuls ces bookmakers restent dans chaque enregistrement, p. ex. IT ou GB,SE. |
| after string | Pagination STABLE par curseur : after= vide pour la première page, puis le next_after de la réponse jusqu'à null. L'ordre ne dépend pas du rafraîchissement du snapshot : une synchronisation complète n'a ni trous ni doublons. Exclusif avec offset ; combinable avec changed_since. |
| format full | compact | compact = les mêmes données sans répétition (métadonnées des bookmakers une fois dans books, données de l'événement une fois dans events) : environ 40 % d'octets en moins. Par défaut full, le schéma habituel. |
| changed_since string | Synchronisation DELTA, sur chaque offre. La première fois, changed_since= vide : réponse complète plus un delta_token. Ensuite renvoyez le jeton : seulement les enregistrements modifiés ou apparus (dans odds, dans leur état actuel) et ceux qui ont disparu (dans removed), avec un nouveau delta_token. Un jeton ancien (au-delà d'environ 10 minutes) ou d'un autre démarrage du serveur répond 410 resync_required : on repart avec changed_since= vide. Un enregistrement dont le prix n'a pas changé ne revient pas dans le delta : son last_update reste celui du dernier changement, même si le book a été relu ensuite. |
| Champ | Description |
|---|---|
| count | Total des enregistrements correspondant aux filtres (toutes pages). |
| offset · returned | Écho de l'offset demandé et enregistrements renvoyés dans cette page. |
| odds[].event_id | Id déterministe de l'événement : identique pour tous les marchés du même match et stable pendant toute la fenêtre prématch. |
| odds[].event | Nom normalisé de l'événement (Domicile - Extérieur). |
| odds[].sport · league | Sport et ligue/compétition de l'événement. |
| odds[].home_team · away_team | Les deux équipes, quand disponibles. |
| odds[].commence_time | Début de l'événement, ISO 8601 UTC. |
| odds[].market · line · scope · period | Marché canonique, ligne éventuelle (ex. 2.5), portée (ex. équipe) et période (ex. 1re mi-temps). |
| odds[].state · score · minute | state = prematch ou live. Pour le live : score (ex. « 1-0 ») et minute (ex. « 63' ») actuels. Même event_id que le prématch → corrèle le même match dans les deux états. |
| …bookmakers[].key | Clé du bookmaker, avec country, playable_it et is_exchange. |
| …bookmakers[].outcomes | Carte issue → cote décimale (ex. HOME: 2.10). |
| …bookmakers[].suspended | Issues que ce book cote mais sur lesquelles il n'accepte pas de paris en ce moment. Elles ne sont pas dans outcomes (une issue suspendue n'a pas de prix jouable) et sont nommées ici, pour que «le book ne propose pas cette issue» et «il la propose et elle est fermée maintenant» restent deux faits distincts. Champ optionnel, et son absence veut dire quelque chose: s'il manque, ce book ne déclare pas l'état; [] veut dire déclarée, et rien de suspendu. Ne lisez jamais l'absence comme une liste vide. |
| …bookmakers[].last_update | Horodatage ISO de la dernière mise à jour réussie de ce book. |
| …bookmakers[].family | Plateforme d'où vient la liste de prix. Des marques de la même famille peuvent servir la MÊME liste : les compter comme listes indépendantes invente des arbitrages qui n'existent pas. Même famille ne veut pas toujours dire même prix : c'est un avertissement de corrélation, pas une règle d'exclusion. |
| odds[].player · player_id | Seulement sur les lignes de player props (absents, pas null, sur les lignes de match) : player fait partie de l'identité de la ligne ; player_id est l'id stable du joueur chez ce bookmaker, pour le suivre d'un rafraîchissement à l'autre (pas un id valable entre bookmakers). |
Répétez l'appel en augmentant offset de returned, tant que offset + returned < count. Le programme est vivant : count peut varier légèrement entre les pages.
GET /api/v1/odds?sport=calcio&limit=1000&offset=0
GET /api/v1/odds?sport=calcio&limit=1000&offset=1000
# … tant que offset + returned < count
Les sports disponibles en ce moment dans le flux (les valeurs du paramètre sport).
Les bookmakers actifs dans le flux, chacun avec ces champs.
| Champ | Description |
|---|---|
| country | Code ISO 3166-1 alpha-2 du pays de licence (IT, GB, US, SE…), ou world lorsqu'il n'est pas attribué. |
| playable_it | true uniquement pour les books titulaires d'une licence ADM italienne, donc jouables depuis l'Italie ; false pour tous les autres books du flux, des références sharp comme Pinnacle aux marques étrangères. |
| is_exchange | Exchange, avec commission sur les gains. |
| feed_keys | Les clés avec lesquelles les cotes de cet opérateur sortent dans /odds : la marque et, le cas échéant, sa ligne de marché dédiée (ex. <marque>-corners). Un opérateur, une ligne. |
| derived_from | Seulement si les cotes d'avant-match de l'opérateur sont copiées d'un autre : la clé du book d'origine, comme derived_from sur chaque cote (derived_states dit dans quel état). |
| source | Type de canal de la liste de prix : direct | partner_feed. |
Le programme actuel agrégé : pour chaque sport, les ligues cotées, avec nombre d'événements et de bookmakers. Utile pour découvrir les valeurs du filtre league.
Server-Sent Events : n'arrivent que les enregistrements modifiés et supprimés, pas de polling. Avec state=live, le live arrive en général en 10 à 30 secondes (médiane mesurée, environ 15 s). Limite actuelle, mesurée le 8 octobre 2026 : avec state=all un tour d'avant-match complet pèse des centaines de Mo et la connexion tombe avant de le recevoir ; le flux est resté sans changement 79 % du temps, avec un resync toutes les 12 minutes environ. L'avant-match n'arrive qu'avec des filtres étroits (sport, marché, ligue), par vagues, quand l'instantané servi se renouvelle. Nous réécrivons la livraison en petites pages avec contre-pression ; d'ici là, pour tout l'avant-match, utilisez l'instantané paginé de /odds.
| Élément | Description |
|---|---|
| hello | À la connexion. |
| odds | Les enregistrements MODIFIÉS (même schéma que /odds, chacun avec son state) et les supprimés. |
| sport · state | Paramètres optionnels (state : prematch | live | all). Snapshot initial via GET /odds?state=…. |
| Cadence | Celle de l'instantané servi : le live se renouvelle toutes les quelques secondes, l'avant-match en moyenne toutes les 4 à 6 minutes (le contenu italien toutes les 7 à 12). last_update fait foi, avec une limite : à prix inchangé l'enregistrement n'est pas renvoyé, donc le last_update que vous avez reste celui du dernier changement même si le book a été relu ensuite. L'âge réel de l'avant-match servi est sur /status (served_age). |
| Limites | Max 3 streams concurrents ; la connexion compte pour 1 requête de quota. |
Pas encore actif. La capture est éteinte aujourd'hui : chaque appel répond 200 avec count: 0 et history_enabled: false, et compte dans le quota. Une fois actif : historique des variations de cote d'un événement, une ligne à chaque fois qu'un bookmaker bouge un prix sur un groupe. Filtres event_id (obligatoire), book, market, from/to (ISO), limit. Du plus récent : pour un événement commencé, la première ligne est sa clôture. Respecte la portée de la clé.
curl "https://odss-api.com/api/v1/odds/history?event_id=a3f9c1e07b2d4865&book=snai" \
-H "x-api-key: odss_live_..."
Middles Over/Under calculés sur le flux courant : OVER sur une ligne basse chez un book, UNDER sur une ligne haute chez un autre. Si le total tombe dans la fenêtre, les deux paris gagnent. Champs middle_window, hit_return_pct, miss_return_pct, safe (aucune perte même à côté). Filtres : sport, min_return, safe, limit.
Règle de fraîcheur : une cote figée depuis plus de stale_after_seconds (900s par défaut) reste dans les réponses de /odds avec son last_update, mais n'est jamais appariée dans un middle : une jambe périmée n'existe probablement plus chez le bookmaker. Le seuil appliqué et les jambes écartées figurent dans la réponse.
Limites de safe, aujourd'hui : certaines familles de marché ne sont pas encore séparées par unité (au tennis et au volley un total de sets peut côtoyer un total de jeux ou de points), certains pseudo-événements « Home - Away » d'une plateforme sont servis comme des matchs, et deux matchs homonymes peuvent partager un event_id. Dans ces cas safe: true n'est pas un vrai middle : avant d'agir, vérifiez que les deux jambes sont le même match, la même unité et le même horaire. La réponse le rappelle dans le champ safe_note.
curl "https://odss-api.com/api/v1/middles?sport=calcio&safe=true" \
-H "x-api-key: odss_live_..."
Combien de marques de bookmakers ont une cote valide dans le flux actuel, par région (Italie, USA, UK, monde). Correspond aux entrées de /api/v1/bookmakers : les deux comptent un opérateur une seule fois, avec ses lignes de marché dédiées (ex. <marque>-corners) sous la marque ; dans /bookmakers les clés de ses cotes sont dans feed_keys.
Pour chaque bookmaker, sport par sport : les marchés normalisés qu'il cote en ce moment, avec les lignes vues. Cela sert à distinguer trois choses qu'une liste plate confond.
Un marché non listé sous un opérateur attivo est une absence structurelle : il ne le cote pas, et demain ce sera pareil. Les bookmakers dans live_only_bookmakers ont des lignes mais pas en pré-match, donc sur leurs marchés pré-match cette réponse ne dit rien ; si un couloir du flux n'a pas répondu, incomplete_lanes le nomme et la couverture est partielle, pas absente.
Et un marché que le moteur ne sait pas mapper avec certitude n'est jamais deviné : il sort en other:<étiquette> et n'est ici que compté (other_markets), car deux books l'appellent différemment et comparer ces étiquettes serait faux — celles que beaucoup de books écrivent à l'identique sont dans other_markets_common. Portée prematch, recalculée au maximum toutes les 10 minutes (generated_at).
Le battement du flux, uniquement des nombres agrégés (ni prix, ni noms de books) : c'est ce que les pages de ce site interrogent d'elles-mêmes. Aucun paramètre, Cache-Control: public, max-age=5, limite par IP à part (60 par minute).
| Champ | Description |
|---|---|
| prematch_it_at | L'instant où a été publié l'instantané qui contient la voie italienne actuelle : jamais plus récent que les pages servies. |
| beats | Les dernières entrées d'une nouvelle voie italienne dans l'instantané servi, jusqu'à 30, collectées depuis le démarrage du serveur (beats_since). |
| freshness_24h | Pour chaque demi-heure des dernières 24 heures : served_p50 et served_p95, l'âge des cotes italiennes que vous receviez (échantillonné toutes les 2 minutes sur l'instantané servi), et p50/p95, l'âge dans le moteur. served porte les mêmes percentiles sur 24 heures. Une demi-heure sans échantillons reste vide, jamais estimée. |
Serveur MCP (JSON-RPC 2.0) pour agents IA et connecteurs (Claude, ChatGPT…). Auth avec la même clé (Authorization: Bearer odss_live_… ou x-api-key). Outils : get_odds (avec state=live), list_sports, list_bookmakers, list_leagues. Seul tools/call consomme du quota ; le handshake est gratuit. Stateless.
curl -X POST https://odss-api.com/api/mcp \
-H "Authorization: Bearer odss_live_..." -H "content-type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"get_odds","arguments":{"sport":"calcio","state":"live","limit":5}}}'
Enregistrez une URL https et recevez les changements de cotes par POST, avec le même payload {changed, removed} que le flux.
| Élément | Description |
|---|---|
| POST /api/account/webhooks | Depuis le tableau de bord ou via l'API, avec la session compte. Body {url, sport?, state?} ; le secret n'est montré qu'une fois, max 20 par compte. |
| X-Odss-Signature | t=<unix>,v1=<hex> = HMAC-SHA256 de «{timestamp}.{body}» avec le secret. Chaque livraison est signée : vérifiez-la, rejetez les vieux timestamps. |
| X-Odss-Page | page/total : une livraison peut arriver en plusieurs POST consécutifs, chacun signé séparément. Chaque corps porte page, pages, changed_total et removed_total, la première page vous dit donc déjà combien arrive. |
| Règles | Répondez 2xx. https uniquement, pas de redirections ; les endpoints en échec se désactivent. Ne limitez pas la fréquence de l'endpoint : une page refusée arrête les suivantes. |
Chaque réponse authentifiée inclut X-RateLimit-Limit (quota mensuel du plan), X-RateLimit-Remaining et X-RateLimit-Reset (temps unix en secondes où la fenêtre se rouvre ; sur le 429 de quota la même date est dans le corps comme retry_at). Le quota vaut pour une fenêtre de 30 jours qui commence à la première requête de la période : à son terme, le compteur repart de zéro avec la requête suivante.
| Code | Description |
|---|---|
| 400 | Requête invalide : paramètre inconnu, valeur hors de celles admises (ex. state) ou paramètre obligatoire manquant (ex. event_id sur /odds/history). Le corps de la réponse indique lequel. |
| 401 | Clé absente, invalide ou révoquée. |
| 403 | Hors périmètre : compte suspendu, flux hors du périmètre de la clé (ex. live avec une clé prématch seul) ou fonction selon le plan (stream : Pro et Enterprise ; webhooks : Enterprise). |
| 429 | Burst : requêtes par minute du plan dépassées. En-tête Retry-After: 60. |
| 429 | Quota mensuel épuisé : passez au plan supérieur ou attendez la fenêtre. |
| 502 | Flux temporairement indisponible : réessayez avec backoff. |
Sur tous les endpoints /api/v1, un paramètre que nous ne reconnaissons pas n'est jamais ignoré : si vous écrivez bookmaker au lieu de bookmakers, vous recevez 400 avec le nom erroné, la liste de ceux admis sur cet endpoint et, s'il s'agit d'une faute de frappe, la suggestion du nom correct. La comparaison est exacte : même Sport avec une majuscule est rejeté. Les endpoints de catalogue (/sports, /bookmakers, /leagues, /coverage, /status) n'acceptent aucun paramètre. Nous préférons une erreur immédiate à une réponse 200 avec des données non filtrées qui semblent correctes : le 400 est déterministe, il doit être corrigé et non réessayé, et il ne consomme pas de quota.
La même règle s'applique aux arguments des outils du serveur MCP (POST /api/mcp) : un nom qui n'existe pas, ou un type erroné comme une liste au lieu de la chaîne CSV, reçoit une erreur JSON-RPC -32602 plutôt que d'être ignoré. Le champ error.data contient les noms admis, de sorte que l'agent se corrige tout seul.
curl "https://odss-api.com/api/v1/odds?bookmaker=snai" -H "x-api-key: odss_live_..."
HTTP/1.1 400 Bad Request
{
"error": "Parametro sconosciuto: \"bookmaker\" (forse intendevi \"bookmakers\"?). Ammessi su questo endpoint: after, bookmakers, changed_since, commence_from, commence_to, content, country, event_id, format, league, limit, market, offset, playable_it, player, sport, state"
}
Pour générer des clients, SDK ou utiliser l'API depuis un agent IA : le contrat OpenAPI 3.1 et un guide concis pour LLM sont publics et toujours synchronisés.
| Ressource | Description |
|---|---|
| /openapi.json | Contrat OpenAPI 3.1 (endpoints, paramètres, schémas, auth x-api-key). |
| /llms.txt | Guide markdown pour LLM (llmstxt.org) : résumé et liens vers les ressources. |
| /postman_collection.json | Collection Postman : importez-la et définissez la variable x-api-key pour tester les endpoints tout de suite. |
| /sdk/odss_api.py | SDK Python officiel (fichier unique, sans dépendances) : client typé avec pagination automatique et support live. |
| /sdk/odss-api.ts | SDK TypeScript officiel (fichier unique, sans dépendances) : types, itérateur async et helper pour le flux SSE. |
| /.well-known/api-catalog | Catalogue d'API (RFC 9727, linkset JSON). |
L'usage interne (modèles, bots, analyses, backtests) est inclus dans tous les plans. Redistribuer les données — p. ex. les afficher aux utilisateurs finaux de votre produit — exige la licence de Redistribution Display (option Enterprise, +120 €/mois), qui ne couvre que l'affichage. Créer, alimenter ou commercialiser des services de surebet/arbitrage, de value betting ou équivalents exige en revanche la Surebet API, le plan qui comprend la licence pour revendre les surebets calculées : 950 €/mois + TVA. Redistribuer l'API ou les données brutes reste hors de tout plan : pour cela, écrivez à [email protected].
Quand vous êtes prêt, la clé Free se crée en une minute. Sans carte.
curl https://odss-api.com/api/v1/mock/odds