Errore 400 “Invalid JSON” del token di accesso Tradovate
Invia credenziali corrette all'endpoint access-token e ottiene comunque un 400 “invalid JSON”. Ecco tutti gli errori di formattazione che lo causano, e la richiesta corretta per curl, Python e JavaScript.
Invia il Suo nome utente e la password all'endpoint access-token, e invece di un token riceve un secco 400 con un messaggio come [Invalid JSON: expected '}' or ',', offset: 0x00000028]. Le credenziali sono corrette. L'account funziona nella piattaforma web. Allora qual è il problema?
Ecco la risposta breve: il server non ha mai letto il Suo accesso. Un 400 “invalid JSON” si verifica nella fase di parsing, prima di qualsiasi verifica delle credenziali. Qualcosa nella forma del Suo corpo della richiesta, le virgolette, l'intestazione, il modo in cui il Suo linguaggio lo ha serializzato, non è JSON valido. Corregga la formattazione e le stesse identiche credenziali passeranno senza problemi.
Questa guida esamina ogni versione di questo errore di formattazione, nell'ordine in cui è più probabile incontrarlo, con la richiesta corretta per curl, Python e JavaScript.
Come si presenta realmente l'errore
La richiesta va all'endpoint di autenticazione. Nell'ambiente demo è:
POST https://demo.tradovateapi.com/v1/auth/accesstokenrequest
In reale è https://live.tradovateapi.com/v1/auth/accesstokenrequest. Stesso corpo, host diverso, confonderli è un problema a sé, ma non produrrà un messaggio “invalid JSON”, quindi lo metta da parte per ora.
Una chiamata riuscita restituisce un oggetto JSON con un accessToken e una expirationTime. Una malformata restituisce HTTP 400 e un corpo che indica il reclamo del parser e un offset in byte. Quell'offset è il Suo indizio migliore, e ci torneremo.
La causa reale: il Suo corpo non è JSON valido
JSON ha regole rigide che molto codice infrange silenziosamente. I modi più comuni in cui un corpo di accesso diventa non valido:
- Apici singoli. JSON richiede virgolette doppie attorno alle chiavi e ai valori stringa. Se stampa un dict Python, un oggetto JavaScript o un hash Ruby direttamente nella richiesta, ottiene apici singoli e non è più JSON.
- Una virgola finale. Una virgola dopo l'ultimo campo è legale nella maggior parte dei linguaggi e illegale in JSON.
- Codifica a modulo. Molte librerie HTTP usano di default
application/x-www-form-urlencoded. Il server, che si aspetta JSON, si blocca già al primo byte. - Doppia codifica. Converte l'oggetto in stringa una volta, poi passa quella stringa a un client che la converte di nuovo. Ora il corpo è una stringa tra virgolette, non un oggetto.
- Caratteri nascosti. Un byte-order mark o una “virgoletta tipografica” incollata da un documento o da una chat appare identica a schermo ma rompe il parser.
Ognuno di questi produce la stessa famiglia di errori 400. Li eliminiamo uno alla volta.
Soluzione 1: invii JSON reale con virgolette doppie
Partiamo dall'obiettivo. Ecco come appare un corpo valido, virgolette doppie ovunque, nessuna virgola finale, cid come numero semplice:
{ "name": "your_username", "password": "your_password", "appId": "My App", "appVersion": "1.0", "cid": 8, "sec": "your-api-secret", "deviceId": "123e4567-e89b-12d3-a456-426614174000" }
Solo name e password sono strettamente obbligatori; il resto identifica la Sua applicazione ed è necessario per l'accesso completo all'API. Confronti questo con la versione errata che di solito viene inviata, cioè un oggetto di linguaggio stampato come testo:
{'name': 'your_username', 'password': 'your_password', 'appId': 'My App', 'cid': '8'}
Due problemi qui: apici singoli ovunque, e cid racchiuso tra virgolette per cui viene letto come stringa. Sostituisca gli apici singoli con virgolette doppie e tolga le virgolette dal valore cid, e il corpo diventa valido.

