Tradovate API

Corriger le 401 Access Denied de user/syncrequest sur le WebSocket Tradovate

Vous ouvrez un socket, vous lancez user/syncrequest, et vous obtenez un net 401 Access is denied. Le socket n'a jamais été autorisé, voici exactement le handshake qui corrige cela.

Vérifié par l'équipe Trading Systems de PickMyTrade Dernière mise à jour
· Lecture de 7 minutes
Journal de frames WebSocket Tradovate montrant user/syncrequest renvoyant une réponse 401 Access is denied

Vous avez ouvert un WebSocket, lancé user/syncrequest, et au lieu d'un flux de données de compte et d'ordres, vous avez reçu un net 401 avec “Access is denied.” Rien ne cloche avec votre connexion et rien n'est cassé sur le compte. Le socket n'a tout simplement jamais été autorisé, si bien que le serveur traite chaque requête sur celui-ci comme anonyme. La solution est un ordre d'opérations précis : récupérez un jeton d'accès depuis le point de terminaison d'authentification REST, transmettez-le au socket dans un frame authorize, attendez la réponse de succès, et alors seulement envoyez user/syncrequest. Respectez cet ordre et le 401 disparaît.

C'est ce qui fait trébucher presque tout le monde la première fois qu'on câble le socket Tradovate à la main, généralement parce qu'on essaie de s'authentifier comme fonctionne REST. Les WebSockets ne fonctionnent pas ainsi ici. Passons en revue exactement ce qui se passe et la voie propre pour s'en sortir.

À quoi ressemble réellement l'erreur

Dans votre journal de frames, vous verrez le socket se connecter, le frame open arriver, puis votre user/syncrequest revenir immédiatement avec un refus. Cela ressemble à ceci :

<-- o
--> user/syncrequest
1

<-- a[{"i":1,"s":401,"d":"Access is denied"}]

L'indice révélateur est le statut 401 associé à Access is denied sur le frame de requête. Si vous n'avez jamais vu de réponse de statut 200 à un frame authorize avant cela, voilà votre réponse : le socket n'est pas authentifié.

Pourquoi le socket renvoie un 401

Il n'y a en réalité qu'une poignée de causes profondes, et elles s'empilent dans un ordre prévisible.

1. Le socket n'a jamais été autorisé

C'est la grande cause. Une connexion WebSocket brute vers Tradovate n'est pas authentifiée. L'ouvrir et envoyer immédiatement user/syncrequest revient à entrer dans un club privé et commander un verre sans montrer sa carte. Vous devez envoyer exactement un frame authorize par connexion, portant un jeton d'accès valide, avant que quoi que ce soit d'autre ne puisse passer.

2. Vous avez essayé d'obtenir le jeton via le socket

Une erreur courante consiste à essayer d'appeler accessTokenRequest via le WebSocket lui-même. Ce point de terminaison se trouve du côté REST. Le jeton est émis via HTTPS, puis présenté au socket. Le socket n'émet jamais de jetons.

3. Un paramètre environment dans la requête de jeton

Si vous avez copié un corps de requête quelque part et qu'il inclut "environment": "demo" (ou "live"), supprimez-le. Ce champ n'est pas accepté par accessTokenRequest et peut faire dérailler toute la requête. L'environnement est déterminé par l'hôte que vous appelez, pas par un paramètre.

4. Un compte réel sans deviceId ou avec un appareil non approuvé

Le démo est indulgent. Le réel ne l'est pas. Sur un compte financé/réel, vous devez envoyer un deviceId stable lorsque vous demandez le jeton, et l'appareil doit être approuvé via le flux de confirmation que Tradovate exécute pour la sécurité à deux facteurs. Manquez cela et le jeton réel que vous obtenez n'autorisera pas le socket réel.

5. Le jeton a expiré

Si tout fonctionnait avant et que le 401 a commencé à apparaître de nulle part, c'est que le jeton a vieilli. Les jetons d'accès sont limités dans le temps, si bien qu'un socket de longue durée finira par voir un 401 comme s'il n'avait jamais été autorisé. C'est un problème de renouvellement, pas de configuration.

La solution, étape par étape

1

Obtenez un jeton d'accès depuis REST

Envoyez vos identifiants en POST au point de terminaison d'authentification via HTTPS. Utilisez l'hôte correspondant au compte souhaité :

