Errori dell’API di Polymarket: ogni codice, decodificato
I messaggi di errore di Polymarket sono laconici, e quelli che rompono il tuo bot alle 3 di notte di solito mancano del tutto dalla documentazione. Ecco il riferimento completo: errori documentati, quelli non documentati e cosa fare davvero per ciascuno.
Ogni errore dell’API CLOB di Polymarket torna con la stessa forma, un oggetto JSON con un unico campo error: un modello ammirevole di coerenza e del tutto inutile quando stai cercando di capire perché il tuo ordine è appena sparito.
{
"error": "<message>"
}Questa pagina li decodifica. Copre gli errori documentati del CLOB, i codici di stato con le loro cause reali e (la parte che non troverai nella documentazione ufficiale) gli errori che si incontrano davvero in produzione e che Polymarket non ha mai messo per iscritto.
Ogni messaggio documentato ha anche una pagina dedicata con le cause e un verdetto sul retry, elencata nell’indice degli errori di Polymarket.
Riferimento rapido dei codici di stato
| Stato | Significato | Cause comuni |
|---|---|---|
400 | Bad Request | Parametri non validi, payload malformato, violazione della logica di business |
401 | Unauthorized | Chiave API mancante o non valida, firma HMAC errata, timestamp scaduto |
404 | Not Found | Il mercato non esiste, ordine non trovato, token ID non riconosciuto |
425 | Too Early | Il motore di matching si sta riavviando: riprova con backoff |
429 | Too Many Requests | Rate limit superato: rallenta con un backoff esponenziale |
500 | Internal Server Error | Errore imprevisto del server: riprova con backoff |
503 | Service Unavailable | Exchange in pausa, o bloccato dalla modalità cancel-only / post-only |
La sovrascrittura del codice di stato che ti ingannerà
L’API CLOB riscrive i codici di stato in base al contenuto del messaggio. Ogni messaggio di errore che contiene "not found" restituisce 404, ogni messaggio che contiene "unauthorized" restituisce 401 e ogni messaggio che contiene "context canceled" restituisce 400, indipendentemente dal codice di stato originale. Se un codice di stato sembra contraddire il messaggio, il motivo è questo. Basa la gestione degli errori sul testo del messaggio, non sul numero.
401: errori di autenticazione
Unauthorized/Invalid api key
L’errore di Polymarket più cercato in assoluto. La tua chiave API manca, è scaduta o non è valida. In pratica non si tratta quasi mai di una chiave davvero sbagliata, ma di uno di questi casi:
- Stai inviando solo una parte del set di credenziali. L’autenticazione L2 di Polymarket richiede insieme la chiave, il secret e la passphrase. Un errore comune è valorizzare
POLY_API_KEYePOLY_PASSPHRASElasciando vuoto il secret: il client invia una richiesta ben formata ma impossibile da firmare. - L’orologio di sistema è andato alla deriva. La firma include un timestamp, e un orologio sballato di più di qualche secondo produce una firma che il server rifiuta come non valida. È la causa che si scopre per ultima ed è deprimente quanto sia comune su VM e container.
- Hai derivato la chiave con un wallet diverso da quello con cui fai trading. Le chiavi sono legate all’indirizzo del signer che le ha create.
- Stai chiamando un endpoint autenticato con header L1 dove è previsto L2, o viceversa.
Invalid L1 Request headers
I tuoi header di autenticazione L1 (il set di firme EIP-712) sono malformati, oppure la firma non corrisponde all’indirizzo che dichiari. Controlla di firmare con la stessa chiave privata dell’indirizzo nell’header, e che il domain separator corrisponda alla chain su cui ti trovi (Polygon, chain ID 137). Una firma valida per il chain ID sbagliato è comunque una firma valida, solo non per questo server.
Could not create api key / Could not derive api key!
Sono gli errori dietro la ricerca "polymarket unable to generate api credentials". Entrambi vengono restituiti dagli endpoint di autenticazione quando la creazione o la derivazione della chiave fallisce. Could not derive api key! su GET /auth/derive-api-key di solito significa che per quel signer non esiste ancora una chiave: derive restituisce una chiave esistente, non ne crea una. Crea prima la chiave con POST /auth/api-key, poi derivala nelle esecuzioni successive.
Lo schema derive-poi-create
Invece di salvare le chiavi, la maggior parte dei bot in produzione prova prima derive e ripiega su create se fallisce. È idempotente tra un riavvio e l’altro ed evita di accumulare chiavi orfane; gli endpoint di autenticazione sono limitati a 100 req / 10s, quindi comunque non vuoi creare una chiave a ogni avvio.
400: errori di rifiuto degli ordini
Vengono restituiti quando un ordine supera la validazione di trasporto ma viola le regole di business. Compaiono nel body della risposta di POST /order e POST /orders.
| Messaggio di errore | Cosa significa |
|---|---|
the order signer address has to be the address of the API KEY | La chiave che firma l’ordine non è la chiave che, secondo l’ordine, lo ha firmato. Stai mescolando credenziali, di solito una chiave vecchia di un wallet precedente. |
the order owner has to be the owner of the API KEY | L’indirizzo maker nell’ordine non corrisponde all’indirizzo a cui appartiene la chiave API. |
order {id} is invalid. Price ({price}) breaks minimum tick size rule: {tick} | Il tuo prezzo non è sulla griglia dei tick del mercato. Chiama GET /tick-size e arrotonda di conseguenza: non dare per scontato 0.01. |
order {id} is invalid. Size ({size}) lower than the minimum: {min} | Size dell’ordine inferiore al minimo del mercato. |
not enough balance / allowance | Saldo pUSD insufficiente, oppure non hai mai concesso un’allowance al contratto dell’exchange. Servono entrambi. |
invalid post-only order: order crosses book | Il tuo ordine post-only prenderebbe subito liquidità. Cambia prezzo in modo che resti in attesa nel book. |
order couldn't be fully filled. FOK orders are fully filled or killed. | Il Fill-or-Kill ha trovato liquidità insufficiente. L’intero ordine viene rifiutato. |
no orders found to match with FAK order. | Il Fill-and-Kill non ha trovato alcuna corrispondenza. Ne serve almeno una. |
invalid expiration | Il timestamp di scadenza è nel passato o malformato. |
order {id} is invalid. Duplicated. | Lo stesso ordine è stato inviato due volte. |
order canceled in the CTF exchange contract | L’ordine è stato cancellato on-chain. |
'{address}' address banned | All’indirizzo è vietato fare trading. |
'{address}' address in closed only mode | L’indirizzo può solo chiudere posizioni esistenti. |
La dimensione del tick è per mercato e cambia
Il rifiuto silenzioso di ordini più comune è una violazione della dimensione del tick. La dimensione del tick varia tra i mercati e può restringersi man mano che un mercato matura: un prezzo valido la settimana scorsa potrebbe non esserlo oggi. Ottieni GET /tick-size per ogni mercato e arrotonda di conseguenza invece di fissare una griglia nel codice.
Gli ordini batch falliscono in modo diverso
In POST /orders, gli errori dei singoli ordini tornano dentro l’array della risposta 200, con campi errorMsg individuali, e non come errore di primo livello. Un 200 non significa che ogni ordine del batch sia stato accettato. Itera l’array e controlla ogni voce.
425: Too Early
Un codice di stato insolito che confonde perché è usato raramente nel resto del web. Su Polymarket significa che il motore di matching si sta riavviando. La tua richiesta è arrivata durante la finestra in cui l’exchange sta tornando operativo.
Questo è davvero transitorio e davvero sicuro da ritentare: è probabilmente l’errore più adatto al retry dell’intera piattaforma. Rallenta e riprova; non trattarlo come un fallimento e non generare alert per un singolo caso.
503: l’exchange è in una modalità limitata
Polymarket può mettere l’exchange in modalità limitate. Non sono errori tuoi, e ritentare la stessa richiesta non servirà a nulla finché la modalità non viene rimossa.
| Messaggio | Cosa puoi ancora fare |
|---|---|
Trading is currently disabled. Check polymarket.com for updates | Niente. Nessun ordine accettato, cancellazioni comprese. |
Trading is currently cancel-only. New orders are not accepted, but cancels are allowed. | Cancellare gli ordini esistenti. Non puoi aprirne di nuovi. |
post-only mode: only post-only orders and cancels are allowed | Cancellare, o piazzare ordini con postOnly: true. Gli ordini taker vengono rifiutati. |
La modalità post-only è quella da gestire bene, perché ti dice esattamente quando tornare. La risposta include code: "post_only_mode" e retry_after_seconds, e lo stesso ritardo viene inviato nell’header Retry-After.
{
"error": "post-only mode: only post-only orders and cancels are allowed",
"code": "post_only_mode",
"retry_after_seconds": 79
}La modalità cancel-only può intrappolare un bot di market making
Se la procedura di arresto del tuo bot ri-quota prima di cancellare, la modalità cancel-only rifiuterà la nuova quotazione e il bot potrebbe finire in un loop invece di chiudere le posizioni. Gestisci il 503 cancellando prima e solo dopo decidendo se rientrare.
Errori che non sono nella documentazione
È qui che va la maggior parte del vero tempo di debugging. I seguenti non compaiono nel riferimento ai codici di errore di Polymarket perché non nascono affatto dall’applicazione CLOB: vengono dall’edge, dalla rete o dalla tua libreria client. Sapere quale livello ha prodotto un errore ti dice dove guardare.
"The server was unable to process your request"
L’errore di Polymarket più cercato che non è nella documentazione. È un messaggio del livello edge e non un errore dell’API CLOB: è quello che ottieni quando la richiesta non ha mai raggiunto l’applicazione, o non ne è mai tornata in modo pulito. In pratica le cause abituali sono:
- Una richiesta malformata che l’edge rifiuta prima dell’instradamento: un payload troppo grande, un header errato o un metodo HTTP non valido per la rotta.
- Un guasto upstream transitorio mentre il servizio viene rideployato o è sotto carico.
- Un rate limiting prolungato. Poiché Cloudflare rallenta mettendo in coda invece di rifiutare, un client molto oltre il limite può ritrovarsi con richieste che vanno in timeout sull’edge invece di ricevere un
429pulito.
Trattalo come ritentabile con backoff, ma se è persistente e non occasionale controlla prima la tua frequenza di richieste (vedi il riferimento ai rate limit) e poi la dimensione del payload.
403 Forbidden
Un 403 da Polymarket di solito non è un problema di autenticazione, ed è questo che lo rende confuso. In genere è l’edge che blocca la richiesta. I fattori scatenanti comuni sono le restrizioni geografiche sugli endpoint di trading, i range di IP di datacenter e VPN sottoposti a challenge e gli header mancanti o non simili a quelli di un browser su richieste che l’edge si aspetta da un client.
Se un 403 compare solo dalla tua VM cloud ma non dal tuo portatile, è un problema di reputazione dell’IP, non del codice. Se compare sugli endpoint di trading ma non su quelli dei dati di mercato, è geografico.
Errori SSL, TLS e di certificato
"polymarket ssl error", "polymarket certificate error" e "polymarket https error" sono quasi sempre lato client. I certificati di Polymarket sono a posto; è qualcosa tra te e loro a non esserlo. Controlla, in ordine: un bundle di CA obsoleto (molto comune nelle vecchie immagini Docker e negli ambienti Python congelati), un proxy aziendale che ispeziona il TLS sostituendo il proprio certificato e un orologio di sistema così sballato che i certificati sembrano non ancora validi o scaduti.
# 1. Does TLS work at all, outside your app's HTTP client?
curl -sS -o /dev/null -w "%{http_code} %{ssl_verify_result}\n" \
https://clob.polymarket.com/ok
# 2. Is your CA bundle current? (Python)
python3 -c "import certifi, os; print(certifi.where()); print(os.path.getmtime(certifi.where()))"
# 3. Is your clock right? Certificate validation depends on it.
date -u"Service not ready"
Un messaggio di fase di avvio: il servizio è abbastanza attivo da rispondere ma non pronto a servire. In pratica trattalo come un 425: rallenta e riprova. Dovrebbe risolversi in pochi secondi, e non è qualcosa che puoi sistemare lato client.
"Order manager not ready"
Un messaggio di fase di avvio del motore di matching, parente stretto di 425 Too Early. Il servizio è raggiungibile ma il livello di gestione degli ordini non ha finito di avviarsi, quindi accetta la tua connessione e rifiuta il tuo ordine. È transitorio e sicuro da ritentare con backoff, ma consideralo un segnale per smettere di inviare per qualche secondo invece di insistere, perché un riavvio di solito significa che il book sta per cambiarti sotto i piedi.
Se lo vedi in modo persistente e non a raffiche, controlla lo stato di Polymarket prima di fare debug del tuo codice: lato client non c’è nulla da sistemare.
"Couldn’t get a quote"
Di solito significa che non c’è liquidità in attesa sul lato che hai chiesto di prezzare, non che qualcosa sia rotto. Sui mercati Up/Down sottili vicino alla scadenza un lato si svuota regolarmente (nessuno vende Up a nessun prezzo una volta che Up è certo), quindi una richiesta di quotazione non restituisce nulla. I nostri dati mostrano che è comune: in un campione di mercati BTC a 5 minuti, 1,454 su 8,510 avevano il book degli ask vuoto su un lato 60 secondi prima della scadenza.
Gestiscilo come "nessun mercato" e non come un errore: salta l’operazione, non ritentare in un loop stretto. Se ti serve sapere quanto spesso succede per una serie su cui operi, le pagine dei dati di mercato mostrano la liquidità per timeframe.
Eccezioni della libreria client
Errori come PolyApiException[status_code=None, error_message=request exception!] vengono dal client Python, non dal server. status_code=None è l’indizio: non è mai stata ricevuta alcuna risposta HTTP, quindi è un errore a livello di connessione (DNS, TLS, timeout o un socket caduto) che emerge come eccezione della libreria. Fai debug come per un problema di rete, non dell’API. Lo stesso ragionamento vale per BuilderApiKeyCreds invalid authorization 401 nel client del relayer, che significa che le credenziali builder passate al client non sono state accettate; derivale di nuovo invece di riusare un set in cache.
Una politica di retry che gestisce tutto questo
La conclusione pratica è che gli errori di Polymarket rientrano in tre categorie, e confonderle è ciò che rende fragili i bot: riprova alla cieca, riprova dopo un ritardo specifico e non riprovare mai.
| Categoria | Codici / messaggi | Azione |
|---|---|---|
| Transitorio | 425, 500, Service not ready, errori di connessione | Riprova con backoff esponenziale + jitter |
| Rate limit | 429 | Riprova dopo Retry-After; se assente, backoff con jitter |
| Modalità limitata | 503 post-only | Aspetta retry_after_seconds, poi riprova |
| Modalità limitata | 503 cancel-only / disabilitato | Smetti di aprire posizioni; cancella se consentito; interroga lentamente |
| Definitivo | 400 di validazione, 401, 404 | Non riprovare: correggi la richiesta o le credenziali |
type Decision =
| { retry: true; delayMs: number }
| { retry: false; reason: string };
function classify(status: number, body: { error?: string; code?: string; retry_after_seconds?: number }, attempt: number): Decision {
const msg = (body.error ?? "").toLowerCase();
const backoff = Math.min(2 ** attempt * 250, 8000);
const jittered = Math.random() * backoff;
// Never retry — the request itself is wrong.
if (status === 401) return { retry: false, reason: "auth: check key, secret, passphrase and clock drift" };
if (status === 404) return { retry: false, reason: "not found" };
if (status === 400) return { retry: false, reason: `validation: ${body.error}` };
// Mode-restricted — the server tells you when to come back.
if (status === 503 && body.code === "post_only_mode") {
return { retry: true, delayMs: (body.retry_after_seconds ?? 60) * 1000 };
}
if (status === 503) return { retry: false, reason: "exchange paused or cancel-only" };
// Transient — safe to retry.
if (status === 425 || status === 429 || status >= 500) return { retry: true, delayMs: jittered };
if (msg.includes("service not ready")) return { retry: true, delayMs: jittered };
return { retry: false, reason: `unhandled status ${status}` };
}Registra il messaggio, genera alert sulla categoria
Gli alert sulle stringhe di errore grezze producono rumore, perché i messaggi di Polymarket contengono ID degli ordini e prezzi. Genera alert sulla categoria: un picco di 400 definitivi significa che hai rilasciato un bug; un picco di 429 significa che devi rallentare; un picco di 425 significa che Polymarket si sta riavviando e non devi fare proprio nulla.
Errori da cui non puoi uscire con il debugging
Alcune cose che sembrano errori semplicemente non sono supportate. Polymarket non ha un endpoint per l’order book storico, quindi non c’è nulla da chiamare nel modo sbagliato. Il book di un mercato risolto restituisce 404 perché Polymarket smette di fornirlo quando il mercato si regola, anche se il tuo token ID è corretto.
Se sbatti contro questi muri, non stai facendo debug di un’integrazione: ti manca una fonte di dati. PolyTest registra snapshot point-in-time dei mercati crypto Up/Down di Polymarket mentre sono attivi, con la profondità completa dell’order book, quindi lo storico c’è anche dopo la risoluzione. Il nostro riferimento agli errori copre le forme degli errori dell’API di PolyTest, volutamente noiose al confronto.
Domande frequenti
- Cosa significa "Unauthorized/Invalid api key" su Polymarket?
- Significa che la tua chiave API manca, è scaduta o non è valida, ma in pratica la causa è di solito una di quattro: stai inviando un set di credenziali incompleto (servono chiave, secret e passphrase), l’orologio di sistema è andato alla deriva abbastanza da invalidare la firma della richiesta, hai derivato la chiave con un wallet diverso da quello con cui fai trading, oppure stai inviando header L1 dove sono previsti header L2.
- Cos’è l’errore 425 di Polymarket?
- HTTP 425 Too Early significa che il motore di matching di Polymarket si sta riavviando e la tua richiesta è arrivata in quella finestra. È transitorio e sicuro da ritentare con un backoff esponenziale. Un singolo 425 non merita un alert.
- Perché Polymarket dice "The server was unable to process your request"?
- È un messaggio del livello edge e non un errore documentato dell’API CLOB, e significa che la richiesta non ha mai raggiunto l’applicazione o non ne è tornata in modo pulito. Le cause abituali sono una richiesta malformata rifiutata prima dell’instradamento, un guasto upstream transitorio o un rate limiting prolungato: poiché Polymarket rallenta mettendo in coda invece di rifiutare, un client molto oltre il limite può vedere timeout sull’edge invece di 429 puliti.
- Perché ricevo un 403 dall’API di Polymarket?
- Un 403 da Polymarket di solito è l’edge che blocca la richiesta, non un errore di autenticazione. I fattori scatenanti comuni sono le restrizioni geografiche sugli endpoint di trading, i range di IP di datacenter o VPN sottoposti a challenge e la mancanza di header simili a quelli di un browser. Se succede da una VM cloud ma non dal tuo portatile, è la reputazione dell’IP; se succede sugli endpoint di trading ma non su quelli dei dati di mercato, è geografico.
- Come risolvo "the order signer address has to be the address of the API KEY"?
- La chiave che firma il tuo ordine non corrisponde a quella che l’ordine dichiara di aver usato. Significa che stai mescolando credenziali, in genere una chiave API vecchia in cache da un wallet precedente. Deriva di nuovo le credenziali API per il wallet con cui fai davvero trading e assicurati che l’indirizzo maker nell’ordine corrisponda all’indirizzo proprietario della chiave.
- Cosa significa "order manager not ready" su Polymarket?
- È un messaggio di fase di avvio del motore di matching: il servizio è raggiungibile ma il livello di gestione degli ordini non ha finito di avviarsi, quindi accetta la connessione e rifiuta l’ordine. È transitorio e strettamente legato all’HTTP 425 Too Early. Riprova con backoff, ma sospendi gli invii per qualche secondo invece di insistere, perché un riavvio di solito significa che il book sta per muoversi. Se si ripete in modo persistente è un problema lato Polymarket, non un bug del client.
- Perché Polymarket dice che non è riuscito a ottenere una quotazione?
- Quasi sempre perché non c’è liquidità in attesa sul lato che hai chiesto di prezzare, non perché qualcosa sia rotto. Sui mercati Up/Down sottili vicino alla scadenza un lato si svuota regolarmente: nessuno offre Up quando Up è certo. In un campione di mercati BTC a 5 minuti, 1,454 su 8,510 avevano il book degli ask vuoto su un lato 60 secondi prima della scadenza. Trattalo come "nessun mercato" e salta l’operazione invece di ritentare in un loop.
- Dovrei ritentare automaticamente gli errori dell’API di Polymarket?
- Solo alcuni. Ritenta 425, 429, la serie 500 e gli errori di connessione con backoff esponenziale più jitter. Ritenta la modalità post-only 503 dopo il valore retry_after_seconds fornito dalla risposta. Non ritentare mai gli errori di validazione 400, gli errori di autenticazione 401 o i 404: richiedono una richiesta o credenziali corrette, e ritentare consuma solo budget di rate limit.
Ottieni i dati storici che Polymarket non conserva
PolyTest registra i mercati crypto Up/Down di Polymarket mentre sono attivi: 240M+ snapshot con 8 livelli di profondità dell’order book, timestamp sotto il secondo e mercati risolti conservati. Inizia con una prova gratuita di 3 giorni.
Continua a leggere
Rate limit dell’API di Polymarket: il riferimento completo
Polymarket pubblica i suoi rate limit su diverse pagine, in due sistemi completamente diversi, usando una finestra di 10 secondi che quasi nessuno si aspetta. Qui c’è tutto in un unico set di tabelle, più cosa succede davvero quando superi un limite.
Come costruire un bot di trading per Polymarket
La maggior parte dei tutorial sui bot per Polymarket si basa su SDK che non esistono più. Questo è il percorso attuale dall’inizio alla fine: cosa installare nel 2026, come funziona davvero l’autenticazione, dove sono i buchi nei dati e i problemi che uccidono i bot nella prima settimana.
L’SDK Python di Polymarket nel 2026 (e la migrazione da py-clob-client)
Se il tuo codice importa ancora ClobClient da py_clob_client, è costruito su un pacchetto superato, come la maggior parte del codice Polymarket che un assistente AI scriverà per te. Ecco l’SDK attuale e come fare il passaggio.