e-sotop Market API
Accueil Obtenir une clé v1.0

Documentation e-sotop Market API

Référence complète pour intégrer les données financières africaines et mondiales dans vos applications.

REST / JSON BRVM Crypto · Forex · Stocks · Commodities Authentification par clé API

Introduction

e-sotop API est une interface REST unifiée qui réunit, sous une seule base URL et une seule clé, deux capacités complémentaires : la consultation des marchés financiers (BRVM, crypto, forex, actions, matières premières, OPCVM) et le placement d'ordres avec suivi de portefeuille.

Toutes les routes partagent le préfixe /api/v1 et se répartissent en trois familles : /markets (prix), /orders (exécution) et /accounts (portefeuille). Une même clé API, dotée de scopes et d'une granularité par marché, gouverne l'accès à l'ensemble.

Les données de marché reposent sur un cache intelligent pré-chargé en arrière-plan, garantissant des temps de réponse inférieurs à 50 ms dans la grande majorité des cas.

URL de base https://malaw-preprod.online/api/v1
Toutes les routes partagent ce préfixe : /markets, /orders, /accounts. Votre clé API vous est communiquée après validation. Demander un accès →

Démarrage rapide

Voici le chemin le plus court pour effectuer votre premier appel en moins de 2 minutes.

Étape 1 — Obtenir une clé API

Contactez-nous via le formulaire de contact pour recevoir votre clé API. Elle se présente sous cette forme :

Clé API
es_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6

Étape 2 — Premier appel

cURL
curl -X GET \
  "https://malaw-preprod.online/api/v1/markets/brvm/SNTS" \
  -H "X-API-Key: es_live_votre_cle_ici"

Étape 3 — Lire la réponse

JSON — Réponse
{
  "status": "success",
  "request": {
    "type": "brvm",
    "asset": "SNTS",
    "category": "equities"
  },
  "meta": {
    "source": "brvm.org",
    "updated_at": "2026-04-07T08:00:00Z",
    "currency": "XOF"
  },
  "cache": { "hit": true, "age_sec": 187 },
  "data": {
    "ticker": "SNTS",
    "name": "Sonatel",
    "last_price": 18500,
    "change_pct": 1.65,
    "volume": 4320,
    "prev_close": 18200
  }
}

Authentification

Toutes les requêtes doivent inclure une clé API valide. Deux méthodes sont acceptées :

Via le header HTTP (recommandé)

Header
X-API-Key: es_live_votre_cle_ici

Scopes & granularité par marché

Chaque clé porte deux niveaux de permission qui se combinent : des scopes (quelles opérations) et une liste de marchés autorisés (sur quels marchés).

ScopeAutorise
market:readLire les prix (/markets)
orders:readConsulter comptes & portefeuilles (/accounts)
orders:tradePlacer des ordres (/orders)

Exemple : une clé avec market:read et les marchés ["brvm","opcvm"] peut lire les prix BRVM et OPCVM, mais une requête sur crypto renverra 403. Votre périmètre exact (scopes et marchés) vous est communiqué avec votre clé.

Sécurité Ne partagez jamais votre clé API dans un dépôt public. Transmettez-la via le header X-API-Key plutôt que dans l'URL, qui peut apparaître dans les logs.

Conventions de format

Ces règles s'appliquent à tous les endpoints. Les tableaux de paramètres de chaque endpoint s'y réfèrent.

ÉlémentConvention
Corps des requêtesJSON, en-tête Content-Type: application/json obligatoire sur POST
Authentificationen-tête X-API-Key obligatoire sur toutes les requêtes
Montantsentiers, en XOF (pas de décimales)
Dateschaîne au format AAAA-MM-JJ (ex. 1990-01-01)
Téléphonephone : numéro local sans indicatif ; phone_code : indicatif avec + (ex. +225)
Documentsfichiers encodés en Base64 dans content_base64
Booléens KYCexprimés en chaîne ("Oui" / "Non") selon le courtier
Colonne « Requis »Oui = rejet si absent · Cond. = requis sous condition · Non = optionnel