POST https://demo.tradovateapi.com/v1/auth/accessTokenRequest   (simulé)
POST https://live.tradovateapi.com/v1/auth/accessTokenRequest   (financé)

Content-Type: application/json
{
  "name": "your-username",
  "password": "your-password",
  "appId": "YourAppName",
  "appVersion": "1.0",
  "cid": 0000,
  "sec": "your-api-secret",
  "deviceId": "a-stable-unique-id"
}


La réponse vous remet une chaîne accessToken (plus un horodatage d'expiration). C'est ce jeton que veut le socket. Remarquez qu'il n'y a aucun champ environment dans ce corps, l'hôte démo vous donne un jeton démo, l'hôte réel vous donne un jeton réel.

2

Ouvrez le socket et attendez le frame open

Connectez-vous à l'URL WebSocket correspondant à l'environnement de votre jeton :

wss://demo.tradovateapi.com/v1/websocket   (simulé)
wss://live.tradovateapi.com/v1/websocket   (financé)


Dès que la connexion est établie, le serveur envoie un frame open à un seul caractère : o. N'envoyez rien avant de l'avoir vu. Un jeton démo sur le socket réel (ou l'inverse) est sa propre façon discrète de gagner un 401, alors gardez la paire correspondante.

3

Envoyez le frame authorize

Les frames sur ce socket sont du texte brut : un point de terminaison, un id de requête, une ligne vide pour la chaîne de requête, puis le corps, chacun séparé par un saut de ligne. Le frame authorize place le jeton dans le corps :

authorize
0

YOUR_ACCESS_TOKEN


Écrit sous forme d'une seule chaîne, cela donne authorize\n0\n\nYOUR_ACCESS_TOKEN. Le serveur répond avec un frame de données et un statut qui vous intéresse vraiment :

a[{"i":0,"s":200}]

Le statut 200 signifie que le socket est désormais authentifié pour toute la durée de la connexion. Si vous obtenez autre chose que 200 ici, arrêtez-vous, le jeton est le problème, et la synchronisation ne se réparera pas d'elle-même plus loin.

4

Envoyez maintenant user/syncrequest

Le socket étant autorisé, le même appel qui échouait passe désormais sans problème. Envoyez-le avec l'id de requête suivant et un corps vide pour synchroniser tout ce à quoi l'utilisateur a accès :

user/syncrequest
1



Cela donne user/syncrequest\n1\n\n. Vous récupérerez l'instantané initial des comptes, positions, ordres, exécutions et soldes de trésorerie, et dès lors le socket diffuse des mises à jour incrémentielles au fur et à mesure de leurs changements. user/syncrequest est exclusif au WebSocket, il n'a pas d'équivalent REST, ce qui explique précisément pourquoi le socket doit d'abord être autorisé.

5

Maintenez la connexion active

Une fois autorisé, envoyez un frame de battement de cœur, un tableau JSON vide, [], toutes les quelques secondes (environ toutes les 2,5 secondes) pour que le serveur ne vous déconnecte pas. Le serveur envoie également ses propres battements de cœur. Si vous cessez d'en recevoir pendant environ dix secondes, considérez le socket comme mort, reconnectez-vous, et relancez l'étape d'autorisation sur la nouvelle connexion.

POST REST vers accessTokenRequest renvoyant un accessToken, sans paramètre environment dans le corpsFrame authorize WebSocket portant le jeton d'accès suivi d'une réponse de succès de statut 200

Comptes réels : la vérification du deviceId et des permissions

Si le démo fonctionne parfaitement et que le réel est le seul endroit où vous rencontrez le 401, la cause est presque toujours du côté de l'approbation de l'appareil plutôt que dans votre code. Deux choses à confirmer.

Premièrement, assurez-vous que l'accès API est réellement activé sur le compte et que la clé a la permission de faire ce que vous demandez. Dans l'application web Tradovate, cela se trouve dans les paramètres du compte, dans la section qui gère le complément API Access et les permissions de la clé. (Confirmez le libellé exact dans votre version actuelle, le texte et l'emplacement de cet écran de complément sont ajustés au fil du temps.)

Paramètres de compte Tradovate montrant le complément API Access et les contrôles de permissions de la clé API

Deuxièmement, envoyez un deviceId qui reste identique d'une exécution à l'autre et approuvez-le. Le réel impose une sécurité à deux facteurs basée sur l'appareil ; un deviceId flambant neuf ou manquant déclenche une étape d'approbation qui, tant que vous ne l'avez pas réglée, laisse le jeton incapable d'autoriser le socket réel. Générez un identifiant stable pour votre application, réutilisez-le à chaque fois, et confirmez-le via l'e-mail que Tradovate envoie.

Toujours un 401 ? Parcourez cette liste de contrôle

Vérification Ce qu'il faut confirmer
Authorize est venu en premierVous avez envoyé un frame authorize et vu s:200 avant toute autre requête.
Origine du jetonLe jeton provenait de REST /auth/accessTokenRequest, pas du socket.
Aucun champ environmentLe corps de la requête de jeton n'a pas de paramètre environment.
L'hôte correspond au jetonJeton démo sur le socket démo, jeton réel sur le socket réel, jamais croisés.
deviceId (réel)Un deviceId stable a été envoyé et l'appareil est approuvé.
Fraîcheur du jetonLe jeton n'a pas expiré depuis que vous l'avez récupéré.
Permissions de la cléL'accès API est activé et la clé est autorisée à lire/router sur ce compte.

Si cela fonctionnait puis s'est cassé en cours de session, passez directement à la durée de vie du jeton. Les jetons d'accès ne durent pas éternellement, et un socket resté ouvert un moment commencera à renvoyer des 401 dès que le jeton qui le sous-tend expire. Renouvelez avant l'expiration plutôt que d'attendre les échecs. Et si c'est la toute première requête de jeton qui échoue, revenez en arrière et vérifiez l'accès API et la génération d'une clé avant de toucher le socket.

Évitez entièrement la plomberie du socket

Construire à la main le handshake d'authentification, les battements de cœur, l'approbation de l'appareil et le renouvellement du jeton représente beaucoup de pièces mobiles juste pour router un ordre. Si vous reliez Tradovate à des alertes TradingView ou à une stratégie, PickMyTrade gère toute la couche de connexion pour vous, sessions autorisées, gestion des appareils réels et renouvellement des jetons inclus, si bien que vous envoyez un signal et cela trade.

Évitez la plomberie du socket

PickMyTrade gère toute la couche de connexion pour vous, sessions autorisées, gestion des appareils réels et renouvellement des jetons inclus, si bien que vous envoyez un signal et cela trade.

Démarrez votre essai gratuit de 5 jours

Questions fréquentes

Parce que la connexion WebSocket n'a jamais été autorisée. user/syncrequest ne fonctionne que sur un socket autorisé. Envoyez d'abord un frame authorize portant un jeton d'accès valide, attendez la réponse de statut 200, puis envoyez syncrequest.

Depuis le point de terminaison REST /auth/accessTokenRequest, pas depuis le socket. Envoyez vos identifiants en POST via HTTPS, lisez accessToken dans la réponse JSON, et transmettez ce jeton au socket dans le frame authorize.

Non. environment n'est pas un champ valide pour cette requête et peut la faire échouer. Le choix entre démo et réel est déterminé par l'hôte que vous appelez, l'hôte démo pour le compte simulé, l'hôte réel pour le compte financé.

Le réel impose une approbation d'appareil que le démo n'exige pas. Envoyez un deviceId stable lorsque vous demandez le jeton réel, approuvez l'appareil depuis la confirmation que Tradovate vous envoie par e-mail, et assurez-vous d'autoriser le socket réel avec un jeton réel.

Le jeton a expiré. Les jetons sont limités dans le temps, si bien qu'un socket de longue durée finira par rencontrer un 401 comme s'il n'avait jamais été autorisé. Renouvelez le jeton avant son expiration et réautorisez sur une session neuve.

Ce guide est fourni à des fins éducatives et informatives uniquement et ne constitue pas un conseil financier, d'investissement ou de trading. Le trading de contrats à terme et d'autres produits à effet de levier comporte un risque de perte substantiel et ne convient pas à tous les investisseurs. PickMyTrade est une plateforme d'automatisation tierce indépendante et n'est ni affiliée à, ni approuvée par, ni parrainée par Tradovate, Inc. ou Bookmap. Tous les noms, logos et marques associés sont la propriété de leurs détenteurs respectifs. Les fonctionnalités et les étapes de la plateforme évoluent avec le temps, confirmez donc toujours le processus actuel dans la documentation officielle de la plateforme avant d'agir.