Documentation
Avancé

Meilleures pratiques

Des bonnes pratiques pour que votre intégration Deriv API reste robuste, efficace et résiliente. Appliquez-les en complément de la référence par point de terminaison.

Gestion des connexions

Ouvrez une seule connexion WebSocket et réutilisez-la pour chaque requête et abonnement, plutôt que d'ouvrir une connexion par appel. Multiplexez les requêtes sur le socket partagé et associez chaque réponse à sa requête à l'aide de req_id.

Lorsque la connexion est interrompue, reconnectez-vous avec un backoff exponentiel (par exemple 1s, 2s, 4s, 8s, plafonné) accompagné d'un léger jitter, plutôt que de réessayer en boucle serrée. Envoyez un ping périodique pour maintenir la connexion active et détecter rapidement les déconnexions silencieuses.

Pour une connexion authentifiée, demandez une nouvelle URL OTP avant chaque reconnexion. Chaque URL ne fonctionne qu’une seule fois.

// keepalive: send a ping on an interval over the shared socket
setInterval(() => socket.send(JSON.stringify({ ping: 1 })), 30000);

Limitation du débit et contrôle des requêtes

Limitez le débit des requêtes sortantes pour rester dans les limites de débit de l'API. Mettez les appels en file d'attente et espacez-les au lieu d'envoyer de grandes rafales, et appliquez un anti-rebond aux actions déclenchées par l'utilisateur afin qu'une seule interaction ne génère pas une multitude de requêtes.

Si vous êtes soumis à une limitation de débit, attendez de manière exponentielle avant de réessayer, en augmentant le délai après chaque rejet. Privilégiez les abonnements au polling pour les données qui se mettent à jour en continu, afin que le serveur pousse les modifications plutôt que vous ne les redemandiez.

Vous pouvez rapprocher les virements et retraits effectués par un agent de paiement à l’aide de l’identifiant de requête. Envoyez un request_id unique avec chacun d’eux et, si la réponse est perdue, vérifiez son résultat avec Transfer status ou Withdrawal status au lieu de l’envoyer à nouveau. Un achat ne dispose pas de recherche par identifiant de requête : req_id associe uniquement une réponse à sa requête. Pour éviter un achat en double, achetez par identifiant de proposition : le même identifiant de proposition ne peut pas être acheté deux fois.

Pour les chiffres eux-mêmes — les limites de requêtes par IP et par compte, ainsi que les budgets partagés sur lesquels s'appuient les groupes d'appels WebSocket — consultez Limites.

Authentification et hygiène des tokens

Demandez une URL WebSocket authentifiée avec POST /trading/v1/options/accounts/{accountId}/otp. Envoyez votre jeton dans l’en-tête Authorization: Bearer. Consultez la documentation Options WebSocket pour plus de détails.

Ajoutez l’en-tête Deriv-App-ID lorsque vous utilisez un jeton d’accès personnel (PAT). Les jetons d’accès OAuth 2.0 n’ont pas besoin de cet en-tête. Consultez le guide d’authentification pour plus de détails.

Connectez-vous directement à l’URL dans data.url. L’URL contient un mot de passe à usage unique (OTP), vous n’avez donc pas besoin d’envoyer un message d’authentification après la connexion.

Le mot de passe à usage unique est valide pendant 120 secondes et ne fonctionne qu’une seule fois. Demandez une nouvelle URL OTP avant chaque reconnexion.

Utilisez des jetons disposant des privilèges minimaux requis pour la tâche en demandant uniquement les portées nécessaires à vos points de terminaison, telles que trade ou account_manage ; un jeton ne disposant pas d’une portée requise est rejeté avec une erreur 403.

Pour les applications destinées aux utilisateurs, utilisez le flux OAuth 2.0 Authorization Code avec PKCE plutôt que d’intégrer des tokens. Effectuez toujours l’échange de tokens sur votre backend, et non dans le navigateur, et validez le paramètre state dans le callback avant d’utiliser le code d’autorisation. Les codes d’autorisation sont à usage unique et de courte durée : échangez-les donc immédiatement et ne les stockez ni ne les consignez jamais dans les logs. Générez un nouveau code_verifier et state pour chaque requête, puis supprimez-les une fois l’échange réussi. Les tokens d’accès expirent après le nombre de secondes indiqué dans expires_in. Deriv n’émet pas de tokens de rafraîchissement ; exécutez donc à nouveau le flux d’autorisation lorsqu’un token expire ou qu’un appel renvoie une erreur 401. Si un nouveau token d’accès renvoie également une erreur 401, ne relancez pas le flux. Vérifiez plutôt l’en-tête Authorization et le point de terminaison. Consultez le guide OAuth 2.0 pour l’implémentation complète.