Gestion des erreurs

L'API retourne toujours un JSON avec un champ status. En cas d'erreur, un champ message décrit le problème.

Code HTTPStatusCause
200successRequête traitée avec succès.
400errorParamètre manquant ou invalide (type, asset).
401errorClé API absente ou invalide.
403errorCompte suspendu ou type non autorisé par votre plan.
404errorAsset introuvable.
429errorRate limit atteint. Attendez la prochaine fenêtre horaire.
502errorÉchec de récupération côté source externe.
JSON — Réponse d'erreur
{
  "status": "error",
  "code": 401,
  "message": "Clé API invalide."
}

Rate limiting

Chaque clé API est soumise à une limite de requêtes par heure, définie par votre plan. L'état du rate limit est transmis dans les headers de chaque réponse :

Headers de réponse
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 487
X-RateLimit-Reset: 1712345678
X-RateLimit-Window: 3600
HeaderDescription
X-RateLimit-LimitNombre maximum de requêtes autorisées par heure.
X-RateLimit-RemainingNombre de requêtes restantes dans la fenêtre courante.
X-RateLimit-ResetTimestamp UNIX de réinitialisation du compteur.

Endpoint unique

GET /api/v1/markets/{type}/{asset}

Retourne les données d'un asset financier selon son type et son identifiant.

Paramètres de requête

ParamètreTypeRequisDescription
typestring Requis Type de marché : brvm, crypto, forex, stocks, commodities
assetstring Requis Identifiant de l'asset (ex: SNTS, BTC, EURUSD) ou ALL pour la liste complète.
categorystring Optionnel Sous-catégorie BRVM uniquement : equities (défaut), bonds, indices

BRVM — Bourse Régionale des Valeurs Mobilières

Couvre l'ensemble des titres cotés à la BRVM : actions, obligations et indices. Les données sont rafraîchies toutes les heures aux horaires d'ouverture du marché.

Actions (equities)

Exemples
# Action spécifique
GET /api/v1/markets/brvm/SNTS

# Toutes les actions cotées
GET /api/v1/markets/brvm/ALL
ChampTypeDescription
tickerstringSymbole boursier (ex: SNTS, BOAB)
namestringNom de la société
last_pricenumberDernier cours en XOF
prev_closenumberCours de clôture de la veille
opennumberCours d'ouverture
changenumberVariation absolue en XOF
change_pctnumberVariation en pourcentage
volumeintegerVolume de titres échangés

Obligations (bonds)

Exemple
GET /api/v1/markets/brvm/ALL/bonds

Indices

Exemple
GET /api/v1/markets/brvm/ALL/indices

Retourne les trois indices BRVM : BRVM Composite, BRVM 30, BRVM Prestige.

Cryptomonnaies

Données issues de CoinGecko. Couvre le top 500 par capitalisation boursière. Rafraîchissement toutes les 5 minutes.

Exemples
# Crypto spécifique
GET /api/v1/markets/crypto/BTC
GET /api/v1/markets/crypto/ETH

# Top 500 complet
GET /api/v1/markets/crypto/ALL
ChampTypeDescription
tickerstringSymbole (BTC, ETH, SOL...)
namestringNom complet
last_pricenumberPrix en USD
high_24hnumberPlus haut sur 24h
low_24hnumberPlus bas sur 24h
change_pct_24hnumberVariation 24h en %
volume_24hnumberVolume 24h en USD
market_capnumberCapitalisation boursière USD
rankintegerRang par capitalisation

Forex

160+ paires de devises dont XOF, XAF, GHS, NGN et toutes les devises africaines majeures. Rafraîchissement toutes les 5 minutes.

Exemples
# Dollar → Franc CFA
GET /api/v1/markets/forex/USDXOF

# Euro → Dirham marocain
GET /api/v1/markets/forex/EURMAD

