API REST pour développeurs et agents IA
Une requête, une réponse déjà agrégée. Toutes les routes partagent la même forme, la même enveloppe et les mêmes paramètres transverses : ce qui est vrai d’une famille l’est des autres.
Les agents IA atteignent les mêmes routes sans construire d’URL : les outils du serveur MCP les appellent avec votre clé et renvoient les mêmes champs.
#La forme d’une requête
GET https://api.bytnode.com/v1/<family>/<metric>
?symbol=BTCUSDT # required on per-asset routes
&timeframe=1h # on bucketed routes
&limit=100 # on /history routes
&fields=time,rate_pct
X-API-KEY: your_keyLe chemin dit la famille et la métrique. Les paramètres disent l’actif, l’unité de temps et la profondeur. L’en-tête porte la clé. Il n’y a rien d’autre à savoir pour appeler n’importe quelle route.
Un seul endpoint échappe à cette forme : POST /v1/indicators, qui prend un corps JSON parce qu’il décrit un calcul, pas une lecture.
#Dernière valeur ou historique
La plupart des métriques existent en deux versions. La route nue renvoie la dernière valeur : un objet, ou null. Le suffixe /history renvoie une liste de fenêtres closes uniquement, de la plus récente à la plus ancienne.
# The latest value
GET /v1/basis?symbol=BTCUSDT
# The last 24, from newest to oldest
GET /v1/basis/history?symbol=BTCUSDT&timeframe=1h&limit=24
# A dated window, in epoch milliseconds (here the last 12 hours, computed by the shell)
NOW=$(( $(date +%s) * 1000 ))
curl -H "X-API-KEY: $BYTNODE_API_KEY" \
"https://api.bytnode.com/v1/basis/history?symbol=BTCUSDT&timeframe=1h&since_ms=$(( NOW - 43200000 ))&until_ms=$NOW"#Paramètres communs
| Paramètre | Type | Défaut | Description |
|---|---|---|---|
symbol | string | obligatoire | L’actif, au format du catalogue (BTCUSDT), dans n’importe quelle casse. Absent : 422. Inconnu : 422 avec la liste. Les routes de tout le marché ne l’acceptent pas. |
timeframe | string | obligatoire | Sur les routes par intervalles, obligatoire : 1m, 5m, 15m, 30m, 1h, 4h, 1d (et 1w sur les bougies). Absent ou hors liste : 422. Une ligne par minute, c’est timeframe=1m. |
limit | integer | — | Nombre de lignes, des plus récentes aux plus anciennes, sur les routes /history et les séries : 100 par défaut et 1000 au plus sur toutes les routes ; 10 000 au plus sur les événements individuels (ticks spot et futures, gros trades, liquidations). Au-delà d’une page, suivez next. |
since_ms / until_ms | integer | — | Fenêtre de temps en millisecondes Unix, là où la route l’accepte. Le filtre s’applique avant limit. |
live | boolean | false | Sur les routes de dernière valeur par intervalles : expose la période en cours, marquée is_closed: false. |
fields | string | — | Projection CSV de data, notation pointée pour les champs imbriqués. Champ inconnu : 422 avec une suggestion. |
Ce qui n’existe pas
Le paramètre exchange n’existe sur aucune route : le passer renvoie 422, comme tout paramètre qu’une route ne déclare pas, ou un paramètre répété ; l’erreur suggère le nom le plus proche.
#Paginer un historique
Chaque route /history se pagine avec next : chaque réponse porte l’URL de la page suivante, ou null une fois la plage lue. Les lignes arrivent de la plus récente à la plus ancienne par défaut ; avec order=asc (et since_ms), de la plus ancienne. Chaque ligne porte time et is_closed.
- Demandez une première page :
limitlignes, sans borne pour les plus récentes, ousince_msetorder=ascpour avancer à partir d’une date. - Appelez
nexttel quel : c’est l’URL relative de la page suivante (/v1/klines/history?symbol=BTCUSDT&timeframe=1h&limit=500&before_ms=…), vos paramètres compris — préfixez-la de l’hôte de l’API. Vers le passé, elle utilisebefore_ms, une borne EXCLUSIVE : aucune ligne ne revient deux fois, rien à soustraire. - Arrêtez-vous quand
nextvautnull: la plage est lue, ou la page suivante sortirait de la fenêtre d’historique de votre offre (la dernière page ne demande alors que les lignes qui y tiennent encore). Un403history_depthne revient que si vous écrivez vous-même une borne au-delà de cette fenêtre ;GET /v1/limitsdonne les fenêtres de votre offre. Sur les trades individuels (/v1/trades/*), une page couvre au plus 15 minutes et peut être vide ou partielle alors quenextn’est pasnull: seulnext: nulltermine la plage. Il en va de même sur toute route paginée : une lecture d’historique qui atteint une période dense rend, dans son budget de temps, les lignes déjà lues — une page courte avec unnext, jamais un dépassement de délai. Les SDK officiels suiventnextpour vous.
import os
import requests # pip install requests
def history(path: str, params: dict, max_pages: int = 20) -> list[dict]:
"""Every row of a /history route, following `next` until the range is read."""
rows: list[dict] = []
url, query = f"https://api.bytnode.com{path}", params
for _ in range(max_pages):
body = requests.get(
url,
params=query,
headers={"X-API-KEY": os.environ["BYTNODE_API_KEY"]},
timeout=30,
).json()
if body["status"] == "error":
# history_depth: the range asked goes further back than your plan's window;
# error.message gives the largest limit that fits. Never swallow it.
raise RuntimeError(f'{body["error"]["code"]}: {body["error"]["message"]}')
page = body["data"] or []
rows += page
if body.get("next") is None:
break # the range is read
# `next` is the relative URL of the following page, your parameters
# included: call it as is. It never repeats a row.
url, query = f"https://api.bytnode.com{body['next']}", None
return rows
# Without `limit`, each page stops at your plan's history window: no 403.
candles = history("/v1/klines/history", {"symbol": "BTCUSDT", "timeframe": "1h"})#Les familles
Toutes les routes tiennent sur une page dans le catalogue des endpoints ; chaque champ de chaque route, avec son unité et une réponse réelle, est dans la référence interactive.