مستندات API

مرجع کامل REST و WebSocket کرای‌هاب — احراز هویت، ساختار داده، و نمونه کد در cURL، Node.js، Python و Go.

شروع کار

مستندات Cryhub API

پلتفرم استریم داده‌های بازار ارز دیجیتال — دسترسی لحظه‌ای از طریق REST و WebSocket با پشتیبانی از چند ارز پایه.

REST Base URLhttps://api.cryhub.io/rest/v1
WebSocket URLwss://api.cryhub.io/ws
با یک ایجنت هوش مصنوعی کار می‌کنید؟ نسخه فشرده و ماشین‌خوان همین مستندات — شامل تمام اندپوینت‌ها، کانال‌ها، ساختار داده‌ها و نکات مهم — به صورت متن ساده در آدرس /llms.txt در دسترس است. به‌جای پیمایش این صفحه، ایجنت را به همان آدرس وصل کنید.
پوشش بازارهای اسپات و پرپچوالسهام · کالا · ارزUSDT · USDC · TMN · AED · EURREST + WebSocket
شروع کار

احراز هویت

هر درخواست نیاز به توکن دسترسی ۳۲ کاراکتری (حروف و اعداد) دارد.

REST — هدر Authorization

curl https://api.cryhub.io/rest/v1/market/ticker?source=s1&quote=usdt&symbols=btc \
  -H "Authorization: Bearer YOUR_32_CHAR_TOKEN"

WebSocket — پارامتر token

const ws = new WebSocket('wss://api.cryhub.io/ws?token=YOUR_32_CHAR_TOKEN');
توکن باید دقیقاً ۳۲ کاراکتر باشد و فقط شامل حروف انگلیسی (a-z, A-Z) و اعداد (0-9) باشد. درخواست بدون توکن یا با توکن نامعتبر با خطای HTTP 401 رد می‌شود.
شروع کار

منابع و نمادها

هر درخواست REST و هر کانال WebSocket به یک source محدود است. هر منبع مجموعه ارزهای پایه مخصوص خود را منتشر می‌کند.

sourceپوششارزهای RESTارزهای WebSocket
s1فید اسپات — رمزارزusdt · tmn · aed · eurusdt · tmn
s2فید پرپچوال — رمزارز، سهام، کالا، شاخص و فارکسusdc · tmnusdc · tmn
AED و EUR فقط از طریق REST در دسترس‌اند. کانالی مانند s1.btcaed.ticker با موفقیت subscribe می‌شود اما هرگز داده‌ای ارسال نمی‌کند. برای این ارزها از REST استفاده کنید. s2 اصلاً از AED و EUR پشتیبانی نمی‌کند.

ارزهای فیات (TMN، AED، EUR) در سمت سرور و با نرخی که هر ۴ ثانیه به‌روز می‌شود تبدیل می‌شوند. تمام قیمت‌ها در پاسخ‌ها از قبل به ارز درخواستی تبدیل شده‌اند و نیازی به تبدیل سمت کلاینت نیست.

قالب نماد

پارامترهای symbols/symbol در REST فقط نماد پایه می‌گیرند؛ اما {pair} در WebSocket برابر پایه + ارز است.

REST       symbols=btc,eth,xrp    → symbol: "btcusdt", "ethusdt", …
WebSocket  s1.btcusdt.ticker      → pair: base + quote (btcusdt, btctmn, …)

# Builder-DEX markets (s2 only) use a <dex>-<coin> prefix
REST       symbols=xyz-tsla,cash-meta  → symbol: "xyz-tslausdc", "cash-metausdc"
WebSocket  s2.xyz-tslausdc.ticker      → pair: <dex>-<coin><quote>

روی s2 هشت DEX پرپچوال، جهان اصلی پرپ را گسترش می‌دهند: xyz · flx · vntl · hyna · km · abcd · cash · para. یک نام سکه می‌تواند روی چند DEX وجود داشته باشد، بنابراین بازارهای DEX همیشه با پیشوند آدرس‌دهی می‌شوند. ترکیب نمادهای پرپ اصلی و DEX در یک درخواست مجاز است و همه اندپوینت‌ها و کانال‌ها برای هر دو یکسان کار می‌کنند. وجود خط تیره در symbol مطمئن‌ترین راه تشخیص آن‌ها در سمت کلاینت است.

فقط دارایی‌های فهرست‌شده فعلی داده برمی‌گردانند. نماد ناشناخته یا حذف‌شده با خطای symbol not found (در REST) یا invalid symbol (هنگام subscribe در WebSocket) رد می‌شود. فهرست نمادها هر ساعت به‌روز می‌شود؛ کانال‌های سراسری top_mover از این بررسی مستثنا هستند.
شروع کار

