Patterns de Conception d'API de Polymarket : Le Leader Mondial des Marchés de Prédiction
Modèle 1 : Séparer les API par domaine
Polymarket expose trois API avec des responsabilités distinctes :
- API Gamma (
gamma-api.polymarket.com) : découverte de marchés, événements, balises et recherche. - API CLOB (
clob.polymarket.com) : carnet d’ordres, prix et placement d’ordres. - API de données (
data-api.polymarket.com) : positions, transactions, analyses et classements.
Cette séparation ne relève pas seulement du nommage. Chaque domaine a ses propres contraintes :
| Domaine | Consommateurs principaux | Latence attendue | Authentification |
|---|---|---|---|
| Découverte | UI, recherche, indexeurs | Modérée | Publique |
| Trading | Bots, traders, teneurs de marché | Faible | Lecture publique, écriture authentifiée |
| Données | Dashboards, reporting, analytics | Variable | Publique, requêtes par portefeuille |
Au lieu de regrouper toutes les ressources sous une seule API (/markets, /orders, /users), définissez d’abord le but de chaque surface d’API :
- Découvrir → Gamma
- Trader → CLOB
- Analyser → Data API
Cette découpe permet de faire évoluer indépendamment :
- les mécanismes d’authentification ;
- les politiques de cache ;
- les limites de débit ;
- les SLA de latence ;
- les modèles de pagination et de streaming.
À appliquer : découpez vos API selon les flux métier et les profils de consommation, pas uniquement selon vos tables ou entités de base de données.
Modèle 2 : Privilégier un accès public aux données de lecture
Les données de marché - prix, carnets d’ordres, métadonnées d’événements et transactions historiques - sont accessibles publiquement :
curl "https://gamma-api.polymarket.com/events?limit=5"
Aucune clé API ni flux OAuth n’est nécessaire pour lire ces données. Cette approche réduit fortement la friction pour :
- les développeurs qui explorent la plateforme ;
- les interfaces publiques ;
- les outils d’analyse ;
- les bots qui surveillent les marchés ;
- les intégrations tierces.
Le principe est simple : séparez explicitement les autorisations de lecture et d’écriture.
GET /markets→ publicGET /order-book/:id→ publicPOST /orders→ authentifiéDELETE /orders/:id→ authentifié
Pour une plateforme où la lecture dépasse largement l’écriture, demander une authentification pour chaque endpoint public ajoute surtout de la complexité inutile.
À appliquer : Listez les endpoints qui exposent des données non sensibles. Rendez-les accessibles sans inscription si possible. Réservez les contrôles forts aux actions qui modifient un état, déplacent des fonds ou créent un engagement.
Modèle 3 : Utiliser deux niveaux d’authentification
Les endpoints de trading nécessitent une authentification en deux étapes.
Niveau L1 : prouver le contrôle du portefeuille
L’authentification L1 utilise une signature EIP-712 avec la clé privée de l’utilisateur. Elle sert à dériver des identifiants API :
// L1 : dériver des identifiants API depuis la clé privée
const credentials = await client.createOrDeriveApiKey();
// → { key: "...", secret: "...", passphrase: "..." }
Cette opération est sensible : elle prouve le contrôle du portefeuille.
Niveau L2 : signer les requêtes de trading
Une fois les identifiants dérivés, les requêtes utilisent HMAC-SHA256 :
{
"POLY_ADDRESS": "0x...",
"POLY_SIGNATURE": "<hmac-sha256>",
"POLY_TIMESTAMP": "1716000000",
"POLY_API_KEY": "550e8400-...",
"POLY_PASSPHRASE": "..."
}
Le modèle général est le suivant :
- L1 : « Je prouve mon identité avec un identifiant fort »
- L2 : « Je prouve que cette requête est autorisée »
Il évite de demander une signature de clé privée pour chaque appel à faible latence, tout en conservant un lien cryptographique avec l’identité initiale.
À appliquer : utilisez un facteur fort et rare pour créer une session ou des identifiants ; utilisez ensuite des credentials plus légers pour les appels fréquents ; définissez clairement la durée de vie, la révocation et la rotation des secrets L2.
Modèle 4 : Traiter les ordres comme des messages signés
Sur Polymarket, un ordre n’est pas une simple requête métier envoyée à un serveur. C’est un message signé qui constitue un engagement financier.
const response = await client.createAndPostOrder(
{
tokenID: "71321045679...",
price: 0.65,
size: 100,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: false,
},
OrderType.GTC
);
Le SDK :
- construit une structure EIP-712 typée ;
- la signe avec la clé privée ;
- soumet l’ordre signé ;
- permet au moteur de correspondance hors chaîne de traiter l’ordre ;
- utilise la signature lors du règlement sur Polygon.
La différence de sémantique est importante :
- API classique : « Veuillez effectuer cette opération pour moi. »
- Message signé : « Voici une autorisation cryptographique pour cette opération. »
Le message transporte lui-même une partie de l’autorisation. Ce modèle apporte des propriétés utiles :
- non-répudiation ;
- vérifiabilité ;
- limitation du pouvoir de l’opérateur ;
- séparation entre transport réseau et autorisation métier.
À appliquer : envisagez des payloads signés pour les opérations à fort enjeu : transactions financières, validation de documents, approbations irréversibles ou instructions réglementées.
Modèle 5 : Rendre l’ontologie du domaine explicite
Polymarket structure ses données autour de deux concepts :
- Événement : la question globale ;
- Marché : une issue binaire négociable de cet événement.
Exemple : une course électorale peut être un événement, et chaque candidat peut correspondre à un marché distinct.
{
"id": "501",
"title": "2026 Pennsylvania Senate Race",
"negRisk": true,
"markets": [
{
"id": "2301",
"question": "Will Bob Casey win?",
"outcomePrices": "[\"0.42\", \"0.58\"]"
},
{
"id": "2302",
"question": "Will Dave McCormick win?",
"outcomePrices": "[\"0.35\", \"0.65\"]"
},
{
"id": "2303",
"question": "Will a third candidate win?",
"outcomePrices": "[\"0.23\", \"0.77\"]"
}
]
}
L’API encode ainsi des relations métier importantes :
- un événement contient plusieurs marchés ;
- les résultats et leurs prix sont liés par index ;
outcomes[0]correspond àoutcomePrices[0];negRiskmodifie les relations de capital entre les marchés.
Ne masquez pas ces relations derrière une structure plate si elles influencent les calculs métier.
À appliquer : Identifiez les invariants de votre domaine. Ajoutez-les au modèle de réponse. Utilisez des types ou champs explicites plutôt que de les laisser uniquement dans la documentation. Faites échouer les requêtes invalides plutôt que de laisser le client interpréter des données ambiguës.
Modèle 6 : Exposer les relations de capital avec negRisk
Le champ negRisk indique qu’un événement comporte une relation financière particulière entre ses marchés : exactement un seul résultat peut gagner.
Dans ce contexte :
- 1 jeton « Non » sur le résultat A ≡ 1 jeton « Oui » sur tous les autres résultats
Exemple de conversion :
| Avant | Après |
|---|---|
| 1× Non (Autre) | 1× Oui (Casey) + 1× Oui (McCormick) |
Cette contrainte est visible dans l’API :
{
"negRisk": true
}
Elle doit aussi être fournie lors de la construction d’un ordre :
{
"tickSize": "0.01",
"negRisk": true
}
Le point important n’est pas seulement le champ lui-même. C’est le fait que l’invariant métier soit représenté dans le contrat d’API. Sans cette information, un bot peut calculer une exposition erronée. Le champ empêche donc une erreur de modélisation silencieuse.
À appliquer : lorsqu’une règle métier modifie les calculs, les transitions d’état ou les autorisations, encodez-la directement dans les schémas d’entrée et de sortie.
Modèle 7 : Diffuser les paramètres dynamiques comme état temps réel
La taille de tick n’est pas toujours fixe. Sur Polymarket, elle change selon le prix du marché. Quand le prix dépasse 0.96 ou descend sous 0.04, le tick minimum passe de 0.01 à 0.001 :
{
"event_type": "tick_size_change",
"asset_id": "65818619657...",
"old_tick_size": "0.01",
"new_tick_size": "0.001",
"timestamp": "100000000"
}
Cette granularité est nécessaire près des extrêmes. Entre 0.04 et 0.03, un mouvement de 0.01 représente 25 % de la probabilité initiale. Un tick de 0.001 permet une découverte de prix plus précise.
Le client doit donc traiter la taille de tick comme un état mutable :
let tickSize = "0.01";
socket.on("tick_size_change", (event) => {
if (event.asset_id === assetId) {
tickSize = event.new_tick_size;
}
});
Puis utiliser la valeur à jour lors de la création d’ordres :
const orderOptions = {
tickSize,
negRisk: true,
};
Ne codez pas ces paramètres en dur. Si le client ignore une transition d’état, ses ordres peuvent être rejetés.
À appliquer : distinguez les configurations statiques des paramètres dynamiques ; diffusez les changements de règles par événements ; permettez aux clients de reconstruire leur état après reconnexion ; documentez les actions attendues après chaque événement.
Modèle 8 : Séparer les WebSockets selon les consommateurs
Polymarket utilise deux couches WebSocket pour des besoins différents.
Canal de marché
Le canal de marché est destiné au trading :
wss://ws-subscriptions-clob.polymarket.com/ws/market
Les abonnements utilisent des IDs d’actifs :
{
"assets_ids": [
"65818619657568813474341868652308942079804919287380422192892211131408793125422"
],
"type": "market"
}
Les clients reçoivent notamment :
- snapshots de carnet d’ordres ;
- changements de prix ;
- exécutions ;
- changements de taille de tick.
Socket de données temps réel
Le second socket cible des usages plus larges :
wss://ws-live-data.polymarket.com
Il peut diffuser des commentaires, prix crypto, prix d’actions et événements sociaux.
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices",
"type": "update",
"filters": "btcusdt,ethusd"
}
]
}
Ces flux ont des contraintes différentes :
| Besoin | Flux de trading | Flux de données générales |
|---|---|---|
| Latence | Très faible | Variable |
| Volume | Carnets et exécutions | Activité, commentaires, prix externes |
| Identifiant | Asset ID | Sujet |
| Consommateur | Bot, teneur de marché | UI, dashboard, application sociale |
Un endpoint unique obligerait à faire des compromis sur les performances, la fiabilité et la complexité du protocole.
À appliquer : créez des flux distincts dès que les audiences ont des exigences réellement incompatibles en matière de latence, de volume ou de tolérance aux pertes.
Ce qu’il faut retenir
Les choix de conception de Polymarket suivent un principe cohérent : l’API expose la structure réelle du domaine au lieu de la masquer.
Pour rendre une API financière ou temps réel plus robuste :
- Séparez les surfaces d’API par usage métier.
- Rendez les données de lecture accessibles lorsque le risque le permet.
- Distinguez preuve d’identité et autorisation de requête.
- Utilisez des messages signés pour les actions irréversibles ou à fort enjeu.
- Exposez les relations métier importantes dans les schémas.
- Encodez les invariants comme champs typés et validations.
- Diffusez les changements d’état au lieu de laisser les clients les découvrir par erreur.
- Segmentez les infrastructures temps réel selon les besoins des consommateurs.
Une API ergonomique est utile. Une API fidèle au domaine l’est davantage : elle aide les clients à construire des intégrations correctes, notamment lorsque les erreurs de modélisation ont un coût financier direct.
Comments
No comments yet. Start the discussion.