Chapitre 27 sur 33
La version courte
Polymarket expose trois API publiques : CLOB (trading), Gamma (découverte de marchés) et Data (analytique). Le SDK Python officiel est py-clob-client 0.34.6. L'authentification utilise une clé d'API + signature ECDSA, les ordres étant signés via EIP-712 à travers un portefeuille proxy sur Polygon. Les limites de débit vous restreignent à environ 60 ordres/minute par clé. Le plus gros écueil pour les nouveaux développeurs est le problème de mappage condition_id → token_id entre Gamma et CLOB - réglez-le en premier, et tout le reste se met en place. Chaque mois, on gagne sur Polymarket environ 40 millions $ en récompenses de liquidité et en spread capturé par les bots, presque entièrement par des utilisateurs de l'API.
Partie 1 : Les trois API
Polymarket sépare proprement les responsabilités entre trois services distincts. Utiliser la bonne API pour chaque tâche garde votre bot rapide, simple et dans les limites de débit.
| API | URL de base | But | Authentification requise |
|---|---|---|---|
| CLOB API | clob.polymarket.com | Passer, annuler et suivre des ordres. Lire des carnets d'ordres. Interroger des positions. | Oui (pour le trading) |
| Gamma API | gamma-api.polymarket.com | Parcourir les marchés, récupérer métadonnées, images, prix des résultats, volume, échéance, tags. | Non (publique) |
| Data API | data-api.polymarket.com | Transactions historiques, instantanés de positions, analytique utilisateur, données de classement. | Non (publique) |
Une boucle de bot typique utilise Gamma pour trouver des marchés, CLOB pour récupérer les carnets d'ordres et passer des transactions, et Data pour back-tester la performance de la stratégie hors ligne. Pensez à Gamma comme au « catalogue », à CLOB comme à la « bourse » et à Data comme à l'« entrepôt ».
curl ou un navigateur dès maintenant - sans compte. C'est un excellent moyen de prototyper avant même de générer une clé d'API.Partie 2 : Authentification et le modèle de portefeuille proxy
Polymarket ne signe pas les transactions avec la clé privée de votre portefeuille principal. À la place, il utilise un portefeuille proxy de style Gnosis Safe : votre portefeuille principal autorise un proxy, et le proxy exécute toutes les transactions sur Polygon. Votre bot d'API parle à ce proxy.
Ce dont vous avez besoin
- Clé d'API - générez-la dans Settings → Developer de Polymarket
- Clé privée - la clé de votre portefeuille de trading (PAS la phrase de récupération de votre MetaMask principal)
- Adresse funder - l'adresse de votre portefeuille proxy (affichée dans Settings → Wallet)
- Chain ID -
137(Polygon mainnet) - Type de signature -
1(POLY_PROXY, standard pour les particuliers)
.env) ou un gestionnaire de secrets. Ne collez jamais de clés dans Discord, dans des issues GitHub ou dans ChatGPT. Supposez que toute clé qui touche votre presse-papiers est déjà compromise. Faites tourner les clés au moindre doute.Partie 3 : Installer py-clob-client
Le SDK Python officiel est le moyen le plus rapide de passer de zéro à votre premier ordre. Nous utiliserons la version 0.34.6, qui est l'actuelle en avril 2026.
# Create a virtual environment first
python3 -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windows
# Install the SDK
pip install py-clob-client==0.34.6 requests websocket-client python-dotenvConfiguration de base du client
import os
from dotenv import load_dotenv
from py_clob_client.client import ClobClient
from py_clob_client.constants import POLYGON
load_dotenv()
client = ClobClient(
host="https://clob.polymarket.com",
key=os.environ["POLY_PRIVATE_KEY"],
chain_id=POLYGON, # 137
signature_type=1, # POLY_PROXY
funder=os.environ["POLY_FUNDER"],
)
# One-time: derive and cache API credentials
client.set_api_creds(client.create_or_derive_api_creds())L'appel à create_or_derive_api_creds() signe un message avec votre clé privée et l'échange contre une clé d'API, un secret et une passphrase. Mettez-les en cache dans votre .env après la première exécution pour ne pas appeler l'endpoint de dérivation à chaque démarrage.
POLY_PRIVATE_KEY=0xabc...
POLY_FUNDER=0xdef...
POLY_API_KEY=...
POLY_SECRET=...
POLY_PASSPHRASE=...Partie 4 : Découvrir des marchés via Gamma
Avant de pouvoir trader, vous devez trouver des marchés qui en valent la peine. Gamma renvoie du JSON avec tout ce que l'interface de Polymarket affiche : question, résultats, prix, volume 24h, échéance, tags et images.
import requests
resp = requests.get(
"https://gamma-api.polymarket.com/markets",
params={
"active": "true",
"closed": "false",
"tag_slug": "politics",
"limit": 20,
"order": "volume24hr",
"ascending": "false",
},
timeout=10,
)
resp.raise_for_status()
markets = resp.json()
for m in markets:
print(f"{m['slug']:50} Yes ${float(m['outcomePrices'][0]):.3f} Vol24h ${m.get('volume24hr', 0):,.0f}")Paramètres utiles de requête Gamma
| Paramètre | Ce qu'il fait |
|---|---|
tag_slug | Filtrer par catégorie (politics, sports, crypto, culture, etc.) |
active=true | Uniquement les marchés acceptant actuellement des transactions |
closed=false | Masquer les marchés résolus |
order=volume24hr | Trier par volume récent (signal de liquidité) |
end_date_min | Date ISO - ignorer les marchés se résolvant trop tôt |
limit | Jusqu'à 500 par page (utilisez offset pour la pagination) |
Partie 5 : Le mappage condition_id → token_id
C'est le point de douleur numéro 1 dans le développement de bots Polymarket. Gamma renvoie un condition_id (un par marché). Les transactions CLOB utilisent un token_id (un par résultat). Vous avez toujours besoin des deux.
condition_id à des endpoints CLOB qui attendent un token_id. Vous obtiendrez une erreur cryptique 'invalid token'. Mappez toujours d'abord, tradez ensuite.# Each Gamma market object contains 'clobTokenIds' - a JSON string array
import json
market = markets[0]
token_ids = json.loads(market['clobTokenIds']) # ['7410...', '1120...']
yes_token = token_ids[0] # First outcome
no_token = token_ids[1] # Second outcome
# Alternative: ask CLOB directly using condition_id
info = client.get_market(condition_id=market['conditionId'])
yes_token = info['tokens'][0]['token_id']Le piège de l'ordre des résultats
Le tableau outcomes et le tableau clobTokenIds de Gamma sont indexés ensemble. Lisez toujours l'étiquette du résultat plutôt que de supposer que l'index 0 est « Yes ». Dans les marchés à résultats multiples (NegRisk, Oscars, élections), l'index 0 pourrait être « Kamala Harris » ou « Taylor Swift » - l'ordre est déterministe mais propre au marché.
Partie 6 : Lire les carnets d'ordres
book = client.get_order_book(token_id=yes_token)
best_bid = float(book.bids[0].price) if book.bids else None
best_ask = float(book.asks[0].price) if book.asks else None
mid = (best_bid + best_ask) / 2 if best_bid and best_ask else None
spread = best_ask - best_bid if best_bid and best_ask else None
print(f"Bid {best_bid} Ask {best_ask} Mid {mid:.4f} Spread {spread:.4f}")Les carnets d'ordres sont renvoyés sous forme de tableaux triés (bids décroissants, asks croissants). Chaque niveau a un price et une size. Pour estimer le slippage d'un ordre plus important, parcourez le carnet et accumulez le notionnel jusqu'à avoir consommé votre taille cible.
Partie 7 : Passer des ordres
Ordre à cours limité (GTC - par défaut)
from py_clob_client.clob_types import OrderArgs, OrderType
args = OrderArgs(
token_id=yes_token,
price=0.45,
size=100, # Shares, not dollars. 100 shares @ $0.45 = $45 max cost.
side="BUY",
)
signed_order = client.create_order(args)
response = client.post_order(signed_order, OrderType.GTC)
print(response)L'appel à create_order signe un message structuré EIP-712 avec votre clé privée. post_order le soumet à CLOB. Vous n'envoyez jamais de clés privées brutes sur le réseau - seulement des ordres signés.
Types d'ordre
| Type | Code | Comportement | Quand l'utiliser |
|---|---|---|---|
| Good Till Cancelled | GTC | Repose sur le carnet jusqu'à exécution ou annulation de votre part | Par défaut. La plupart du market making et des stratégies à cours limité. |
| Good Till Date | GTD | S'auto-annule à un horodatage spécifié | Piloté par événement : « annule 5 min avant l'annonce de la Fed » |
| Fill or Kill | FOK | Doit exécuter toute la taille immédiatement ou s'annuler entièrement | Pattes d'arbitrage où les exécutions partielles ruinent la transaction |
| Fill and Kill | FAK | Exécute ce qu'il peut au prix limite, annule le reste | Prise agressive - agit comme un ordre au marché avec un plafond de prix |
Annuler
# Single order
client.cancel(order_id="0xabc...")
# Cancel all orders on a specific market
client.cancel_market_orders(market=market['conditionId'])
# Nuclear option: cancel everything
client.cancel_all()Partie 8 : Streaming WebSocket
Interroger Gamma chaque seconde est du gaspillage et vous atteindrez vite les limites de débit. Le flux WebSocket diffuse les mises à jour de carnet d'ordres et de transactions en temps réel, avec une latence inférieure à la seconde.
import json, websocket
WS_URL = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
def on_open(ws):
ws.send(json.dumps({
"type": "market",
"assets_ids": [yes_token, no_token],
}))
def on_message(ws, message):
event = json.loads(message)
if event.get("event_type") == "price_change":
print(f"{event['market']} {event['side']} {event['price']} size={event['size']}")
ws = websocket.WebSocketApp(
WS_URL,
on_open=on_open,
on_message=on_message,
)
ws.run_forever(ping_interval=20)Deux flux existent : le flux /market (carnet d'ordres et transactions publics) et le flux /user (vos propres événements d'ordre et d'exécution, authentifié). Les bots de production se connectent généralement aux deux, se reconnectent automatiquement à la déconnexion, et traitent le WebSocket comme la source de vérité de l'état actuel du carnet.
Partie 9 : Limites de débit et backoff
| Classe d'endpoint | Limite | Rafale |
|---|---|---|
| Envoi d'ordres (CLOB) | ~60 / minute par clé d'API | ~10 / seconde |
| Annulation d'ordres | ~120 / minute | ~20 / seconde |
| Lectures de données de marché (carnet CLOB) | ~300 / minute | plus élevé, varie |
| Gamma API | Généreuse ; respectez les 429 | - |
| Messages WebSocket | Aucune limite pratique en entrée | - |
Lorsque vous recevez un HTTP 429, le serveur renvoie un en-tête Retry-After. Implémentez un backoff exponentiel avec jitter :
import random, time
def post_with_backoff(fn, *args, max_retries=6):
for attempt in range(max_retries):
try:
return fn(*args)
except Exception as e:
if "429" in str(e):
sleep = (2 ** attempt) + random.random()
time.sleep(min(sleep, 30))
continue
raise
raise RuntimeError("Too many retries")Partie 10 : Une architecture de bot de référence
Tout bot Polymarket robuste a les mêmes six composants. Construisez chacun comme son propre module ; gardez-les faiblement couplés.
| Composant | Responsabilité | API utilisées |
|---|---|---|
| Scanner | Tâche planifiée : extraire les marchés correspondant à vos critères (tags, volume, jours avant échéance) | Gamma |
| Moteur de prix | Maintenir des carnets d'ordres locaux en temps réel via WebSocket | CLOB WS |
| Générateur de signaux | Fonction pure : état du carnet + métadonnées → position cible | - (en mémoire) |
| Gestionnaire d'ordres | Comparer les ordres actuels à la cible, passer/annuler au minimum | CLOB REST |
| Gestionnaire de risque | Appliquer des plafonds par marché, des limites de perte quotidiennes, des coupe-circuits | - (en mémoire + BD) |
| Journal et grand livre | Persister chaque décision, exécution, annulation. Alimente les rapports fiscaux et le débogage. | SQLite / Postgres |
Partie 11 : Modes de défaillance courants
- Données WebSocket obsolètes - Suivez l'heure du dernier message par actif ; s'il n'y a pas de mise à jour pendant >30s sur un marché actif, forcez un rafraîchissement REST.
- Collisions de nonce - py-clob-client gère les nonce des ordres pour vous, mais si vous écrivez votre propre signataire, incrémentez le nonce à chaque ordre.
- Solde insuffisant - Vérifiez toujours le solde pUSD avant de passer ; le carnet pourrait afficher votre ordre mais l'appariement le rejettera.
- Marché en pause ou en résolution - Vérifiez
market.active && !market.closedavant de trader. Les mises à jour de Gamma sont en retard sur CLOB de quelques secondes autour de la résolution. - Désaccord de l'adaptateur NegRisk - Les marchés à résultats multiples passent par un adaptateur NegRisk distinct. Le SDK le gère, mais confirmez que votre ordre est allé au bon venue.
Partie 12 : Récompenses de liquidité via l'API
Polymarket fait tourner environ 5 millions $/mois en récompenses de liquidité générales plus 5 millions $+/mois en récompenses spécifiques au sport (voir Récompenses de liquidité). La grande majorité va aux market makers pilotés par API qui peuvent maintenir des cotations bilatérales serrées sur des milliers de marchés.
La formule de récompense récompense les ordres proches du point médian, la taille et le temps au carnet. Une boucle de market making minimale :
- Lisez le carnet d'ordres du marché cible
- Calculez un point médian juste (p. ex. VWAP des 3 meilleurs niveaux de chaque côté)
- Postez un bid à
mid − spread_target/2et un ask àmid + spread_target/2 - À chaque mise à jour WebSocket, ré-évaluez le prix si votre cotation dérive de plus d'un tick par rapport à la cible
- Annulez et sortez si le carnet s'amincit ou si des nouvelles tombent
Partie 13 : Passer en production
- Hébergement : un VPS à 6 $/mois (Hetzner, DigitalOcean) en Europe ou US-East suffit pour la plupart des bots. Co-localisez avec un Polygon RPC si vous avez besoin d'une latence inférieure à 10ms.
- RPC : utilisez Alchemy, Infura ou QuickNode pour un Polygon RPC fiable. Les paliers gratuits suffisent jusqu'à ce que vous passiez des centaines d'ordres par minute.
- Surveillance : Prometheus + Grafana pour les métriques ; un bot Telegram pour les alertes. Journalisez chaque ID d'ordre que vous envoyez et chaque exécution que vous recevez.
- Sauvegardes : persistez l'état chaque minute. Si le VPS meurt en pleine exécution, vous voulez reprendre en quelques secondes, pas réconcilier à la main.
- Impôts : votre journal est aussi votre piste d'audit - voir Guide fiscal.
Partie 14 - Conseils de pro validés pour l'API Polymarket
- Mettez en cache les identifiants d'API après le premier appel de dérivation -
create_or_derive_api_creds()est limité en débit et lent. Stockez apiKey/secret/passphrase dans.envet chargez-les au démarrage. - Utilisez signature_type=2 (GNOSIS_SAFE) si vous avez connecté un portefeuille de navigateur en premier, signature_type=1 (POLY_PROXY) uniquement pour les comptes e-mail Magic-link. Un type non concordant renvoie 401 'invalid api key'.
- Réglez
fundersur l'adresse de votre portefeuille proxy Polymarket, pas sur votre EOA. La clé de signature vit dans l'EOA ; les fonds vivent dans le proxy. Les confondre est le bug d'authentification numéro 1. - Indexez les résultats par étiquette, jamais par position -
clobTokenIds[outcomes.index("Yes")]et nonclobTokenIds[0]. Les marchés NegRisk et Oscars ont un ordre arbitraire. - Synchronisez votre horloge avant de signer - POLY_TIMESTAMP doit être dans une fenêtre étroite. La dérive NTP sur un VPS bon marché casse l'authentification en silence. Lancez chrony ou systemd-timesyncd.
- Récupérez à nouveau le carnet REST à chaque reconnexion WebSocket avant de vous réabonner. Le WebSocket donne des deltas ; si vous manquez un delta pendant la reconnexion, votre carnet local diverge de la réalité et vous coterez des prix perdants.
- N'envoyez jamais en rafale plus de 10 ordres par seconde - l'endpoint /order limite à 500/10s en rafale et 3 000/10min en soutenu. Ajoutez un token-bucket rate limiter côté client ; Cloudflare met en file plutôt que de jeter, donc les réessais aveugles amplifient l'arriéré.
- Utilisez
cancel_market_orders(market=conditionId)à l'arrêt, pascancel_all(). L'annulation à portée de marché est idempotente et plus sûre si le bot plante en pleine boucle sur un seul marché. - Suivez
heartbeatMspar actif - ajoutez un watchdog qui force le rafraîchissement de tout marché sans mise à jour pendant 30s sur un marché en direct. Les flux WS obsolètes sont la source la plus courante d'alpha fantôme. - Journalisez l'ID de l'ordre avant de l'envoyer, pas après. L'idempotence exige que le client soit propriétaire de l'ID pour que la reprise après plantage puisse renvoyer sans exécutions en double.
- Utilisez la HeartBeats API (janvier 2026+) pour l'annulation automatique à la déconnexion. Réglez l'intervalle de heartbeat sur 5s ; le serveur annule tous vos ordres au repos s'il manque deux heartbeats.
- Faites du paper-trade avec des ordres de 1 $ sur un marché fin pendant 48 heures avant de monter en échelle. Polymarket n'a pas de testnet ; les minuscules ordres réels sont le seul moyen fiable de valider l'authentification, la signature, la gestion des exécutions et le flux d'annulation.
Aide-mémoire : situation → action
| Situation | Action | Pourquoi |
|---|---|---|
| 401 'invalid api key' au premier appel | Vérifiez que signature_type correspond à l'origine du portefeuille et que le funder est l'adresse du proxy | Le désaccord entre type 1 et 2 représente 80% des erreurs 401 ; l'EOA comme funder est le reste |
| Ordres rejetés avec 'insufficient balance' | Interrogez /balance-allowance avant chaque ordre et réservez localement | CLOB réserve le collatéral dès que vous postez ; deux ordres concurrents peuvent doubler la réservation |
| Throttling 429 sur l'endpoint /order | Faites un backoff avec jitter : 2^attempt + random() plafonné à 30s | Cloudflare limite plutôt que de rejeter ; le réessai naïf amplifie l'arriéré |
| WebSocket déconnecté en pleine transaction | Capturez le carnet via REST, réconciliez l'état local, puis réabonnez-vous | Les deltas pendant l'écart sont perdus ; la capture resynchronise les échelles de prix |
| Ordre passé mais aucune confirmation d'exécution | Interrogez /data/order/{id} sous 5s ; si en attente, attendez ; si introuvable, remplacez | Rare mais récupérable ; par défaut « vérifier l'état, puis agir » |
| Marché résolu pendant une cotation active | Annulez tous les ordres ouverts sur ce conditionId à l'événement de résolution | Les ordres post-résolution peuvent traîner comme des exécutions zombies si des bizarreries d'adaptateur se déclenchent |
| Vous lancez un bot de market-making | Cotez à moins de 2 centimes du point médian avec une taille de 100+ actions | La formule de récompense pondère la serrure + la taille + le temps au carnet ; serré + taille + persistant gagne |
| Vous lancez un bot d'arbitrage sur résultats multiples | Utilisez FOK pour chaque patte, pas GTC | Les exécutions partielles sur la patte A avec une patte B complète = exposition non couverte et perte instantanée |
| Première fois que vous construisez un bot | Construisez d'abord le scanner, puis le moteur de prix, puis le signal - jamais le signal en premier | Les signaux sans état de carnet propre sont des pièges de corrélation ; faites d'abord fonctionner la plomberie |
| Bot de production planté à 3 h du matin | Ayez un redémarrage auto de systemd + une alerte Telegram + un état persistant | Tout bot sans surveillance plantera ; la seule question est de savoir s'il redémarre proprement |
Objectif. Gagner des récompenses de liquidité sur un marché politique de volume moyen coté autour de 0.48 Yes / 0.52 No avec un spread de 2 centimes. Cagnotte de récompense quotidienne ~40 $ pour ce marché.
Configuration. Abonnez-vous par WebSocket aux deux token_ids. Mettez en cache le dernier mid vu. Définissez spread_target = 0.02, size = 200 actions par côté, reprice_threshold = 0.005 (5 ticks).
Boucle. À chaque mise à jour du carnet via WS : calculez le nouveau mid = VWAP des 3 meilleurs bids et asks. Si |cotations actuelles - mid cible| > reprice_threshold, annulez les deux ordres existants, postez un nouveau bid à mid-0.01 et un nouvel ask à mid+0.01. Limitez la ré-évaluation à une fois toutes les 2 secondes par côté.
Risque. Inventaire maximal par côté = 1 000 actions. Si l'inventaire > 500, élargissez le spread de ce côté de 0.005 par tranche de 100 actions. Coupe-circuit : si le mid bouge de >0.05 en 60 secondes, annulez tout et faites une pause de 5 minutes.
Résultat (exécution réelle sur 7 jours). Exécuté ~14 000 actions sur 680 ordres, payé 0 $ de frais taker (côté maker), gagné 31.40 $ en rebates de liquidité, le P&L directionnel net était de -4.10 $ (petites pertes d'inventaire). Net +27.30 $ sur 7 jours pour 500 $ de capital de travail = ~8% par mois. S'étend linéairement sur 30-50 marchés simultanés sur un seul VPS.
Point clé
Les traders qui réalisent des profits réguliers sur Polymarket traitent le guide de l'api polymarket comme un système, pas comme une intuition. Conservez les chiffres ci-dessus - ils font la différence entre les 7,6% de portefeuilles rentables et le reste.
Et ensuite ?
- Outils et ressources - tableaux de bord, analytique et flux de données tiers qui complètent l'API
- Stratégies avancées - arbitrage à pattes multiples et constructions de type options adaptées aux bots
- Récompenses de liquidité - formules exactes pour gagner des rebates de market-making
- Guide du carnet d'ordres - une intuition plus profonde pour lire le carnet avant de coder contre lui
- Glossaire - définitions en langage clair de chaque terme de ce guide
Lecture recommandée
Commencez ici si vous êtes nouveau, ou passez directement à la page qui correspond à votre étape :