ساختار پاسخ REST

تمام پاسخ‌های REST در یک پوشش مشترک قرار می‌گیرند:

200 OK
{
  "data":        /* main payload — array or object */,
  "next_cursor": 1711612800000,  // kline + trade only, when data is non-empty
  "message":     "ok",           // always present; error text on failure
  "success":     true,           // present on success only
  "ts":          1711612800000   // server time, Unix ms
}

در پاسخ خطا کد HTTP 4xx/5xx برمی‌گردد و فیلد "success" حذف می‌شود — کد HTTP را به‌عنوان سیگنال اصلی خطا در نظر بگیرید؛ "message" توضیح خطا را دارد.

صفحه‌بندی

اندپوینت‌های kline و trade مقدار next_cursor را برای صفحه‌بندی cursor-based برمی‌گردانند — آن را به عنوان end_time درخواست بعدی ارسال کنید تا صفحه قبلی را دریافت کنید.

next_cursor برابر قدیمی‌ترین زمان در صفحه فعلی است و وقتی data خالی باشد ارسال نمی‌شود. /market/detail هرگز آن را برنمی‌گرداند — آن اندپوینت را یک snapshot در نظر بگیرید.

حذف مقادیر صفر

فیلدهای عددی با مقدار صفر ممکن است به‌کلی حذف شوند — چه در پاسخ REST و چه در tick وب‌سوکت. مثلاً یک kline tick تازه بدون معامله به شکل { symbol, ts, open, high, low, close } و بدون vol، amount و count می‌رسد. همیشه فیلد عددی غایب را 0 در نظر بگیرید.
REST API

GET /market/ticker

GET/rest/v1/market/ticker

تیکر ۲۴ ساعته برای یک یا چند نماد. شامل قیمت باز، بسته، بالا، پایین، حجم، و بهترین قیمت خرید/فروش.

پارامترها

پارامتراجباریمقادیرتوضیح
sourcerequireds1 · s2فید اسپات (s1) یا فید پرپچوال (s2)
quoterequireds1: usdt · tmn · aed · eur
s2: usdc · tmn
ارز پایه برای قیمت‌گذاری
symbolsrequiredمثال: btc,eth,xrpنمادهای پایه با کاما جدا شده (حروف کوچک)

نمونه درخواست

curl "https://api.cryhub.io/rest/v1/market/ticker?source=s1&quote=usdt&symbols=btc,eth,xrp" \
  -H "Authorization: Bearer YOUR_TOKEN"

نمونه پاسخ

200 OK
{
  "data": [
    {
      "symbol":     "btcusdt",
      "open":       65000.0,
      "high":       67000.0,
      "low":        64500.0,
      "close":      66500.0,
      "last_price": 66500.0,
      "bid":        66490.0,
      "bid_size":   0.5,
      "ask":        66510.0,
      "ask_size":   0.3,
      "last_size":  0.1,
      "vol":        1234.56,
      "amount":     85432000.0,
      "count":      142300
    }
  ],
  "message": "ok",
  "success": true,
  "ts": 1711612800000
}

symbol = پایه + ارز. مثلاً با quote=tmn و symbols=btc مقدار symbol برابر btctmn است.

REST API

GET /market/detail

GET/rest/v1/market/detail

اطلاعات بازار ۲۴ ساعته شامل قیمت، تغییر، حجم و درصد تغییر. داده‌ها از تاریخچه Kline استخراج می‌شوند.

پارامترها

پارامتراجباریمقادیرپیش‌فرض
sourcerequireds1 · s2
quoterequireds1: usdt · tmn · aed · eur
s2: usdc · tmn
symbolsrequiredbtc,eth
slicerequiredدوره Kline — مرجع
sizeoptional1–2000500
start_timeoptionalUnix ms
end_timeoptionalUnix ms

برای هر کندل و هر نماد یک ردیف detail تولید می‌شود؛ بنابراین این اندپوینت همان پارامترها و همان چهار حالت کوئری /market/kline را دارد و فیلدهای محاسبه‌شده change و change_percent را اضافه می‌کند.

این اندپوینت هرگز next_cursor برنمی‌گرداند — آن را یک snapshot در نظر بگیرید. رایج‌ترین کاربرد، size=1 همراه با slice=1day است که قیمت فعلی و آمار ۲۴ ساعته هر نماد را در یک درخواست می‌دهد.

نمونه