N'intégrez jamais de tokens API à longue durée de vie dans du code côté client, des dépôts publics ou des artefacts de build. Stockez les secrets côté serveur, renouvelez-les régulièrement et révoquez tout token susceptible d'avoir été exposé.

// Run this on your server, or in the browser only with a short-lived OAuth 2.0 access token.
// Never ship a Personal Access Token (PAT) in client-side code.
async function connectAuthenticated(accountId, token) {
  const response = await fetch(
    `https://api.derivws.com/trading/v1/options/accounts/${accountId}/otp`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        // Add this header for PAT authentication only:
        // "Deriv-App-ID": "<app-id>",
      },
    }
  );

  if (!response.ok) {
    throw new Error(`OTP request failed (${response.status})`);
  }

  const result = await response.json();
  const url = result?.data?.url;
  if (!url) {
    throw new Error("OTP response did not include a WebSocket URL");
  }

  return new WebSocket(url);
}

connectAuthenticated("<account-id>", "<token>");
// Request a fresh OTP URL before every reconnect.

Gestion des erreurs et nettoyage des abonnements

Inspectez toujours le champ error de chaque réponse avant d'utiliser ses données, et consignez le code et le message d'erreur dans vos propres journaux. Associez les réponses aux requêtes via req_id afin qu'un échec soit attribué au bon appel.

Libérez les abonnements dont vous n'avez plus besoin : utilisez forget avec un identifiant d'abonnement pour arrêter un flux unique, et forget_all par type de flux pour arrêter tous les flux de ce type. Le nettoyage évite les abonnements non libérés et le trafic inutile.

// stop a single stream by its subscription id
socket.send(JSON.stringify({ forget: subscriptionId }));
// stop every stream of a given type
socket.send(JSON.stringify({ forget_all: "ticks" }));

Cycle de vie du contrat

Un trade suit un cycle de vie court : demandez un prix avec proposal, exécutez-le avec buy, suivez la position ouverte avec proposal_open_contract, et clôturez-la avec sell ou laissez-la se régler à l'expiration. Achetez sur la base d'une nouvelle proposition plutôt que d'une cotation obsolète — les prix sont éphémères. Transmettez un prix maximum dans l'appel buy afin que les variations entre la cotation et l'exécution ne vous imposent pas un remplissage moins favorable.

Suivez chaque contrat ouvert en vous abonnant à proposal_open_contract plutôt qu'en interrogeant portfolio. L'abonnement envoie les mises à jour du cours au comptant et du profit, et bascule les indicateurs is_sold et is_expired dès que le contrat est réglé.

Lorsque is_sold devient true, appelez forget pour cet abonnement afin de libérer le flux et d’éviter les fuites d’abonnements au fil du temps.

A buy réponse contenant un objet error signifie qu’aucun contrat n’a été créé. Si la réponse est perdue ou expire, vérifiez statement avant d’envoyer à nouveau l’achat. Demandez action_type buy, un date_from juste avant son envoi, et description défini sur 1. Faites correspondre la ligne selon son ID d’application, son montant, shortcode et l’heure de la transaction, puis suivez son contract_id avec proposal_open_contract.

statement répertorie chaque achat exécuté dès sa validation ; l’absence de ligne correspondante signifie donc qu’aucun contrat n’a été acheté. req_id associe uniquement une réponse à sa requête. Un identifiant de proposition ne peut pas être acheté deux fois, mais un achat avec des paramètres n’est pas dédupliqué ; ainsi, envoyer buy: 1 à nouveau peut ouvrir un second contrat. C’est pourquoi l’achat par identifiant de proposition est l’option la plus sûre.

Avant de clôturer prématurément, vérifiez les indicateurs propres au contrat — utilisez sell uniquement lorsque is_valid_to_sell est vrai, et utilisez cancel uniquement dans la fenêtre d'annulation de transaction pour les trades pris en charge. Pour les types de contrats pris en charge, définissez le stop loss et le take profit avec contract_update afin que les sorties se fassent côté serveur plutôt que de surveiller le flux et de vendre manuellement.

// track an open contract, then release the stream once it settles
socket.send(JSON.stringify({
  proposal_open_contract: 1,
  contract_id: contractId,
  subscribe: 1,
}));

// on each update, when data.proposal_open_contract.is_sold is true:
//   socket.send(JSON.stringify({ forget: subscriptionId }));

Pagination

Pour les points de terminaison qui renvoient des listes, récupérez les données par pages plutôt que de tout charger d'un coup. Utilisez les paramètres limit et offset pour parcourir les résultats, et gardez des tailles de pages raisonnables afin de réduire la latence et la pression sur la mémoire.

Continuez à demander les pages suivantes jusqu'à ce qu'une page retourne moins de lignes que la limite que vous avez demandée, ce qui indique que vous avez atteint la fin du jeu de données.

D'autres questions ? Nous contacter

Click to open live chat support. Get instant help from our support team.