Soluzione 2: imposti l'intestazione Content-Type
JSON valido nel corpo non basta. Deve anche indicare al server che il corpo è JSON. Aggiunga queste intestazioni alla richiesta:
Content-Type: application/jsonAccept: application/json
Senza Content-Type: application/json, la maggior parte dei client ricade sulla codifica a modulo e il server tenta di analizzare i campi del modulo come un documento JSON. Il parsing fallisce al byte zero e ottiene un 400. Questa sola intestazione risolve da sola una quota sorprendente di segnalazioni “invalid JSON”.
Soluzione 3: in Python usi json= e non data=
La libreria requests inganna spesso gli utenti qui. Se passa il Suo dizionario tramite il parametro data, viene codificato a modulo e le virgolette doppie non appaiono mai. Lo passi invece tramite json, questo serializza il dict in JSON corretto e imposta automaticamente l'intestazione Content-Type.
Sbagliato:
requests.post(url, data=credentials)
Corretto:requests.post(url, json=credentials)
Con json=credentials non tocca mai le virgolette a mano, la libreria lo fa correttamente. Si assicuri solo che credentials sia un dict reale (con cid come int), non un blob già convertito in stringa. Se ha già chiamato json.dumps() su di esso, o elimini quella chiamata e usi json=, oppure mantenga la stringa e la passi tramite data= con l'intestazione Content-Type impostata manualmente. Non faccia entrambe le cose.

Soluzione 4: in JavaScript, serializzi esattamente una volta
Con fetch, l'errore classico è dimenticare JSON.stringify (per cui il corpo diventa l'inutile stringa [object Object]) o chiamarlo due volte. Lo faccia una volta e imposti l'intestazione:
fetch(url, {method: "POST",headers: { "Content-Type": "application/json", "Accept": "application/json" },body: JSON.stringify(credentials)})
Se credentials è già una stringa, non la racchiuda di nuovo in JSON.stringify, il secondo passaggio esegue l'escape di ogni virgoletta e il server riceve un'unica lunga stringa tra virgolette, che non è un oggetto.
Soluzione 5: con curl, esegua l'escape delle virgolette
La shell divora i caratteri delle virgolette, quindi un payload JSON grezzo sulla riga di comando richiede attenzione. Esegua l'escape delle virgolette doppie interne con backslash:
curl -X POST https://demo.tradovateapi.com/v1/auth/accesstokenrequest \-H "Content-Type: application/json" \-H "Accept: application/json" \-d "{ \"name\": \"your_username\", \"password\": \"your_password\", \"appId\": \"My App\", \"appVersion\": \"1.0\", \"cid\": 8, \"deviceId\": \"123e4567-e89b-12d3-a456-426614174000\", \"sec\": \"your-api-secret\" }"
Una via più semplice: metta il JSON in un file e passi -d @body.json, che elimina del tutto il problema delle virgolette della shell. Noti che il semplice -d usa di default la codifica a modulo, quindi l'intestazione Content-Type: application/json deve comunque essere esplicita.
Soluzione 6: controlli i tipi dei Suoi campi
Anche un JSON pulito viene rifiutato se un valore ha il tipo sbagliato. Quello che trae in inganno più spesso è cid: è un intero, quindi invii "cid": 8, mai "cid": "8". Mantenga i campi stringa (name, password, appId, appVersion, sec, deviceId) tra virgolette, e lasci cid come numero semplice. Ecco il riferimento rapido:
| Campo | Tipo | Obbligatorio? | Esempio |
|---|---|---|---|
| name | string | Sì | "trader_jane" |
| password | string | Sì | "S3cureP@ss!" |
| appId | string | Per l'accesso completo | "My App" |
| appVersion | string | Per l'accesso completo | "1.0" |
| cid | integer | Per l'accesso completo | 8 |
| sec | string | Per l'accesso completo | "f03741b6-..." |
| deviceId | string | Consigliato | "123e4567-..." |
Se la Sua password contiene una virgoletta doppia, un backslash o un a capo, quei caratteri devono essere sottoposti a escape all'interno della stringa JSON. Lasciare che il Suo serializzatore costruisca il corpo (gli approcci json= e JSON.stringify sopra) se ne occupa per Lei.
Leggere l'offset nell'errore
Quando il messaggio Le fornisce un offset come 0x00000028, lo usi. Il valore è esadecimale, 0x28 equivale a 40 in decimale, e punta al byte in cui il parser si è fermato. Conti nel corpo esatto che ha inviato (lo registri, non indovini) e ispezioni quel carattere. Un apice singolo, una virgola senza nulla dopo, o un carattere di controllo si trova quasi sempre proprio lì. Un offset di 0x0 è diverso: significa che il parser non ha trovato nulla da leggere, quindi il Suo corpo era vuoto o non è mai uscito dal client.
Verifichi la soluzione
Una volta che il corpo è pulito e l'intestazione è impostata, riesegua la richiesta. Una chiamata funzionante restituisce HTTP 200 con un payload JSON contenente il Suo accessToken, uno userId, e una expirationTime di circa 90 minuti. Copi quel token in un'intestazione Authorization: Bearer <token> per ogni chiamata successiva.