# Latest 30 daily candles for BTC and ETH in TMN
curl "https://api.cryhub.io/rest/v1/market/detail?source=s1&quote=tmn&symbols=btc,eth&slice=1day&size=30" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Specific time range
curl "https://api.cryhub.io/rest/v1/market/detail?source=s1&quote=usdt&symbols=btc&slice=1hour&start_time=1711526400000&end_time=1711612800000" \
  -H "Authorization: Bearer YOUR_TOKEN"

نمونه پاسخ

200 OK
{
  "data": [
    {
      "symbol":         "btctmn",
      "price":          4056500000.0,
      "change":         91500000.0,
      "high":           4087000000.0,
      "low":            3935500000.0,
      "volume_quote":   5185000000000.0,
      "change_percent": 2.31,
      "volume":         1234.56,
      "count":          142300
    }
  ],
  "message": "ok", "success": true, "ts": 1711612800000
}
REST API

GET /market/kline

GET/rest/v1/market/kline

داده‌های کندل‌استیک (OHLCV) برای یک یا چند نماد. پشتیبانی از ۴ حالت کوئری و صفحه‌بندی.

پارامترها

پارامتراجباریمقادیرپیش‌فرض
sourcerequireds1 · s2
quoterequireds1: usdt · tmn · aed · eur
s2: usdc · tmn
symbolsrequiredbtc,eth
slicerequired1min · 5min · 15min · 30min · 60min · 4hour · 1day · 1week · 1mon
sizeoptional1–2000500
start_timeoptionalUnix ms — شامل
end_timeoptionalUnix ms — غیرشامل
مقدار slice=1year در هیچ منبعی از REST پشتیبانی نمی‌شود و خطای HTTP 400 برمی‌گرداند. برای کندل سالانه از کانال s1.{pair}.kline.1y در WebSocket استفاده کنید — s2 اصلاً بازه سالانه ندارد.

حالت‌های کوئری

حالتپارامترهاترتیبکاربرد
Asizeجدیدترین اولبارگذاری اولیه نمودار
Bsize + end_timeقدیمی‌ترین اولاسکرول به چپ / صفحه‌بندی به عقب
Csize + start_timeقدیمی‌ترین اولپرش به تاریخ مشخص — پنجره رو به جلو
Dstart_time + end_timeقدیمی‌ترین اولبازه ثابت — سقف ۲۰۰۰ کندل
نکته حیاتی برای نمودار: حالت A داده را از جدید به قدیم برمی‌گرداند. پیش از دادن آرایه به کتابخانه نمودار آن را معکوس کنید تا کندل‌ها از قدیم به جدید رسم شوند. صفحه‌های بعدی (حالت B) از قبل از قدیم به جدید هستند و مستقیم prepend می‌شوند. ترتیب در هر دو منبع یکسان است. ترکیب size با هر دوی start_time و end_time رد می‌شود.

نمونه درخواست

# 60 1-minute BTC/TMN candles
curl "https://api.cryhub.io/rest/v1/market/kline?source=s1&quote=tmn&symbols=btc&slice=1min&size=60" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Older page via cursor (backward pagination)
curl "https://api.cryhub.io/rest/v1/market/kline?source=s1&quote=usdt&symbols=btc&slice=1day&size=100&end_time=1711526400000" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Exact time window
curl "https://api.cryhub.io/rest/v1/market/kline?source=s1&quote=usdt&symbols=btc&slice=1hour&start_time=1711526400000&end_time=1711612800000" \
  -H "Authorization: Bearer YOUR_TOKEN"

نمونه پاسخ

200 OK
{
  "data": [
    {
      "symbol": "btcusdt",
      "slice":  "1day",
      "ts":     1711526400000,  // candle timestamp, Unix ms — see note below
      "open":   65000.0,
      "high":   67000.0,
      "low":    64500.0,
      "close":  66500.0,
      "vol":    1234.56,        // quote volume (converted to the quote param)
      "amount": 85432000.0,     // base volume (coin units, not converted)
      "count":  142300
    }
  ],
  "next_cursor": 1711526400000,
  "message": "ok", "success": true, "ts": 1711612800000
}
قرارداد زمان در دو منبع متفاوت است. در s1 مقدار ts زمان باز شدن کندل و هم‌تراز با بازه است. در s2 این مقدار لحظه بسته شدن منهای ۱ میلی‌ثانیه است. صفحه‌بندی و تطبیق کندل در هر دو یکسان کار می‌کند — فقط همیشه از ts به‌عنوان کلید کندل استفاده کنید و در s2 فرض نکنید که ts % interval === 0 است.

