System and metadata
Five routes that serve no market metric: they say whether the service answers, whether the data is fresh, which assets exist, what each one can actually serve, and what your key may do.
An AI agent asks the same questions through one MCP tool: get_system_info returns the health of the service and your plan (families, history depth, rate, remaining quota) without using your quota, and on demand the served pairs and the freshness of the data. See the MCP server.
#Health of the service
All 1 fields of this route (from the contract)
database | `connected` when the service reaches its database. A failing check answers 503 `service_unavailable` with `database` in `error.details`. |
The probe. It says whether the service is up and whether its database answers. It is the only route that answers without a key, and it is never counted against the quota, which makes it the point a monitoring system can query without consuming anything.
{
"status": "ok",
"server_time": "2026-11-08T12:51:13.156Z",
"data_type": "health",
"data": {
"database": "connected"
}
}In case of a problem: 503 with the error body (error.code: "service_unavailable", and database: "unreachable", service and retry_after_s under error.details), and the Retry-After header.
#Freshness of the feeds
All 15 fields of this route (from the contract)
computed_at | ISO 8601 UTC, milliseconds (2026-09-28T14:00:00.000Z) | When the status was measured: the OLDEST of its measurements (each data family is measured on its own, cached up to 5 minutes for market feeds and 30 seconds for the others). Every `age_s` is measured at or after this instant, not at `server_time`. |
state | `ok`, or `degraded` when at least one feed is stale or failed its check. The envelope's `status` stays `ok` (the request succeeded). | |
feed_count | count | Public feeds checked. |
stale_feed_count | count | Feeds older than their threshold. |
error_feed_count | count | Feeds that could not be checked. |
max_age_s | seconds | Age of the oldest feed. |
feeds | One row per public feed. | |
feeds.feed | Public feed name. The closed list of this contract version; `routes` gives the routes each one supplies. | |
feeds.family | Data family the feed belongs to, as in `/v1/limits` and the `x-family` of each route: `price_volume`, `derivatives`, `microstructure`, `trades`, `options`, `onchain`, `macro`, `etf`, `tokenomics` or `sentiment`. | |
feeds.routes | The public routes (contract paths) this feed supplies: watch this feed to know whether they are fresh. A per-timeframe feed (`cvd_1h`) supplies them at that timeframe. | |
feeds.age_s | seconds | Age of the latest row of the feed. For a feed made of several series (one per asset, per macro series, per ETF), the age of its OLDEST series. For the market-hours intraday series (`macro_intraday_<tf>`, not `_continuous`), counted on weekdays only, like their threshold. `null` if the feed is empty or could not be checked. |
feeds.expected_interval_s | seconds | Maximum legitimate age of the feed. |
feeds.threshold_s | seconds | Age above which the feed is stale (1.5 × expected_interval_s). |
feeds.is_stale | Whether the feed is stale: older than `threshold_s`, or (series feed) at least one of its series is. `null` when the feed could not be checked (counted in `error_feed_count`). | |
feeds.stale_venue_count | count | Venues lagging on this feed; `null` when the feed is not split by venue (every non-market feed). |
One line per data feed, under its public name: its age, the rhythm at which it is expected to publish, and an is_stale flag computed server-side. The rule is the same for every feed: a feed is late when it has not delivered for 1.5 × its expected rhythm. No internal table, no venue name, no row count. It is the route to query before building an analysis: knowing that data is old is better than discovering it in a result. It covers every family: prices and volumes, derivatives, order flow, trades, and also options, on-chain, macro, ETF, tokenomics and sentiment. A slow series is not a late one: a monthly macro series or a quarterly ETF filing legitimately reaches an age of weeks, and its expected_interval_s says so.
{
"status": "ok",
"server_time": "2026-11-08T12:51:14.698Z",
"data_type": "status",
"data": {
"computed_at": "2026-11-08T12:51:13.669Z",
"state": "ok",
"feed_count": 82,
"stale_feed_count": 0,
"error_feed_count": 0,
"max_age_s": 7649473.7,
"feeds": [
{
"feed": "klines_futures_1m",
"family": "price_volume",
"routes": [
"/v1/klines",
"/v1/klines/history"
],
"age_s": 73.7,
"expected_interval_s": 120,
"threshold_s": 180,
"is_stale": false,
"stale_venue_count": 0
},
{
"feed": "klines_1m",
"family": "price_volume",
"routes": [
"/v1/klines",
"/v1/klines/history"
],
"age_s": 73.7,
"expected_interval_s": 180,
"threshold_s": 270,
"is_stale": false,
"stale_venue_count": 0
},
{
"feed": "klines_multi",
"family": "price_volume",
"routes": [
"/v1/klines",
"/v1/klines/history"
],
"age_s": 373.7,
"expected_interval_s": 660,
"threshold_s": 990,
"is_stale": false,
"stale_venue_count": null
}
]
}
}| Field | Type | Description |
|---|---|---|
status | string | Always ok when the request succeeded; the state of the feeds is data.state. |
server_time | string | The instant the response was produced, in ISO 8601 UTC with milliseconds. |
data.computed_at | string | When the status was measured: the oldest of its measurements (market feeds are cached up to five minutes, the other families thirty seconds). Every age_s is measured at or after this instant, not at server_time. |
data.state | string | ok, or degraded as soon as a feed is late or its check has failed. |
data.feed_count | integer | Number of feeds checked. |
data.stale_feed_count | integer | Number of feeds late. |
data.error_feed_count | integer | Number of feeds whose check failed. |
data.max_age_s | float | null | The largest age observed among the feeds. |
data.feeds | array | One entry per feed, described below. |
| Field of each feed | Type | Description |
|---|---|---|
feed | string | The public name of the feed: klines_1m, funding_rate, cvd_1h, options_aggregates, btc_mempool, macro_daily_weekly, etf_filings… The closed list is in the contract (enum of feed). |
family | string | The quota family the feed belongs to, as in /v1/limits and the x-family of each route: price_volume, derivatives, microstructure, trades, options, onchain, macro, etf, tokenomics or sentiment. |
routes | string[] | The public routes that serve this feed's data: a late feed tells you which routes are affected. |
age_s | float | null | Seconds since the last delivery. For a feed made of several series (one per asset, per macro series, per ETF), the age of its oldest series; for the market-hours intraday macro series (macro_intraday_1m … macro_intraday_1d), counted on weekdays only, like their threshold. null if the feed holds no data yet, or if the check failed. |
expected_interval_s | integer | The expected rhythm: the longest age that is still legitimate for this feed (one day for a daily series, for example). |
threshold_s | integer | The threshold applied, always 1.5 × expected_interval_s. |
is_stale | boolean | null | True if the feed exceeds its threshold, if a single one of its venues exceeds it, or (series feed) if a single one of its series does. null if the check failed: it is then counted in error_feed_count. |
stale_venue_count | integer | null | The number of venues late on this feed, never their names. null when the feed is not broken down by venue (every feed outside the market families). |
#Symbol catalogue
All 5 fields of this route (from the contract)
symbol | Trading pair, e.g. `BTCUSDT`. | |
base_asset | Base asset of the pair. | |
name | Human-readable name. | |
quote_asset | Quote currency of the pair (`USDT` for BTCUSDT, `USDC` for USDTUSDC): the currency of its prices. | |
markets | Markets served for the pair: `spot` and `futures` (USDT-margined perpetual), or `spot` only for the two stablecoin pairs (their `/futures` routes answer `unavailable: not_applicable`). |
The live list of the assets enabled. It is the authority: do not hard-code the list in a client, have it read at start-up.
{
"status": "ok",
"server_time": "2026-11-08T12:51:15.750Z",
"data_type": "symbols",
"data": [
{
"symbol": "AAVEUSDT",
"base_asset": "AAVE",
"name": "Aave",
"quote_asset": "USDT",
"markets": [
"spot",
"futures"
]
},
{
"symbol": "ADAUSDT",
"base_asset": "ADA",
"name": "Cardano",
"quote_asset": "USDT",
"markets": [
"spot",
"futures"
]
}
]
}| Field | Type | Description |
|---|---|---|
symbol | string | The identifier to pass in ?symbol=. |
base_asset | string | The base asset (BTC, ETH). It is what the options routes take in ?asset=. |
name | string | The full name, for display. |
quote_asset | string | The quote currency: the currency of the pair’s prices (USDT for BTCUSDT, USDC for USDTUSDC). |
markets | string[] | The markets served: spot and futures, or spot only for the two stablecoin pairs. |
#Capability report
All 25 fields of this route (from the contract)
asset_class | `crypto` or `stablecoin` (spot only, no futures metrics). | |
feeds_active_last_24h | Per source feed, under its `/v1/status` name (`trades_spot`, `trades_kline_futures_seconds`, `oi`, `funding_rate`, `klines_1m`...): whether it received data for this symbol in the last 24 h. | |
feeds_active_last_24h.klines_futures_1m | `true` when the `klines_futures_1m` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
feeds_active_last_24h.trades_spot | `true` when the `trades_spot` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
feeds_active_last_24h.trades_futures | `true` when the `trades_futures` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
feeds_active_last_24h.oi | base asset quantity (BTC for BTCUSDT) | `true` when the `oi` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. |
feeds_active_last_24h.funding_rate | `true` when the `funding_rate` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
feeds_active_last_24h.liquidations_events | `true` when the `liquidations_events` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
feeds_active_last_24h.trades_kline_futures_seconds | `true` when the `trades_kline_futures_seconds` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
feeds_active_last_24h.klines_futures_multi | `true` when the `klines_futures_multi` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
feeds_active_last_24h.klines_1m | `true` when the `klines_1m` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
feeds_active_last_24h.klines_multi | `true` when the `klines_multi` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
feeds_active_last_24h.orderbook_1m | `true` when the `orderbook_1m` feed delivered data in the last 24 hours; `null` when its probe did not conclude in time. | |
computed_metrics_available | Derived metrics available for the symbol. | |
computed_metrics_blocked | Derived metrics unavailable, with the missing feeds. | |
feeds_not_applicable | Feeds that do not exist for this symbol (the futures feeds of a spot-only stablecoin), under their `/v1/status` names. | |
stablecoin_note | Spot-only stablecoin: why its futures feeds and derived metrics do not apply. Absent for any other symbol. | |
computed_metrics_not_applicable | Derived metrics that do not apply (stablecoins have no futures). | |
computed_metrics_not_applicable.basis | Why `basis` does not apply to this symbol. | |
computed_metrics_not_applicable.oi_change | base asset quantity (BTC for BTCUSDT) | Why `oi_change` does not apply to this symbol. |
computed_metrics_not_applicable.liquidations_cumulative | Why `liquidations_cumulative` does not apply to this symbol. | |
computed_metrics_not_applicable.liquidations_big_small_ratio | Why `liquidations_big_small_ratio` does not apply to this symbol. | |
computed_metrics_not_applicable.funding_cumulative | Why `funding_cumulative` does not apply to this symbol. | |
computed_metrics_not_applicable.indicators | Why `indicators` does not apply to this symbol. | |
computed_metrics_not_applicable.trades_kline_futures | Why `trades_kline_futures` does not apply to this symbol. |
What this asset can actually serve, measured over the last twenty-four hours. It makes it possible to anticipate an empty response instead of discovering it, and to tell a metric that makes no sense here from a metric momentarily blocked.
curl -H "X-API-KEY: $BYTNODE_API_KEY" "https://api.bytnode.com/v1/capabilities?symbol=BTCUSDT"| Field | Type | Description |
|---|---|---|
symbol | string | The asset queried — in the envelope, next to data. |
asset_class | string | crypto or stablecoin. |
feeds_active_last_24h | object | The feeds probed, each true or false depending on whether it produced data over the window, or null when its probe did not conclude in time. Capability is not freshness: a feed active twenty hours ago is still true there. On a stablecoin, only the spot feed is probed. |
computed_metrics_available | array | The metrics that can be computed: all their input streams are present. |
computed_metrics_blocked | object | The metrics prevented, with the missing feeds and the reason. undetermined_feeds lists those whose probe exceeded its delay: unknown, not absent. |
computed_metrics_not_applicable | object | On a stablecoin: every metric derived from the futures market, with its reason. This is intentional, not a failure. |
feeds_not_applicable | array | On a stablecoin: the futures feeds, which are not probed rather than reported as false. |
stablecoin_note | string | On a stablecoin: what remains available on spot. |
An unknown or disabled symbol returns 422 invalid_symbol with the list of active symbols.
#Your plan’s limits
All 18 fields of this route (from the contract)
plan | Your plan: `free`, `traders`, `financial`, `startup` or `enterprise` (`legacy` for an internal unmetered key: every limit below is then unset). | |
families | Data families your plan includes (`price_volume`, `derivatives`, `microstructure`, `trades`, `snapshot`, `indicators`, `macro`, `options`, `onchain`, `etf`, `tokenomics`, `sentiment`); `null` = all of them. A route outside them answers 403 `plan_family`. | |
history | History window per timeframe, one object per timeframe the API serves. | |
history.timeframe | The timeframe the window applies to. | |
history.window_s | seconds | How far back this timeframe may be read, in seconds, measured from now; `null` = unlimited. Beyond it: 403 `history_depth`. |
trades_window_s | seconds | How far back individual trades (`/v1/trades/spot`, `/futures`, `/large`) may be read, in seconds; `0` = not in your plan (family `trades`), `null` = unlimited. |
liquidations_events_count | count | How many of the most recent individual liquidations `/v1/liquidations/events` may return, counted from the latest: 100 (Free), 500 (Traders), 1,000 (Financial), 10,000 (Startup); a larger `limit` answers 403 `history_depth`. `null` = no count set (Enterprise, or an unmetered key): up to 10,000 per call, the route's maximum. `0` = not in your plan (family `derivatives`). |
rate | The per-minute rate, as a token bucket; `null` = unlimited or unmetered key. The same values as the `RateLimit` headers (`rate` policy). | |
rate.requests_per_minute | count | Requests per minute of your plan (the bucket refills at this pace). |
rate.burst_count | count | Capacity of the bucket: requests you can send at once. |
rate.refill_s | seconds | Seconds to refill the bucket from empty. |
rate.remaining_count | count | Requests left right now (after this one). |
rate.reset_s | seconds | Seconds until fully restored. |
quota | The monthly quota; `null` = unlimited or unmetered key. The same values as the `RateLimit` headers (`quota` policy). It resets on the 1st of the month, 00:00 UTC. | |
quota.monthly_count | count | Requests included per calendar month. |
quota.month_length_s | seconds | Length of the current calendar month, in seconds. |
quota.remaining_count | count | Requests left right now (after this one). |
quota.reset_s | seconds | Seconds until fully restored. |
What your key may do, read from the plan that served THIS request: the market data families it includes, the history window of each timeframe, the tick-by-tick window, the number of individual liquidations, and the per-minute rate and monthly quota with what is left. Size limit and since_ms from it before paging, instead of discovering the window through a 403 history_depth. Not counted in your quota. With an unmetered key, every limit is null.
curl -H "X-API-KEY: $BYTNODE_API_KEY" "https://api.bytnode.com/v1/limits"| Field | Type | Description |
|---|---|---|
plan | string | null | Your plan: free, traders, financial, startup or enterprise. |
families | string[] | null | The market data families your plan includes; null = all of them. A route outside them answers 403 plan_family. |
history[].timeframe / window_s | string / integer | null | One entry per timeframe: how far back it may be read, in seconds (window_s); 0 = not in your plan, null = unlimited. |
trades_window_s | integer | null | How far back individual trades (/v1/trades/*) may be read, in seconds; 0 = not in your plan (family trades), null = unlimited. |
liquidations_events_count | integer | null | How many of the most recent individual liquidations /v1/liquidations/events may return. |
rate | object | null | The per-minute rate as a token bucket: requests_per_minute, burst_count (the burst capacity), refill_s (seconds to refill from empty), remaining_count, reset_s. The same values as the RateLimit headers. |
quota | object | null | The monthly quota: monthly_count, month_length_s, remaining_count, reset_s (until the 1st of next month, 00:00 UTC). |