# Toutes les devises (base USD)
GET /api/v1/markets/forex/ALL
Format des paires Concaténez les deux codes ISO 4217 : devise de base + devise de cotation. Ex : USDXOF = 1 USD exprimé en XOF.
ChampTypeDescription
pairstringPaire (ex: USD/XOF)
basestringDevise de base
quotestringDevise de cotation
ratenumberTaux de conversion
quote_namestringNom complet de la devise de cotation

Stocks

Actions mondiales via Yahoo Finance (NYSE, NASDAQ, LSE, Euronext...). Le screener couvre dynamiquement les 300+ titres les plus actifs. Tout ticker Yahoo Finance est accepté.

Exemples
# Actions américaines
GET /api/v1/markets/stocks/AAPL
GET /api/v1/markets/stocks/TSLA

# ADR africain
GET /api/v1/markets/stocks/MTN

# Top 300 actifs du moment
GET /api/v1/markets/stocks/ALL
ChampTypeDescription
tickerstringSymbole Yahoo Finance
namestringNom de la société
last_pricenumberDernier cours
change_pctnumberVariation journalière en %
volumenumberVolume journalier
market_capnumberCapitalisation boursière
exchangestringPlace boursière

Matières premières

16 contrats futures couvrant métaux précieux, énergie, céréales et soft commodities. Le cacao, le café et le coton sont inclus en priorité pour leur importance en Afrique de l'Ouest.

Exemples
# Or
GET /api/v1/markets/commodities/GOLD

# Cacao (pertinent CI, Ghana)
GET /api/v1/markets/commodities/COCOA

# Toutes les matières premières
GET /api/v1/markets/commodities/ALL
TickerNomUnitéSecteur
GOLDOrtroy_ozMétaux précieux
SILVERArgenttroy_ozMétaux précieux
BRENTBrent Crude OilbarrelÉnergie
WTIWTI Crude OilbarrelÉnergie
GASNatural GasMMBtuÉnergie
COPPERCuivrelbMétaux industriels
COCOACacaometric_tonSofts
COFFEECafélbSofts
SUGARSucrelbSofts
COTTONCotonlbSofts
CORNMaïsbushelCéréales
WHEATBlébushelCéréales

OPCVM — Fonds NSIA Invest

Valeurs liquidatives des fonds OPCVM gérés par NSIA Invest (SGO agréée UEMOA). Les VL sont publiées une fois par jour ouvré et servies depuis un cache rafraîchi automatiquement — l'API ne sollicite jamais NSIA sur une requête client, garantissant une réponse rapide et stable.

Exemples
# Un fonds précis (par identifiant produit)
GET /api/v1/markets/opcvm/45

# Tous les fonds OPCVM
GET /api/v1/markets/opcvm
ChampTypeDescription
tickerstringIdentifiant normalisé du fonds
navnumberValeur liquidative (VL) courante
last_pricenumberAlias de la VL (cohérence multi-marchés)
nav_datestringDate de la VL (AAAA-MM-JJ)
prev_navnumberVL précédente (calcul de variation)
currencystringDevise (XOF)
Scope requis : market:read avec le marché opcvm autorisé sur votre clé.

API d'ordres — Vue d'ensemble

Au-delà des données de marché, l'API permet de placer des ordres et de consulter les portefeuilles de vos clients finaux. Ces opérations partagent la même base URL /api/v1 et la même clé que les données de marché — seuls les scopes diffèrent.

Deux familles d'opérations distinctes :

FamillePréfixeNatureScope
Données de marché/marketsLecture des prixmarket:read
Placement d'ordres/ordersExécution (écriture)orders:trade
Consultation de compte/accountsPortefeuille, historiqueorders:read
Modèle de paiement : le partenaire encaisse lui-même son client, puis transmet l'ordre déjà payé avec les détails de paiement. L'API n'encaisse jamais : c'est une passerelle d'exécution pure.