در حالت چندنمادی، تمام کندل‌ها در یک آرایه data می‌آیند — پیش از رسم، آن‌ها را بر اساس symbol گروه‌بندی کنید. مقدار next_cursor کمترین ts در میان همه نمادهاست؛ پس برای همه از همان end_time استفاده کنید تا صفحه‌ها هم‌تراز بمانند. وقتی data.length < size شد، صفحه‌بندی را متوقف کنید.

REST API

GET /market/depth

GET/rest/v1/market/depth

اسنپ‌شات کتاب سفارشات (Order Book) برای یک نماد. پشتیبانی از ۶ سطح جمع‌بندی.

پارامترها

پارامتراجباریمقادیرپیش‌فرض
sourcerequireds1 · s2
quoterequireds1: usdt · tmn · aed · eur
s2: usdc · tmn
symbolrequiredbtc
stepoptionalstep0–step5step0
سطوح جمع‌بندی Depth
step (REST)agg (WebSocket)توضیح
step0agg0کتاب سفارش خام — بدون جمع‌بندی
step1agg1قیمت‌ها با ۱ رقم اعشار
step2agg2قیمت‌ها با ۲ رقم اعشار
step3agg3قیمت‌ها گرد شده به عدد صحیح
step4agg4قیمت‌ها گرد شده به مضرب ۱۰
step5agg5قیمت‌ها گرد شده به مضرب ۱۰۰ — بیشترین جمع‌بندی

نمونه درخواست

curl "https://api.cryhub.io/rest/v1/market/depth?source=s1&quote=usdt&symbol=btc&step=step0" \
  -H "Authorization: Bearer YOUR_TOKEN"

نمونه پاسخ

200 OK
{
  "data": {
    "symbol":  "btcusdt",
    "ts":      1711612800000,
    "version": 123456789,
    "bids": [
      { "price": 66490.0, "qty": 0.5 },
      { "price": 66480.0, "qty": 1.2 }
    ],
    "asks": [
      { "price": 66510.0, "qty": 0.3 },
      { "price": 66520.0, "qty": 0.9 }
    ]
  },
  "message": "ok", "success": true, "ts": 1711612800000
}

bids به صورت نزولی و asks به صورت صعودی قیمت مرتب‌اند. مقدار version شماره ترتیب صرافی است — برای تشخیص snapshot قدیمی از آن استفاده کنید.

ساختار depth در REST و WebSocket یکسان نیست. REST آبجکت‌های { price, qty } برمی‌گرداند اما کانال depth در WebSocket آرایه‌های [price, qty] می‌فرستد. اگر کتاب سفارش را با REST مقداردهی اولیه و سپس با سوکت زنده نگه می‌دارید، تبدیل را در نظر بگیرید.
REST API

GET /market/trade

GET/rest/v1/market/trade

معاملات اخیر برای یک نماد. برای داده لحظه‌ای از کانال WebSocket استفاده کنید.

پارامترها

پارامتراجباریمقادیرپیش‌فرض
sourcerequireds1 · s2
quoterequireds1: usdt · tmn · aed · eur
s2: usdc · tmn
symbolrequiredethفقط یک نماد پایه در هر درخواست
sizeoptional1–2000500
start_timeoptionalUnix ms — شامل
end_timeoptionalUnix ms — غیرشامل
تاریخچه معاملات همان چهار حالت کوئری kline را دارد، اما فیلتر زمانی در حافظه و روی حدود ۲۰۰۰ دسته اخیر اعمال می‌شود — یعنی صفحه‌بندی cursor به همین بازه محدود است. برای تاریخچه پیوسته از کانال trade در WebSocket استفاده کنید.

نمونه درخواست

curl "https://api.cryhub.io/rest/v1/market/trade?source=s1&quote=aed&symbol=eth&size=50" \
  -H "Authorization: Bearer YOUR_TOKEN"

نمونه پاسخ

200 OK
{
  "data": [
    {
      "symbol": "ethaed",
      "id":     987654321,
      "ts":     1711612800000,
      "data": [
        {
          "price":     12300.0,
          "amount":    0.5,
          "direction": "buy",
          "ts":        1711612800000
        }
      ]
    }
  ],
  "next_cursor": 1711612800000,
  "message": "ok", "success": true, "ts": 1711612800000
}

هر batch یک یا چند معامله در آرایه data خودش دارد. مقدار direction برابر "buy" است وقتی taker خریدار بوده و "sell" وقتی taker فروشنده بوده است. next_cursor برابر ts قدیمی‌ترین batch صفحه است.

REST API

GET /market/top-mover

GET/rest/v1/market/top-mover

فهرست کنونی بیشترین رشد، بیشترین افت، یا بالاترین حجم. هر حدود ۳ ثانیه بازمحاسبه می‌شود و مرتب‌شده و حداکثر تا ۲۵ نماد برمی‌گردد.

