Документация по работе с публичным batch-эндпоинтом DYOR Platform
DYOR Public API — это единый batch-эндпоинт, через который вы можете запросить агрегированные исторические и рыночные данные платформы DYOR (информация по монетам, рыночные индексы, ликвидации, фандинг, открытый интерес, ордерхистори и т.д.) одним HTTP-запросом, объединяющим до нескольких независимых запросов разных типов.
Объединение запросов в batch снижает накладные расходы (CORS preflight, TLS handshake, установка соединения) и позволяет сократить латентность при загрузке нескольких графиков одновременно.
Доступ продаётся как помесячный апгрейд «Доступ к API» в магазине апгрейдов DYOR. После покупки вы создаёте API-ключ на странице /apiAccount и указываете до двух разрешённых IP-адресов, с которых будут приниматься запросы.
Каждый запрос должен содержать HTTP-заголовок X-API-Key со значением вашего ключа. IP-адрес отправителя сравнивается со списком разрешённых IP, привязанных к ключу. Запросы с IP вне whitelist'а отклоняются с кодом 401.
Управление ключом и IP-списком — на странице /apiAccount. Один ключ на пользователя, до 2 IP в whitelist.
Метод: POST
URL: https://api.dyorplatform.com/publicApi/v1/batch
Content-Type: application/json
Accept: application/json
curl -X POST https://api.dyorplatform.com/publicApi/v1/batch \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"requests": [
{"type": "coinInfo", "params": {"symbol": "btcusdt", "from": 1760081100, "to": 1760081536, "interval": "1m"}},
{"type": "marketInfo", "params": {"from": 1760081100, "to": 1760081536, "interval": "1m"}}
]
}'const response = await fetch('https://api.dyorplatform.com/publicApi/v1/batch', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
requests: [
{ type: 'coinInfo', params: { symbol: 'btcusdt', from: 1760081100, to: 1760081536, interval: '1m' } },
{ type: 'funding', params: { from: 1760000000, to: 1760086400, interval: '1h' } },
],
}),
});
const data = await response.json();
console.log(data.results);Метод: GET
URL: https://api.dyorplatform.com/publicApi/v1/supportedCoins
Возвращает список всех монет, доступных на платформе — используйте чтобы знать какие symbol можно передавать в batch / WebSocket. Авторизация — тот же ключ X-API-Key с правом batch.
curl https://api.dyorplatform.com/publicApi/v1/supportedCoins \
-H "X-API-Key: YOUR_API_KEY"
// Ответ — массив:
// [
// {"symbol": "BTCUSDT", "base": "BTC", "quote": "USDT", "exchangeTypes": ["SPOT", "FUTURES"]},
// {"symbol": "ETHUSDT", "base": "ETH", "quote": "USDT", "exchangeTypes": ["SPOT", "FUTURES"]},
// ...
// ]Вставьте ваш API-ключ и тело запроса, нажмите «Отправить» — запрос уйдёт напрямую с вашего браузера на /publicApi/v1/batch. Ключ нигде не сохраняется и не покидает вашу машину между сессиями.
Для real-time данных доступен публичный WebSocket-эндпоинт. Он работает поверх той же подписки «Доступ к API», что и REST batch — отдельной покупки не нужно.
URL: wss://api.dyorplatform.com/publicApi/v1/ws?apiKey=YOUR_API_KEY
IP-адрес отправителя должен входить в whitelist ключа. Если ключ или IP не валиден, либо подписка api_access не активна — соединение закрывается с кодом 1008 и причиной (missing_api_key, invalid_api_key, subscription_required).
Клиент отправляет JSON-сообщения с полем action:
// Подписаться
{"action":"subscribe","type":"coinInfo","params":{"symbol":"btcusdt","interval":"1m"}}
// Отписаться
{"action":"unsubscribe","type":"coinInfo","params":{"symbol":"btcusdt","interval":"1m"}}
// Получить список текущих подписок
{"action":"list"}
// Heartbeat (опционально)
{"action":"ping"}Сервер отвечает JSON-сообщениями с полем type:
// Подтверждение подписки
{"type":"subscribed","for":"coinInfo","params":{"symbol":"btcusdt","interval":"1m"}}
// Подтверждение отписки
{"type":"unsubscribed","for":"coinInfo","params":{"symbol":"btcusdt","interval":"1m"}}
// Список активных подписок (ответ на "list")
{"type":"subscriptions","items":[{"for":"coinInfo","params":{...}}, ...]}
// Real-time обновление — поле data это ОДИН элемент того же типа,
// что возвращается в массиве batch-ответа для соответствующего type
{"type":"update","for":"coinInfo","params":{"symbol":"btcusdt","interval":"1m"},"data":{...}}
// Ошибка — echo действия в поле action для отладки
{"type":"error","code":"unsupported_stream_type","message":"...","action":{...}}
// Heartbeat ответ
{"type":"pong"}
// Перед закрытием по причине истечения подписки
{"type":"closing","reason":"subscription_expired","message":"Active api_access required"}Чтобы подписаться на много тикеров одним сообщением — передайте массив symbols в params. Такое сообщение считается за 1 action для rate-limit, независимо от количества тикеров. Поддерживается для типов coinInfo и marginLendingCoin.
// Подписаться сразу на N тикеров (одно action-сообщение)
{
"action": "subscribe",
"type": "coinInfo",
"params": {
"interval": "1m",
"symbols": ["btcusdt", "ethusdt", "solusdt", "bnbusdt"]
}
}
// То же для отписки
{
"action": "unsubscribe",
"type": "coinInfo",
"params": {
"interval": "1m",
"symbols": ["btcusdt", "ethusdt"]
}
}Сервер возвращает агрегированный ответ с per-symbol статусами:
{
"type": "bulk_subscribed",
"for": "coinInfo",
"params": {"interval": "1m", "symbols": ["btcusdt", "ethusdt", "solusdt", "bnbusdt"]},
"results": [
{"symbol": "btcusdt", "status": "ok"},
{"symbol": "ethusdt", "status": "ok"},
{"symbol": "solusdt", "status": "ok"},
{"symbol": "bnbusdt", "status": "error", "code": "invalid_params",
"message": "type=coinInfo missing or invalid params"}
]
}
// Симметрично для unsubscribe:
{"type": "bulk_unsubscribed", "for": "coinInfo", "params": {...}, "results": [...]}results имеет status: "ok" или "error". У ошибочных заполнены code и message (те же коды, что у одиночных подписок: invalid_params, already_subscribed, too_many_subscriptions и т.д.).error bulk_too_large.marketInfo) — error unsupported_bulk.Через WebSocket стримятся 5 типов из batch API. Поле data в update-сообщении содержит один элемент той же схемы, которая описана в разделе «Типы запросов» для соответствующего batch-типа.
| type | params | Схема data |
|---|---|---|
coinInfo | symbol, interval | см. coinInfo |
marketInfo | interval, totalType (опц.) | см. marketInfo |
minervaScreener | — | см. minervaScreener |
marginLendingCoin | symbol, interval | см. marginLendingCoin |
marginLendingTotal | interval | см. marginLendingTotal |
Следующие типы не имеют real-time стрима и доступны только через POST /publicApi/v1/batch:
funding — обновляется раз в час, чтения через batch достаточноbinanceOpenInterestCoin, binanceOpenInterestTotal — обновляются по интервалам, опрос через batchmarketCap, marketCapV2 — обновляются по интерваламtotalLiquidations — внешний источник с rate-лимитамиaskBidAnomalies — обновляется по интерваламorderHistory — модель агрегированных запросов, не подходит для стримингаПри попытке подписаться на любой из этих типов сервер ответит ошибкой unsupported_stream_type.
subscribe / unsubscribe / list). ping не входит в лимит. Bulk-сообщение со списком symbols считается за 1 action независимо от размера — подписывайтесь массово.error rate_limit_exceeded с полем message «retry in Xs».api_access. Если она истекла или на паузе — соединение закрывается с reason subscription_expired.| code | Описание |
|---|---|
invalid_action | Неизвестное поле action или невалидный JSON. |
invalid_params | Отсутствуют обязательные параметры (например, symbol) или они некорректны. |
unsupported_stream_type | Тип не поддерживается WebSocket'ом, используйте REST batch. |
already_subscribed | Подписка с такими параметрами уже активна. |
not_subscribed | Попытка unsubscribe для несуществующей подписки. |
rate_limit_exceeded | Превышен лимит action-сообщений. В message — через сколько секунд можно повторить. |
too_many_subscriptions | Достигнут лимит в 1000 подписок на коннект. |
bulk_too_large | В bulk-сообщении больше 1000 символов в params.symbols. |
unsupported_bulk | Тип не поддерживает массовую подписку через params.symbols (например, marketInfo). |
internal_error | Внутренняя ошибка сервера. |
Для клиентов с большим числом подписок (≥100 тикеров) или с медленным/далёким каналом доступен v2-эндпоинт:
URL: wss://api.dyorplatform.com/publicApi/v2/ws?apiKey=YOUR_API_KEY
Протокол идентичен v1 — те же команды subscribe / unsubscribe / list / ping, те же типы стримов, те же лимиты, те же коды ошибок. Отличие одно: real-time апдейты группируются в батч и отправляются раз в 200 мс одним сообщением. Вместо отдельных сообщений type=update приходит одно сообщение type=batch_update с массивом updates:
{
"type": "batch_update",
"updates": [
{"for": "coinInfo", "params": {"symbol": "btcusdt", "interval": "1m"}, "data": {...}},
{"for": "coinInfo", "params": {"symbol": "ethusdt", "interval": "1m"}, "data": {...}},
{"for": "marketInfo", "params": {"interval": "1m"}, "data": {...}}
]
}Каждый элемент массива updates — то же самое, что приходило бы отдельным сообщением type=update в v1, минус поле type. Схема data для каждого for — та же, что в таблице «Поддерживаемые типы стрима» выше.
Контрольные сообщения (subscribed, bulk_subscribed, subscriptions, error, pong, closing) не батчатся — приходят сразу, как в v1.
Когда переходить на v2: если вы получаете ≥50 апдейтов в секунду или видите дисконнекты с кодом 1006 — батчинг резко снижает количество WebSocket-фреймов и нагрузку на TCP, что устраняет основную причину разрывов на медленных каналах (slow-consumer / высокий RTT / packet loss).
const ws = new WebSocket('wss://api.dyorplatform.com/publicApi/v1/ws?apiKey=YOUR_API_KEY');
ws.onopen = () => {
// Подписка на один тикер
ws.send(JSON.stringify({
action: 'subscribe',
type: 'coinInfo',
params: { symbol: 'btcusdt', interval: '1m' }
}));
// Или массовая подписка — одно сообщение, одно action для rate-limit
ws.send(JSON.stringify({
action: 'subscribe',
type: 'coinInfo',
params: {
interval: '1m',
symbols: ['ethusdt', 'solusdt', 'bnbusdt', 'xrpusdt']
}
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'update' && msg.for === 'coinInfo') {
console.log('New coinInfo tick:', msg.data);
} else if (msg.type === 'bulk_subscribed') {
const ok = msg.results.filter(r => r.status === 'ok').length;
const errors = msg.results.filter(r => r.status === 'error');
console.log(`Bulk subscribed: ${ok}/${msg.results.length}`, errors);
}
};
ws.onclose = (event) => {
console.log('Closed:', event.code, event.reason);
};const ws = new WebSocket('wss://api.dyorplatform.com/publicApi/v2/ws?apiKey=YOUR_API_KEY');
ws.onopen = () => {
ws.send(JSON.stringify({
action: 'subscribe',
type: 'coinInfo',
params: {
interval: '1m',
symbols: ['btcusdt', 'ethusdt', 'solusdt', 'bnbusdt']
}
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'batch_update') {
// Один батч может содержать N апдейтов от разных тикеров/типов
for (const u of msg.updates) {
if (u.for === 'coinInfo') {
console.log(`tick ${u.params.symbol}:`, u.data);
}
}
} else if (msg.type === 'bulk_subscribed') {
const ok = msg.results.filter(r => r.status === 'ok').length;
console.log(`Bulk subscribed: ${ok}/${msg.results.length}`);
}
};
ws.onclose = (event) => {
console.log('Closed:', event.code, event.reason);
};Каждый элемент массива requests — объект с полем type и полем params. Общие обязательные параметры для всех типов:
from — начало диапазона, UNIX timestamp в секундах (long).to — конец диапазона, UNIX timestamp в секундах (long).interval — таймфрейм: 1m, 5m, 15m, 1h, 4h, 1d и т.д.Поле data в каждом результате — массив объектов соответствующего типа, упорядоченный по timestamp. Ниже описаны схемы для всех 13 типов.
coinInfo — данные по монетеСвечи и метрики DYOR по конкретной монете: spot/futures объёмы, ликвидации, глубина стакана.
Доп. параметры: symbol (например, btcusdt).
Ответ: массив CoinData:
timestamp (long, сек) — таймстемп свечи (в JSON как _id).interval (string) — интервал свечи.spotTrade — spot-объёмы: buys, sells (в монете), buysUsdt, sellsUsdt (в USDT), delta, buyTradesCount, sellTradesCount.futuresTrade — то же для futures.futuresLiquidation — totalLiquidatedLong, totalLiquidatedShort (USDT).depths / futuresDepths — массив снимков стакана: percentage, asks, bids, asksUsdt, bidsUsdt, delta. Поле percentage принимает строго одно из значений: 1.5, 3.0, 5.0, 8.0, 15.0, 30.0, 60.0 — других значений в ответе не бывает.{
"_id": 1760081100,
"interval": "1h",
"spotTrade": {
"buys": 125.5, "sells": 98.3,
"buysUsdt": 5650000.0, "sellsUsdt": 4400000.0,
"delta": 27.2, "buyTradesCount": 1520, "sellTradesCount": 1340
},
"futuresTrade": { "buys": 450.0, "sells": 380.0, "buysUsdt": 20250000.0, "sellsUsdt": 17100000.0, "delta": 70.0 },
"futuresLiquidation": { "totalLiquidatedLong": 250000.0, "totalLiquidatedShort": 180000.0 },
"depths": [
{ "percentage": 1.5, "asks": 12.0, "bids": 18.5, "asksUsdt": 540000.0, "bidsUsdt": 832500.0, "delta": 292500.0 }
],
"futuresDepths": []
}marketInfo — рыночные индексыАгрегированные индексы рынка: суммарные spot/futures объёмы, ликвидации, дельты стакана.
Доп. параметры (опц.): totalType — TOTAL, TOTAL2, TOTAL3, TOP100, BOTTOM100. Без него возвращается базовая агрегация.
Ответ: массив TotalData:
timestamp (как _id), interval.delta / futuresDelta — массив дельт стакана по уровням percentage: totalAsks, totalBids, delta, avg. Поле percentage принимает строго одно из значений: 1.5, 3.0, 5.0, 8.0, 15.0, 30.0, 60.0 — других значений в ответе не бывает.totalSpotBuysUsdt, totalSpotSellsUsdt, totalSpotBuyTradesCount, totalSpotSellTradesCount.totalFuturesBuysUsdt, totalFuturesSellsUsdt.totalLiquidatedLong, totalLiquidatedShort (в USDT).{
"_id": 1760081100,
"interval": "1h",
"delta": [
{ "percentage": 1.5, "totalAsks": 450000.0, "totalBids": 520000.0, "delta": 70000.0, "avg": 70000.0 }
],
"futuresDelta": [],
"totalSpotBuysUsdt": 12500000.0,
"totalSpotSellsUsdt": 11800000.0,
"totalSpotBuyTradesCount": 25000,
"totalSpotSellTradesCount": 24000,
"totalFuturesBuysUsdt": 45000000.0,
"totalFuturesSellsUsdt": 42000000.0,
"totalLiquidatedLong": 5000000.0,
"totalLiquidatedShort": 3200000.0
}minervaScreener — Minerva long/shortТайм-серия по количеству long/short монет из скринера Minerva.
Доп. параметры: нет.
Ответ: массив MinervaScreenerItem:
timestamp (long, сек).longCoins (int) — число монет с long-сигналом.shortCoins (int) — число монет с short-сигналом.{ "timestamp": 1760081100, "longCoins": 45, "shortCoins": 38 }funding — funding rateРаспределение монет по категориям funding rate. Только интервал 1h.
Доп. параметры: нет.
Ответ: объект {items: Funding[]}. Каждый Funding:
timestamp (long, сек, в JSON как _id).types — массив категорий: type (higher / standard / lower / negative), coinsCount (int), percentage (double).{
"items": [
{
"_id": 1760081100,
"types": [
{ "type": "higher", "coinsCount": 120, "percentage": 35.2 },
{ "type": "standard", "coinsCount": 150, "percentage": 44.1 },
{ "type": "lower", "coinsCount": 60, "percentage": 17.6 },
{ "type": "negative", "coinsCount": 10, "percentage": 3.1 }
]
}
]
}totalLiquidations — ликвидации (Coinglass)Совокупные ликвидации по рынку с разбивкой по биржам.
Доп. параметры: нет.
Ответ: объект {data: CoinglassLiquidation[]}. Каждый элемент:
_id — таймстемп в миллисекундах.buyQty, sellQty — суммарные объёмы в нативной монете.buyVolUsd, sellVolUsd — объёмы в USD.buyTurnoverNumber, sellTurnoverNumber — число операций.price — цена на момент события.list — массив разбивки по биржам: exchangeName, buyQty, sellQty, buyVolUsd, sellVolUsd, buyTurnoverNumber, sellTurnoverNumber.{
"data": [
{
"_id": 1760081100000,
"buyQty": 125.5, "sellQty": 98.3,
"buyVolUsd": 500000.0, "sellVolUsd": 441350.0,
"buyTurnoverNumber": 42, "sellTurnoverNumber": 35,
"price": 45000.0,
"list": [
{ "exchangeName": "Binance", "buyQty": 75.0, "sellQty": 60.0, "buyVolUsd": 300000.0, "sellVolUsd": 270000.0, "buyTurnoverNumber": 25, "sellTurnoverNumber": 20 }
]
}
]
}askBidAnomalies — аномалии стаканаСчётчик аномалий стакана (ask/bid, spot/futures). Только интервал 1h.
Доп. параметры: нет.
Ответ: объект {items: Anomaly[]}:
timestamp (long, сек).ask (int) — число ask-аномалий (spot).bid (int) — число bid-аномалий (spot).askFutures (int) — число ask-аномалий (futures).bidFutures (int) — число bid-аномалий (futures).{
"items": [
{ "timestamp": 1760081100, "ask": 5, "bid": 3, "askFutures": 2, "bidFutures": 1 }
]
}marginLendingCoin — margin lending по монетеДинамика margin lending по конкретному активу.
Доп. параметры: symbol.
Ответ: массив MarginLendingCoinInterval:
_id — таймстемп (сек), interval, asset (uppercase).borrowed, repaid — взятое/возвращённое в нативной монете; borrowedUsdt, repaidUsdt — в USDT.available — доступный пул (среднее за интервал).handsAmount = borrowed − repaid; handsAmountUsdt в USDT.loanCoefficient = handsAmount / borrowed (риск-метрика).spotVolumeUsdt — спотовый объём за интервал.delta, deltaUsdt, cumulativeDelta, cumulativeDeltaUsdt — изменение и накопительная сумма.cumulativeDeltaOpen/High/Low/Close/Avg и аналогичные *Usdt — OHLC накопительной дельты.marginLendingTotal — суммарный margin lendingАгрегированный margin lending по всему рынку.
Доп. параметры: нет.
Ответ: массив MarginLendingTotalInterval:
_id (сек), interval.totalBorrowedUsdt, totalRepaidUsdt, totalHandsUsdt, totalAvailable.coinsCount (int) — число активных монет в интервале.deltaUsdt, cumulativeDeltaUsdt, cumulativeDeltaUsdtOpen/High/Low/Close/Avg.binanceOpenInterestCoin — open interest по монете (Binance)Доп. параметры: symbol.
Ответ: массив BinanceOpenInterest:
_id — таймстемп (сек).value (double) — open interest на момент таймстемпа.{ "_id": 1760081100, "value": 12500000.0 }binanceOpenInterestTotal — суммарный open interestДоп. параметры: нет.
Ответ: массив того же типа что и binanceOpenInterestCoin; value — сумма по всем монетам.
marketCap — market cap нескольких монетДоп. параметры: symbols — массив строк (например, ["btcusdt", "ethusdt"]).
Ответ: массив MarketCap:
_id — таймстемп (сек).coinData — map {symbol → marketCap}.totalData — map агрегированных метрик (например, total, top100).{
"_id": 1760081100,
"coinData": { "BTC": 1250000000000.0, "ETH": 285000000000.0 },
"totalData": { "total": 2100000000000.0, "top100": 1950000000000.0 }
}marketCapV2 — market cap одной монетыДоп. параметры: symbol.
Ответ: та же схема MarketCap, но coinData содержит только запрошенный символ.
orderHistory — крупные лимитные ордераИстория крупных лимитных ордеров с событиями исполнения.
Доп. параметры: symbol; exchangeType — spot или futures (по умолчанию spot); и либо top (int) — top-N ордеров, либо пара priceRangeStart/priceRangeEnd (double) — фильтр по цене; опционально minQuantityInQuote (double) — минимальный размер ордера в USDT.
Ответ: объект OrderHistoryResponse:
orders — массив LimitOrder.error — строка с ошибкой (пустая если успех).Поля LimitOrder:
_id (string) — идентификатор ордера.side — BID или ASK.price (double) — цена.createdAt, removedAt — таймстемпы создания/удаления (мс).duration (long) — время жизни ордера в мс.coin (string), exchangeType (SPOT/FUTURES).maxQuantity (double) — максимальный объём в нативной монете.maxQuantityInQuoteAsset (double) — максимальный объём в USDT.events — массив событий частичного исполнения: timestamp (мс), quantity (double).{
"orders": [
{
"_id": "order-123456789",
"side": "BID",
"price": 45000.0,
"createdAt": 1760081100000,
"removedAt": 1760081700000,
"duration": 600000,
"coin": "BTC",
"exchangeType": "SPOT",
"maxQuantity": 1.5,
"maxQuantityInQuoteAsset": 67500.0,
"events": [
{ "timestamp": 1760081150000, "quantity": 0.5 },
{ "timestamp": 1760081500000, "quantity": 1.0 }
]
}
],
"error": ""
}Ответ всего batch'а — объект с массивом results, элементы которого соответствуют запросам в исходном порядке. Каждый элемент содержит либо data (полезная нагрузка по схеме конкретного типа из раздела 6), либо error (строка с описанием ошибки). Ошибка одного запроса не отменяет batch — остальные результаты возвращаются как обычно.
{
"results": [
{ "data": [ /* ... */ ], "error": null },
{ "data": null, "error": "Invalid symbol: xxxusdt" }
]
}Дефолтный лимит для ключей, выпущенных через подписку «Доступ к API» — 60 запросов в минуту. На каждый ответ возвращаются заголовки:
X-RateLimit-Limit — общий лимит за окно.X-RateLimit-Remaining — оставшееся число запросов.X-RateLimit-Reset — UNIX timestamp сброса окна.При превышении лимита возвращается код 429 Too Many Requests и JSON-тело с полями error, limit, remaining, reset.
| Код | Когда возвращается |
|---|---|
400 | Невалидный JSON в теле запроса либо неправильная структура batch. |
401 | Отсутствует X-API-Key, ключ невалиден или IP не в whitelist. |
403 | Подписка «Доступ к API» неактивна или на паузе. |
429 | Превышен лимит запросов в минуту (см. раздел «Лимиты»). |
500 | Внутренняя ошибка сервера. Обычно временная — повторите запрос с экспоненциальной задержкой. |