Devis (quote)

Obtenez un devis avant d'engager un ordre : frais du courtier et référence de prix. Le devis n'engage pas. Requiert le scope orders:read.

ChampTypeRequisDescription
asset_typestringOuimarché — ex. opcvm
asset_refstringOuiidentifiant de l'actif
sidestringOuiBUY ou SELL
amountnumberOuimontant en XOF, entier > 0
Requête
# Devis pour une souscription OPCVM de 100 000 XOF
POST /api/v1/quotes
Content-Type: application/json

{
  "asset_type": "opcvm",
  "asset_ref": "45",
  "side": "BUY",
  "amount": 100000
}

Ouverture de compte

Certains marchés exigent qu'un compte client soit créé chez le courtier avant tout ordre (KYC réglementaire). C'est le cas de l'OPCVM. Requiert le scope orders:trade. Le profil est transmis dans un vocabulaire neutre ; l'API le traduit vers le format du courtier.

Corps — niveau racine

ChampTypeRequisDescription
asset_typestringOuimarché — ex. opcvm
profileobjectOuiprofil du client (détaillé ci-dessous)

profile — identité

ChampTypeRequisDescription / format
first_name · last_namestringOuiprénom · nom (≤ 100 car.)
emailstringOuiadresse e-mail (≤ 100)
phonestringOuinuméro local sans indicatif (≤ 10)
phone_codestringOuiindicatif avec + — ex. +225
titlestringOuicivilité — M / Mme
genderstringOuisexe — M / F
birth_datestringOuidate de naissance — AAAA-MM-JJ
birth_placestringOuilieu de naissance
nationalitystringOuinationalité
residence_country · citystringOuipays de résidence · ville
addressstringOuiadresse géographique
professionstringOuiprofession

profile.kyc — conformité

ChampTypeRequisDescription
marital_statusstringOuisituation matrimoniale
marital_regimestringNonrégime matrimonial
politically_exposedstringOuipersonne politiquement exposée — Oui/Non
professional_statusstringOuisituation professionnelle
activity_sectorstringOuisecteur d'activité
funds_originstringOuiorigine des fonds
judicial_recordstringOuiantécédents (anti-blanchiment)
us_residentstringOuirésident américain — Oui/Non
tax_obligationstringOuiobligations fiscales
main_objectivestringOuiobjectif principal du placement
investment_horizonstringOuihorizon de placement

profile.documents[] — pièces justificatives

ChampTypeRequisDescription
typestringOuitype — ex. CNI RECTO, CNI VERSO, PASSEPORT, JUSTIFICATIF DE DOMICILE, SELFIE, SIGNATURE 1 CLIENT
content_base64stringOuifichier encodé en Base64
extensionstringOuiextension — ex. jpg, png, pdf
numberstringNonnuméro du document
Requête
POST /api/v1/accounts
X-API-Key: es_live_votre_cle
Content-Type: application/json

{
  "asset_type": "opcvm",
  "profile": {
    "first_name": "Landry",
    "last_name": "Fofana",
    "email": "landry@example.com",
    "phone": "0757534697",
    "phone_code": "+225",
    "title": "M",
    "gender": "M",
    "birth_date": "1990-01-01",
    "birth_place": "Abidjan",
    "nationality": "Ivoirienne",
    "residence_country": "Côte d'ivoire",
    "city": "Abidjan",
    "address": "Marcory Rue 22",
    "profession": "Ingénieur",
    "kyc": {
      "marital_status": "Célibataire",
      "funds_origin": "Salaire",
      "politically_exposed": "Non",
      "us_resident": "Non",
      "investment_horizon": "Long terme",
      "main_objective": "Épargne"
    },
    "documents": [
      { "type": "CNI RECTO", "extension": "jpg", "number": "C-123", "content_base64": "..." },
      { "type": "CNI VERSO", "extension": "jpg", "number": "C-123", "content_base64": "..." }
    ]
  }
}
Réponse
{
  "status": "success",
  "account": {
    "account_ref": "1691",
    "status": "PENDING"
  }
}