پارامترها

پارامتراجباریمقادیرتوضیح
sourcerequireds1 · s2فید اسپات (s1) یا فید پرپچوال (s2)
currencyrequireds1: usdt · tmn
s2: usdc · tmn
نام این پارامتر «quote» نیست
typerequiredgainer · loser · volume
این تنها اندپوینتی است که به‌جای quote پارامتر currency می‌گیرد.
typeترتیب مرتب‌سازی
gainerنزولی بر اساس change_percent
loserصعودی بر اساس change_percent
volumeنزولی بر اساس quote_volume

نمونه درخواست

curl "https://api.cryhub.io/rest/v1/market/top-mover?source=s1&currency=usdt&type=gainer" \
  -H "Authorization: Bearer YOUR_TOKEN"

نمونه پاسخ

200 OK
{
  "data": [
    {
      "symbol":         "btcusdt",
      "price":          79124.07,
      "change":         1580.25,
      "quote_volume":   240482890.81,
      "change_percent": 2.04,
      "volume":         2974.03
    }
  ],
  "message": "ok", "success": true, "ts": 1711612800000
}

در s2 رتبه‌بندی، سکه‌های پرپ اصلی و سکه‌های DEX را با هم ادغام می‌کند. اگر فقط یکی را می‌خواهید، در سمت کلاینت بر اساس وجود خط تیره در symbol فیلتر کنید.

REST API

GET /health

GET/health

بررسی در دسترس بودن سرویس در ریشه دامنه — توجه کنید که زیر /rest/v1 نیست و آنجا خطای ۴۰۴ می‌دهد. پاسخ HTTP 200 با بدنه متنی ok و بدون پوشش JSON است.

curl -i https://api.cryhub.io/health
# HTTP/1.1 200 OK
# ok
پاسخ ۵۰۲، ۵۰۳ یا timeout یعنی سرویس از دسترس خارج، پرفشار یا غیرقابل‌دسترسی است. این بررسی فقط در دسترس بودن لایه بیرونی را می‌سنجد و خط لوله داده پشت آن را بررسی نمی‌کند. برای load-balancer و مانیتورینگ آپ‌تایم مناسب است.
WebSocket API

WebSocket — اتصال

URLwss://api.cryhub.io/ws?token=YOUR_32_CHAR_TOKEN

بلافاصله پس از اتصال، سرور پیام خوش‌آمد ارسال می‌کند:

Server → Client (on connect)
{ "msg": "Connected to Cryhub Stream", "ts": 1711612800000 }

مثال کامل اتصال

const ws = new WebSocket('wss://api.cryhub.io/ws?token=YOUR_TOKEN');

ws.onopen = () => {
  ws.send(JSON.stringify({
    action: 'sub',
    channels: [
      's1.btcusdt.ticker',
      's1.btcusdt.kline.1m',
      's1.btcusdt.depth.agg0',
      's1.usdt.global.top_mover.gainer'
    ]
  }));
};

ws.onmessage = ({ data }) => {
  const msg = JSON.parse(data);

  // Reply to server ping
  if (msg.ping) {
    ws.send(JSON.stringify({ action: 'pong', data: { pong: String(msg.ping) } }));
    return;
  }

  // Market data
  if (msg.ch) {
    console.log(`[${msg.ch}]`, msg.tick, msg.ts);
  }
};

ws.onerror  = (e) => console.error('WS error', e);
ws.onclose  = (e) => console.log('WS closed', e.code);
WebSocket API

WebSocket — پروتکل

پیام‌های Client → Server

actionتوضیح
subاشتراک در یک یا چند کانال
unsubلغو اشتراک از کانال‌ها
pongپاسخ به ping سرور — باید timestamp را به صورت string ارسال کنید
{
  "action": "sub",
  "channels": [
    "s1.btcusdt.ticker",
    "s1.btctmn.ticker",
    "s1.btcusdt.kline.1m",
    "s1.btcusdt.depth.agg0",
    "s1.usdt.global.top_mover.gainer"
  ]
}

پیام‌های Server → Client

فیلدتوضیح
chنام کانال — در پیام‌های داده و تأییدیه اشتراک
tickداده بازار — ساختار بسته به نوع کانال متفاوت است
pingمقدار غیرصفر هنگام heartbeat — باید با pong پاسخ دهید
msgمتن سیستمی، تأییدیه اشتراک، یا پیام خطا
tsزمان سرور — Unix milliseconds
Ping/Pong — Heartbeat

سرور هر ۳۰ ثانیه یک ping ارسال می‌کند. پس از ۳ ping بی‌پاسخ اتصال قطع می‌شود.