Se continua a ricevere lo stesso 400, registri i byte grezzi di ciò che sta effettivamente inviando, non ciò che crede di inviare, e li confronti con l'esempio valido sopra. La differenza è quasi sempre una virgoletta o una virgola.
Quando il JSON è pulito e continua comunque a fallire
Se il parser è soddisfatto ma la richiesta continua a dare errore, ha superato il problema di formattazione e si trova davanti a un problema di autenticazione o di ambiente:
- Host sbagliato. Le credenziali demo sull'host reale (o viceversa) falliscono anche con JSON perfetto.
- Secret API o cid errati. Un
secocidnon corretto restituisce un 400 che non ha nulla a che vedere con la formattazione, il corpo è stato analizzato correttamente, i valori semplicemente non corrispondono. - Limite di sessione o limite di frequenza. Bombardare l'endpoint può bloccarLe l'accesso. Se vede fallimenti ripetuti sotto carico, legga la nostra nota sul limite di frequenza 429 dell'API Tradovate.
- Token scaduto nelle chiamate successive. Il token stesso dura solo circa 90 minuti; lo rinnovi prima che scada invece di riautenticarsi ogni volta. Veda 401 non autorizzato dell'API Tradovate (token scaduto).
Semplifichi l'autenticazione con PickMyTrade
Preferisce non dover sorvegliare richieste di token, scadenze di 90 minuti e virgolette JSON? PickMyTrade collega il Suo account Tradovate e instrada i Suoi avvisi TradingView verso ordini reali, l'autenticazione e la gestione delle sessioni funzionano dietro le quinte, quindi non c'è codice di autenticazione da debuggare per Lei.
Faccia a meno del tutto del codice di autenticazione
PickMyTrade collega il Suo account Tradovate e gestisce le richieste di token, i rinnovi e la formattazione JSON dietro le quinte, così i Suoi avvisi vengono instradati senza che Lei debba debuggare nemmeno una chiamata di autenticazione.
Inizi la Sua prova gratuita di 5 giorniDomande frequenti
Il 400 viene generato prima che il server verifichi il Suo accesso. Il corpo non è JSON valido, oppure non è stato inviato come JSON. Cerchi apici singoli, una virgola finale, codifica a modulo, o un'intestazione Content-Type: application/json mancante. Corregga il corpo e le stesse credenziali si autenticheranno senza problemi.
È la posizione in byte in cui il parser JSON si è fermato, scritta in esadecimale. 0x28 equivale a 40 in decimale, quindi guardi intorno al 40° carattere del corpo esatto che ha inviato, è lì che la sintassi si è rotta. Un offset di 0x0 significa che il corpo era vuoto o non è mai arrivato.
Un numero. Invii "cid": 8, non "cid": "8". Racchiuderlo tra virgolette trasforma un campo intero in una stringa e può far respingere la richiesta anche quando il JSON è altrimenti valido.
L'explorer costruisce un corpo pulito con virgolette doppie e imposta l'intestazione per Lei. Il Suo client potrebbe stampare un oggetto di linguaggio con apici singoli, codificare i dati a modulo, o codificare la stringa due volte. Copi il corpo esatto dell'explorer e lo faccia corrispondere byte per byte.
Sì. Esegua l'escape delle virgolette doppie interne con backslash, oppure racchiuda l'intero payload tra apici singoli così che la shell non tocchi le virgolette doppie interne. Passare il corpo da un file con -d @body.json evita del tutto il balletto delle virgolette.
Questa guida ha finalità esclusivamente educative e informative e non costituisce consulenza finanziaria, di investimento o di trading. Il trading di futures e di altri prodotti a leva comporta un rischio di perdita significativo e non è adatto a tutti gli investitori. PickMyTrade è una piattaforma di automazione indipendente di terze parti e non è affiliata, sostenuta o sponsorizzata da Tradovate, Inc. o Bookmap. Tutti i nomi, i loghi e i marchi correlati sono di proprietà dei rispettivi titolari. Le funzionalità e le procedure della piattaforma cambiano nel tempo, pertanto verifichi sempre il processo attuale nella documentazione ufficiale della piattaforma prima di agire.