Le champ account_ref renvoyé est l'identifiant à réutiliser comme end_user_ref lors du placement d'ordres. Statuts possibles : ACTIVE, PENDING, BLOCKED, UNKNOWN.

Documents (KYC) : chaque entrée de documents[] porte le fichier encodé en Base64 dans content_base64. Types attendus selon le courtier : justificatif de domicile, CNI recto/verso ou passeport, selfie, signatures.

Placer un ordre

Crée et soumet un ordre au courtier. Requiert le scope orders:trade et le header Idempotency-Key — une même clé d'idempotence ne crée jamais deux ordres (garantie anti-double-souscription).

Pas de compte, pas d'ordre. Si le marché exige un compte (ex. OPCVM), le client final doit exister et être au statut ACTIVE chez le courtier. Créez-le d'abord via Ouverture de compte. Un ordre pour un compte inexistant ou non actif est refusé.

En-têtes

En-têteRequisDescription
X-API-KeyOuivotre clé API
Idempotency-KeyOuiidentifiant unique de la requête ; rejouer la même clé ne recrée pas d'ordre
Content-TypeOuiapplication/json

Paramètres du corps

ChampTypeRequisDescription / format
asset_typestringOuimarché ciblé — ex. opcvm
asset_refstringOuiidentifiant de l'actif (pour OPCVM : l'id du fonds)
sidestringOuiBUY (souscription) ou SELL (rachat)
amountnumberOuimontant en XOF, entier > 0
end_user_refstringCond.référence du compte client — obligatoire si le marché exige un compte
meta.type_rachatstringNonSELL uniquement — PARTIEL (défaut) ou TOTAL
paymentobjectOuidétails du paiement déjà encaissé (voir ci-dessous)
payment.moyenPaiementstringOuiopérateur — ex. mtn, orange, moov, wave
payment.montantAPayernumberCond.BUY — montant + frais (souvent ≥ amount)
payment.telephonestringCond.BUY — téléphone du payeur
payment.numeroComptestringCond.SELL — numéro de compte à créditer
payment.referencestringOuiréférence partenaire (traçabilité / rapprochement)
Requête
# Le partenaire a déjà encaissé : il fournit les détails de paiement
POST /api/v1/orders
X-API-Key: es_live_votre_cle
Idempotency-Key: cmd-2026-0042
Content-Type: application/json

{
  "asset_type": "opcvm",
  "asset_ref": "45",
  "side": "BUY",
  "amount": 100000,
  "end_user_ref": "1188",
  "payment": {
    "moyenPaiement": "mtn",
    "montantAPayer": 101500,
    "telephone": "0757534697",
    "reference": "cmd-2026-0042"
  }
}
Réponse
{
  "status": "success",
  "order": {
    "id": "ord_a1b2c3d4e5",
    "asset_type": "opcvm",
    "side": "BUY",
    "amount": 100000,
    "state": "SUBMITTED",
    "provider": "opcvm",
    "provider_ref": "SUB-99871"
  }
}

Les états d'un ordre suivent un cycle universel, quel que soit le marché :

ÉtatSignification
RECEIVEDReçu et validé, pas encore soumis
SUBMITTEDTransmis au courtier
EXECUTINGEn cours de traitement
SETTLEDExécuté avec succès
REJECTED / FAILEDRefusé / échoué
CANCELLEDAnnulé avant soumission

Suivre & annuler un ordre