Server Ping
{ "ping": 1711612830000, "ts": 1711612830000 }
تأییدیه اشتراک
Sub/Unsub ACK
{ "ch": "s1.btcusdt.ticker,s1.btctmn.ticker", "msg": "sub", "ts": 1711612800000 }
WebSocket API

WebSocket — کانال‌ها

{source}.{pair}.{stream}[.{arg}]              — per-pair streams
{source}.{currency}.global.top_mover.{type}  — global top movers
کانالنحوه تحویلتوضیح
s1.{pair}.tickerهمیشه‌فعالتیکر ۲۴ ساعته
s2.{pair}.tickerهمیشه‌فعالتیکر ۲۴ ساعته — با آستانه تغییر ۰٫۰۱٪
s1.{pair}.detailهمیشه‌فعالجزئیات بازار ۲۴ ساعته
s2.{pair}.detailهمیشه‌فعالجزئیات بازار ۲۴ ساعته
s1.{pair}.bboهمیشه‌فعالبهترین قیمت خرید/فروش
s2.{pair}.bboLazyبهترین قیمت خرید/فروش — منبع مشترک با depth
s1.{pair}.tradeهمیشه‌فعالدسته‌های معاملات انجام‌شده
s2.{pair}.tradeLazyدسته‌های معاملات انجام‌شده
s1.{pair}.kline.{tf}Lazytf: 1m · 5m · 15m · 30m · 60m · 4h · 1d · 1w · 1mo · 1y
s2.{pair}.kline.{tf}Lazytf: 1m · 5m · 15m · 30m · 60m · 4h · 1d · 1w · 1mo
s1.{pair}.depth.{agg}Lazyagg: agg0–agg5
s2.{pair}.depth.{agg}Lazyagg: agg0–agg5 — همه سطوح یک منبع مشترک دارند
s1.{currency}.global.top_mover.{type}همیشه‌فعالcurrency: usdt · tmn — type: gainer · loser · volume
s2.{currency}.global.top_mover.{type}همیشه‌فعالcurrency: usdc · tmn — type: gainer · loser · volume
کانال‌های Lazy اتصال upstream را با اولین subscriber باز و پس از آخرین unsubscribe آزاد می‌کنند؛ بنابراین اولین فریم ممکن است حدود ۲۰۰ میلی‌ثانیه طول بکشد. کانال‌های همیشه‌فعال پیوسته داده می‌فرستند.

pair = نماد پایه + ارز: btcusdt · btctmn (s1) · btcusdc · xyz-tslausdc · cash-metausdc (s2)

روی s1 فقط usdt و tmn و روی s2 فقط usdc و tmn از طریق WebSocket منتشر می‌شوند. جفت‌های AED و EUR — از جمله top_mover — subscribe را می‌پذیرند اما هرگز داده‌ای نمی‌فرستند. این ارزها را با REST بگیرید.
WebSocket API

WebSocket Ticker

کانال‌ها: s1.{pair}.ticker · s2.{pair}.ticker

پیام دریافتی
{
  "ch": "s1.btcusdt.ticker",
  "tick": {
    "symbol":     "btcusdt",
    "open":       65000.0,
    "high":       67000.0,
    "low":        64500.0,
    "close":      66500.0,
    "last_price": 66500.0,
    "bid":        66490.0,
    "bid_size":   0.5,
    "ask":        66510.0,
    "ask_size":   0.3,
    "last_size":  0.1,
    "vol":        1234.56,
    "amount":     85432000.0,
    "count":      142300
  },
  "ts": 1711612800000
}
در s2: مقادیر OHLC از آخرین snapshot کندل می‌آید و ممکن است کمی از قیمت میانی زنده عقب باشد؛ bid، ask و last_price بر پایه قیمت میانی محاسبه می‌شوند؛ فیلدهای حجم و اندازه در صورت صفر بودن حذف می‌شوند؛ و فریم‌ها تنها با تغییر ۰٫۰۱ درصدی قیمت منتشر می‌شوند (تقریباً هر ۱ تا ۳ ثانیه).
WebSocket API

WebSocket Market Detail

کانال‌ها: s1.{pair}.detail · s2.{pair}.detail. نام فیلدها دقیقاً مانند REST /market/detail است و مقادیر high، low، volume_quote و volume برای بازه ۲۴ ساعته هستند.

پیام دریافتی
{
  "ch": "s1.btcusdt.detail",
  "tick": {
    "symbol":         "btcusdt",
    "price":          66500.0,
    "change":         1500.0,
    "high":           67000.0,
    "low":            64500.0,
    "volume_quote":   85000000.0,
    "change_percent": 2.31,
    "volume":         1234.56
  },
  "ts": 1711612800000
}
WebSocket API

WebSocket BBO

کانال‌ها: s1.{pair}.bbo · s2.{pair}.bbo — یک شاخص سبک اسپرد که با هر تغییر در بالای کتاب سفارش به‌روز می‌شود. اگر فقط اسپرد را لازم دارید، به‌جای ticker از این استفاده کنید.

پیام دریافتی
{
  "ch": "s1.btcusdt.bbo",
  "tick": {
    "symbol":   "btcusdt",
    "bid":      66490.0,
    "ask":      66510.0,
    "bid_size": 0.5,
    "ask_size": 0.3
  },
  "ts": 1711612800000
}
WebSocket API

WebSocket Kline

کانال‌ها: s1.{pair}.kline.{tf} · s2.{pair}.kline.{tf}. هر فریم کندل در حال تشکیل فعلی است که با هر معامله به‌روز می‌شود — برای کندل‌های بسته‌شده و تاریخی از REST /market/kline استفاده کنید. این کانال Lazy است.

timeframe‌های مجاز: 1m · 5m · 15m · 30m · 60m · 4h · 1d · 1w · 1mo · 1yمقدار 1y فقط در WebSocket و فقط روی s1 کار می‌کند؛ s2.*.kline.1y هنگام subscribe رد می‌شود.
پیام دریافتی
{
  "ch": "s1.btcusdt.kline.1m",
  "tick": {
    "symbol": "btcusdt",
    "ts":     1711612800000,
    "open":   66000.0,
    "high":   66800.0,
    "low":    65900.0,
    "close":  66500.0,
    "vol":    12.34,
    "amount": 815481.0,
    "count":  320
  },
  "ts": 1711612800000
}
منطق به‌روزرسانی کندل
if (tick.ts === currentBar.ts) {
  // same candle — update close/high/low/vol/amount/count in place
  updateBar(tick);
} else if (tick.ts > currentBar.ts) {
  // a new candle opened — append it
  appendBar(tick);
}

// tick.ts is in MILLISECONDS. Chart libraries that expect seconds
// (e.g. Lightweight Charts) need tick.ts / 1000.
// vol / amount / count are omitted when zero — default them.
مقدار ts با ts کندل REST همان منبع یکسان است و مشخص می‌کند کدام کندل باید به‌روز شود — اما به تفاوت قرارداد توجه کنید: s1 زمان باز شدن کندل و s2 لحظه بسته شدن منهای ۱ میلی‌ثانیه را می‌فرستد.
WebSocket API

WebSocket Depth

کانال‌ها: s1.{pair}.depth.{agg} · s2.{pair}.depth.{agg}؛ مقادیر agg0 تا agg5 دقیقاً متناظر با step0 تا step5 در REST هستند. این کانال Lazy است.

هر فریم یک snapshot کامل است، نه تغییرات افزایشی — با هر پیام کل کتاب سفارش محلی را جایگزین کنید.
پیام دریافتی
{
  "ch": "s1.btcusdt.depth.agg0",
  "tick": {
    "symbol": "btcusdt",
    "bids": [[66490.0, 0.5], [66480.0, 1.2]],
    "asks": [[66510.0, 0.3], [66520.0, 0.9]]
  },
  "ts": 1711612800000
}

هر entry آرایه‌ای دو عنصری است: [price, quantity]

WebSocket API

WebSocket Trade

کانال‌ها: s1.{pair}.trade · s2.{pair}.trade — معاملات اجراشده به صورت لحظه‌ای. معاملات جدید را به ابتدای فهرست اضافه کنید و طول فهرست را محدود نگه دارید تا مصرف حافظه بی‌حد رشد نکند.

پیام دریافتی
{
  "ch": "s1.btcusdt.trade",
  "tick": {
    "trades": [
      {
        "symbol":    "btcusdt",
        "price":     66500.0,
        "amount":    0.15,
        "direction": "buy",
        "ts":        1711612800000
      }
    ]
  },
  "ts": 1711612800000
}
WebSocket API

WebSocket Top Mover

فرمت کانال: {source}.{currency}.global.top_mover.{type}