Deux mécanismes de suivi : interrogation directe (polling) et webhooks (poussés vers votre webhook_url à chaque changement d'état).

Exemples
# État d'un ordre (rafraîchi depuis le courtier)
GET /api/v1/orders/ord_a1b2c3d4e5

# Annuler (si le courtier et l'état le permettent)
POST /api/v1/orders/ord_a1b2c3d4e5/cancel

Comptes & portefeuille

Consultez le compte, l'historique et le portefeuille d'un client final. Requiert le scope orders:read. Les données sont exposées dans un vocabulaire neutre commun à tous les courtiers : votre application affiche un portefeuille sans connaître le courtier sous-jacent.

Paramètres de requête (query)

ParamètreTypeRequisDescription
asset_typestringOuimarché ciblé — ex. opcvm
pagenumberNonhistorique uniquement — numéro de page
limitnumberNonhistorique uniquement — éléments par page

Le segment {ref} de l'URL est la référence du compte client (l'account_ref obtenu à l'ouverture de compte).

Exemples
# Rechercher un compte
GET /api/v1/accounts/1188?asset_type=opcvm

# Historique des ordres du client
GET /api/v1/accounts/1188/history?asset_type=opcvm

# Portefeuille détaillé (positions, valorisation, plus-value)
GET /api/v1/accounts/1188/portfolio?asset_type=opcvm

# Portefeuille global (performance + courbe d'évolution)
GET /api/v1/accounts/1188/summary?asset_type=opcvm

Chaque position du portefeuille est décrite avec des champs neutres :

ChampDescription
asset_refRéférence de l'actif détenu
asset_nameNom affichable
quantityQuantité détenue (parts, unités…)
avg_pricePrix moyen d'acquisition
current_pricePrix courant unitaire
invested_amountMontant investi
current_valueValeur actuelle
pnlPlus/moins-value
currencyDevise

Le portefeuille global (/summary) agrège l'ensemble et fournit la performance et la courbe d'évolution, prête à tracer :

ChampDescription
total_valueValeur nette totale du portefeuille
performancePerformance globale
percentagePourcentage d'évolution
pnlPlus-value totale
chartSérie de valeurs (évolution, 90 j par défaut)
chart_dataSérie datée : [{ "value", "date" }] pour un graphe
currencyDevise

Format de réponse

Toutes les réponses suivent la même enveloppe JSON, quel que soit le type d'asset demandé.

Structure complète
{
  "status": "success",          // "success" ou "error"
  "message": "OK",
  "request": {                  // Echo des paramètres envoyés
    "type": "brvm",
    "asset": "SNTS",
    "category": "equities"
  },
  "meta": {                     // Informations sur la source
    "source": "brvm.org",
    "updated_at": "2026-04-07T08:00:00Z",
    "currency": "XOF",
    "category": "equities"
  },
  "cache": {                    // État du cache
    "hit": true,               // true = servi depuis le cache
    "age_sec": 312             // Âge du cache en secondes
  },
  "data": { /* ... données de l'asset ... */ }
}

Système de cache

L'API utilise un système de cache fichier JSON côté serveur. Les données sont précachées par un processus cron en arrière-plan, ce qui garantit des réponses rapides même pour les assets très demandés.

TypeTTL du cacheRafraîchissement
BRVM60 minutesAux heures de marché (Lu–Ve)
Crypto5 minutesContinu
Forex5 minutesContinu
Stocks15 minutesAux heures de marché
Commodities15 minutesContinu
Tip performance Le champ cache.hit: true indique une réponse servie depuis le cache (temps de réponse < 50 ms). Un cache.hit: false indique un fetch en direct depuis la source (~500 ms–2 s).

Plans & limites

FonctionnalitéStarterProEnterprise
BRVM
Crypto
Forex
Stocks
Commodities
Rate limit100 req/h500 req/h2 000 req/h
Historique SQL90 joursIllimité
Whitelist IP
SupportEmailPrioritaireDédié + SLA

Demander une clé API

Remplissez le formulaire ci-dessous. Vous recevrez votre clé API ainsi que l'endpoint d'accès sous 24h ouvrées.

En soumettant ce formulaire, vous acceptez d'être contacté par l'équipe e-sotop services.


© 2026 e-sotop services · Dakar, Sénégal · Retour à l'accueil