منبعارزهاتوضیح
s1usdt · tmnکانال‌های aed/eur وجود دارند اما داده‌ای نمی‌فرستند
s2usdc · tmnنمادهای پرپ اصلی و DEX را در یک رتبه‌بندی ادغام می‌کند؛ حداقل حجم روزانه ۱۰٬۰۰۰ دلار
typeتوضیح
gainer۲۵ سکه با بیشترین رشد درصدی ۲۴ ساعته
loser۲۵ سکه با بیشترین افت درصدی ۲۴ ساعته
volume۲۵ سکه با بیشترین حجم معاملات ۲۴ ساعته
این تنها خانواده کانالی است که tick آن یک آرایه است و تنها موردی که نام فیلدهای کوتاه دارد. بقیه کانال‌ها کلیدهای بلند می‌فرستند — برای آن‌ها fallback کلید کوتاه اضافه نکنید. فهرست‌ها هر حدود ۳ ثانیه بازمحاسبه می‌شوند.
پیام دریافتی — tick یک آرایه است
{
  "ch": "s1.usdt.global.top_mover.gainer",
  "tick": [
    {
      "sym": "shibusdt",
      "p":   0.00002845,    // price
      "c":   0.00000412,    // 24h change
      "qv":  985400000.0,   // 24h quote volume
      "prt": 16.93,         // 24h percent change
      "v":   34600000000.0  // 24h base volume
    }
  ],
  "ts": 1711612800000
}
مرجع

دوره‌های Kline

REST (slice)WebSocket (timeframe)توضیح
1min1m۱ دقیقه
5min5m۵ دقیقه
15min15m۱۵ دقیقه
30min30m۳۰ دقیقه
60min60m۱ ساعت
4hour4h۴ ساعت
1day1dروزانه
1week1wهفتگی
1mon1moماهانه
1yسالانه — فقط WebSocket و فقط روی s1
معادل REST برای 1y وجود ندارد: slice=1year روی هر دو منبع خطای HTTP 400 می‌دهد و s2.*.kline.1y هنگام subscribe رد می‌شود.
مرجع

ارزهای پشتیبانی‌شده

کدناممنابعدسترسی
usdtTethers1REST و WebSocket — بومی، بدون تبدیل
usdcUSD Coins2REST و WebSocket — بومی، بدون تبدیل
tmnتومان ایرانیs1 · s2REST و WebSocket — تبدیل در سمت سرور
aedدرهم اماراتs1فقط REST — روی WebSocket منتشر نمی‌شود
eurیوروs1فقط REST — روی WebSocket منتشر نمی‌شود
ارزهای فیات در سمت سرور از ارز بومی تبدیل می‌شوند و نرخ‌ها هر ۴ ثانیه به‌روز می‌شوند. قیمت‌ها از قبل تبدیل‌شده می‌رسند و نیازی به محاسبه در سمت کلاینت نیست. اگر دریافت نرخ قطع شود، آخرین نرخ معتبر همچنان اعمال می‌شود.
مرجع

خطاها

HTTPmessageعلت
400source X is not supportedمنبع نامعتبر — از s1 یا s2 استفاده کنید
400symbols is requiredپارامتر symbols ارسال نشده
400quote is requiredپارامتر quote ارسال نشده
400quote not supported for this sourceمثلاً aed روی s2
400invalid slice for this provider: "1year"این slice در این منبع پشتیبانی نمی‌شود
400invalid size: N, accepted range 1 to 2000size خارج از بازه مجاز
400cannot combine size with both start_time and end_timeترکیب نامجاز پارامترها
400start_time must be earlier than end_timeبازه زمانی اشتباه
400invalid step "X", accepted: step0..step5step نامعتبر
400type "X" is not supported; valid values: gainer, loser, volumeمقدار type در top-mover نامعتبر
401unauthorized(invalid token)توکن نامعتبر یا فرمت اشتباه
401unauthorized(token required)توکن ارسال نشده
500symbol not found: xyzنماد ناشناخته یا حذف‌شده
500failed to fetch market dataخطای upstream یا سرور

نمونه پاسخ خطا

پاسخ‌های خطا با کد HTTP 4xx/5xx برمی‌گردند و فیلد "success" در آن‌ها حذف می‌شود. کد HTTP را به عنوان سیگنال اصلی خطا در نظر بگیرید.

400 Bad Request
{
  "message": "start_time must be earlier than end_time",
  "ts":      1711612800000
}

پیام‌های خطای WebSocket

خطاهای سوکت به صورت یک فریم ساده msg و بدون ch می‌رسند.

Server Error Messages
{ "msg": "invalid action: foo",     "ts": 1711612800000 }
{ "msg": "channels are empty",      "ts": 1711612800000 }
{ "msg": "invalid source: s9",      "ts": 1711612800000 }
{ "msg": "invalid symbol: foousdt", "ts": 1711612800000 }
{ "msg": "failed to sub: ...",      "ts": 1711612800000 }
{ "msg": "ping timeout. connection closed.", "ts": 1711612800000 }