K-Line API — API reference
Historical K-line query
This module queries persisted OHLCV candlestick data. It is suitable for chart initialization, filling gaps after client disconnects, and loading historical data before subscribing to real-time updates.
Queries must specify the chain, pool, token side, and K-line interval. The endpoint returns an array; when no data matches, it usually returns an empty array.
Query OHLCV data
Request
GET /kline/api/v1/kline/ohlcv
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
interval | string | Yes | - | K-line interval: 1s, 1m, 15m, 1h, 4h, 1d, 1w, 1M, 1Y. |
from | integer | Yes | - | Query start time, Unix seconds or milliseconds. |
to | integer | Yes | - | Query end time, Unix seconds or milliseconds. |
limit | integer | No | 1000 | Maximum row count, from 1 to 5000. |
chain_type | string | Yes | - | Chain type, normalized automatically. |
chain_id | integer | Yes | - | Positive chain ID. |
pool_address | string | Yes | - | Pool contract address. |
token | string | No | base | base or quote. |
curl example
curl -H "X-API-Key: $API_KEY" "https://api.gelabs.org/kline/api/v1/kline/ohlcv?interval=1h&from=1776679200&to=1776765600&limit=500&chain_type=evm&chain_id=1&pool_address=0xabc123def456&token=base"
Successful response
data is an OHLCV array and is not wrapped in items:
{
"code": 0,
"message": "ok",
"data": [
{
"pool_id": 42,
"interval": "1h",
"open_time": 1776679200,
"open": 3500.12,
"high": 3520,
"low": 3480.5,
"close": 3510.88,
"volume": 1234567.89
}
]
}
Response fields
| Field | Type | Always returned | Description |
|---|---|---|---|
pool_id | integer | Yes | Internal pool ID. |
interval | string | Yes | K-line interval. |
open_time | integer | Yes | Candle start time, Unix seconds. |
open | number / null | Yes | Open price. |
high | number / null | Yes | High price. |
low | number / null | Yes | Low price. |
close | number / null | Yes | Close price. |
volume | number / null | Yes | Volume. |
Cache notes
This endpoint does not currently declare a fixed HTTP cache header. Business clients may apply short caching by interval; for high-real-time scenarios, combine HTTP historical queries with WebSocket updates for the latest candle.
Common error response
Missing or invalid parameters usually return:
{
"code": 10001,
"message": "Invalid query params",
"error": {
"type": "ValidationError",
"details": {
"fieldErrors": {
"interval": ["Required"],
"pool_address": ["Required"]
}
}
}
}
Market APIs
Market APIs use the K-Line unified success wrapper, while data contains the corresponding market data.
This module queries market information for pools and tokens, such as pool details, top holders, and token metadata by contract address.
Note: Market APIs are mainly for auxiliary display and debugging. They do not represent the internal K-Line collection state.
Get pool market details
Request
GET /kline/api/v1/market/pools/{network}/{address}
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
network | path | string | Yes | Network identifier, 1-100 characters. |
address | path | string | Yes | Pool contract address, 1-200 characters. |
include | query | string | No | Extra included fields, comma-separated. |
include_volume_breakdown | query | string | No | "true" or "false". |
include_composition | query | string | No | "true" or "false". |
curl example
curl -H "X-API-Key: $API_KEY" "https://api.gelabs.org/kline/api/v1/market/pools/eth/0xabc123def456?include=base_token,quote_token&include_volume_breakdown=true&include_composition=false"
Cache notes
This endpoint does not currently promise a fixed cache duration in the documentation.
Common error response
Request failures, rate limits, or internal exceptions usually return:
{
"code": 99001,
"message": "Internal server error",
"error": { "type": "InternalServerError" }
}
Get token top holders
Request
GET /kline/api/v1/market/tokens/{network}/{address}/top-holders
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
network | path | string | Yes | Network identifier, 1-100 characters. |
address | path | string | Yes | Token contract address, 1-200 characters. |
holders | query | string | No | Positive integer string or max. |
include_pnl_details | query | string | No | "true" or "false". |
curl example
curl -H "X-API-Key: $API_KEY" "https://api.gelabs.org/kline/api/v1/market/tokens/eth/0xabc123def456/top-holders?holders=10&include_pnl_details=false"
Cache notes
This endpoint does not currently promise a fixed cache duration in the documentation. Control call frequency according to display requirements.
Common error response
{
"code": 99001,
"message": "Internal server error",
"error": { "type": "InternalServerError" }
}
Get token metadata by contract address
Request
GET /kline/api/v1/market/coins/{network}/{address}
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
network | path | string | Yes | Platform identifier, 1-100 characters. |
address | path | string | Yes | Token contract address, 1-200 characters. |
curl example
curl -H "X-API-Key: $API_KEY" "https://api.gelabs.org/kline/api/v1/market/coins/ethereum/0xabc123def456"
Cache notes
This proxy endpoint does not currently promise a fixed cache duration in the documentation. Token metadata usually changes infrequently, so clients may cache it according to business needs.
Common error response
{
"code": 99001,
"message": "Internal server error",
"error": { "type": "InternalServerError" }
}
K-Line WebSocket
K-Line real-time push uses a single WebSocket entry point. After connecting, clients dynamically subscribe or unsubscribe to multiple pools with JSON messages.
Keep HTTP historical query support on the client side. On first load or after reconnecting, query historical data first, then use WebSocket updates for the latest candle.
Connection requirements
Connection URL
GET /kline/api/v1/kline/ws
Required headers
| Header | Required | Description |
|---|---|---|
Upgrade: websocket | Yes | Standard WebSocket upgrade header. |
Connection: Upgrade | Yes | Standard WebSocket upgrade header. |
X-API-Key | Yes | Public API key for API authentication and billing identification. |
Note:
X-API-Keyis the only required business request header for external integration. No additional business headers are required from integrators.
When the WebSocket upgrade headers are missing, the endpoint returns HTTP 426:
{
"code": 4000,
"message": "WebSocket upgrade required",
"error": { "type": "BadRequestError" }
}
When X-API-Key is missing or authentication fails, the endpoint usually returns HTTP 401 or 403, depending on gateway configuration:
{
"code": 20001,
"message": "Unauthorized",
"error": { "type": "UnauthorizedError" }
}
Protocol constants
| Constant | String value | Direction | Description |
|---|---|---|---|
WS_TYPE_PING | ping | Client → server | Application heartbeat. |
WS_TYPE_PONG | pong | Server → client | Heartbeat response. |
WS_TYPE_SUBSCRIBE | subscribe | Client → server | Subscribe to a pool. |
WS_TYPE_UNSUBSCRIBE | unsubscribe | Client → server | Unsubscribe from a pool. |
WS_TYPE_SUBSCRIBED | subscribed | Server → client | Subscription acknowledgement. |
WS_TYPE_UNSUBSCRIBED | unsubscribed | Server → client | Unsubscription acknowledgement. |
WS_TYPE_OHLCV | ohlcv | Server → client | Real-time or snapshot K-line push. |
| WebSocket code | Description |
|---|---|
0 | Success |
4001 | Invalid message, such as invalid JSON or missing fields |
4002 | Unknown command |
4500 | Internal error, currently reserved |
Client message format
{
"id": "req-001",
"type": "subscribe",
"data": {}
}
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Request correlation ID. |
type | string | Yes | ping, subscribe, or unsubscribe. |
data | object | Depends on command | Command payload. |
subscribe.data
| Field | Type | Required | Description |
|---|---|---|---|
chain_type | string | Yes | Chain type, normalized automatically. |
chain_id | number | Yes | Chain ID. |
pool_address | string | Yes | Pool address; internal pool key is lowercased. |
token | string | No | base or quote; default is base. |
intervals | string[] | No | Valid intervals. Missing or empty array means all intervals. Invalid values are silently ignored. |
Note:
intervalsmust be a JSON array, not a comma-separated string.
unsubscribe.data
| Field | Type | Required | Description |
|---|---|---|---|
chain_type | string | Yes | Chain type, normalized automatically. |
chain_id | number | Yes | Chain ID. |
pool_address | string | Yes | Pool address. |
token | string | No | base or quote; default is base. |
Server message format
{
"id": "req-001",
"time": 1776682800000,
"type": "subscribed",
"code": 0,
"data": {},
"msg": "ok"
}
| Field | Type | Always returned | Description |
|---|---|---|---|
id | string | Yes | Request ID for command responses; active pushes use "". |
time | number | Yes | Server Unix millisecond timestamp. |
type | string | Yes | pong, subscribed, unsubscribed, ohlcv, or error. |
code | number | Yes | WebSocket business code. |
data | object / null | Yes | Payload. |
msg | string | Yes | Human-readable message; real-time pushes use ok, snapshots use snapshot. |
Subscribe and unsubscribe examples
Heartbeat
{ "id": "hb-001", "type": "ping", "data": {} }
Response:
{
"id": "hb-001",
"time": 1776682800000,
"type": "pong",
"code": 0,
"data": {},
"msg": "ok"
}
Subscribe
{
"id": "sub-001",
"type": "subscribe",
"data": {
"chain_type": "evm",
"chain_id": 1,
"pool_address": "0xabc123def456",
"token": "base",
"intervals": ["1m", "1h", "4h"]
}
}
Successful response:
{
"id": "sub-001",
"time": 1776682800000,
"type": "subscribed",
"code": 0,
"data": {
"key": "evm:1:0xabc123def456:base",
"intervals": ["1m", "1h", "4h"]
},
"msg": "ok"
}
If the server already has a latest tick for the pool in memory, it may immediately push an additional ohlcv snapshot.
Unsubscribe
{
"id": "unsub-001",
"type": "unsubscribe",
"data": {
"chain_type": "evm",
"chain_id": 1,
"pool_address": "0xabc123def456",
"token": "base"
}
}
Response:
{
"id": "unsub-001",
"time": 1776682800000,
"type": "unsubscribed",
"code": 0,
"data": {
"key": "evm:1:0xabc123def456:base"
},
"msg": "ok"
}
Push data fields
Real-time and snapshot pushes both use type: "ohlcv":
{
"id": "",
"time": 1776682800000,
"type": "ohlcv",
"code": 0,
"data": {
"chain_type": "evm",
"chain_id": 1,
"pool_address": "0xabc123def456",
"token": "base",
"interval": "1h",
"open_time": 1776679200,
"open": 3500.12,
"high": 3520,
"low": 3480.5,
"close": 3510.88,
"volume": 1234567.89
},
"msg": "ok"
}
| Field | Type | Always returned | Description |
|---|---|---|---|
chain_type | string / null | Yes | Chain type. |
chain_id | number / null | Yes | Chain ID. |
pool_address | string | Yes | Pool address. |
token | string | Yes | Token side. |
interval | string | Yes | K-line interval. |
open_time | number | Yes | Candle start time, Unix seconds. |
open | number / null | Yes | Open price. |
high | number / null | Yes | High price. |
low | number / null | Yes | Low price. |
close | number / null | Yes | Close price. |
volume | number / null | Yes | Volume. |
KlineHub silently ignores binary frames. Clients receive no ohlcv pushes when they have no active pool subscriptions. Repeated subscribe for the same pool overwrites the pool's intervals setting.
WebSocket error messages
{
"id": "sub-001",
"time": 1776682800000,
"type": "error",
"code": 4001,
"data": null,
"msg": "subscribe: missing required fields"
}
| Scenario | code | Example msg |
|---|---|---|
| JSON parsing failed | 4001 | Invalid JSON |
Missing id or type | 4001 | Missing id or type |
subscribe missing fields | 4001 | subscribe: missing required fields |
unsubscribe missing fields | 4001 | unsubscribe: missing required fields |
| Unknown command | 4002 | Unknown command: xxx |
Generic WebSocket
The generic WebSocket path is:
GET /kline/api/v1/ws/{topic}
topic is used as the Durable Object instance name. The currently exposed capability only supports application-level ping/pong.
Client message
{ "id": "req-001", "type": "ping", "data": {} }
Server response
{
"id": "req-001",
"time": 1704070800000,
"type": "pong",
"code": 0,
"data": {},
"msg": "ok"
}
Plain HTTP requests to this path return HTTP 426 as plain text:
Expected WebSocket upgrade
Unlike KlineHub, the generic WsServer returns an error message for binary frames, with code set to 4001 and msg set to Binary messages are not supported.
Note: Generic WebSocket is currently suitable only for connectivity or basic message-channel validation. Use
/kline/api/v1/kline/wsfor K-line real-time market data.
Error handling and best practices
Common HTTP errors
| HTTP | Common business code | Description |
|---|---|---|
| 400 | 10001 / 10002 / 10005 | Missing or invalid parameters, or WebSocket preflight error. |
| 404 | 10003 / 60001 | Route, pool, or resource not found. |
| 409 | 10004 | Resource conflict, such as duplicate pool creation. |
| 500 | 99001 / 99002 / 99003 | Internal service, database, or cache error. |
Clients should check both the HTTP status code and response body code. Business success is represented by code: 0.
WebSocket integration recommendations
| Item | Recommendation |
|---|---|
| Heartbeat | Periodically send { "id": "hb-001", "type": "ping", "data": {} } and verify pong. |
| Reconnect | Use exponential backoff after disconnects and re-send subscriptions after reconnecting. |
| Gap filling | After reconnecting, call GET /kline/api/v1/kline/ohlcv to fill missing historical data. |
| Idempotency | Treat the same pool, interval, and open_time as an upsert key. |
| Subscription state | Repeated subscribe overwrites the pool's intervals; maintain local subscription state. |
Timestamp handling
- HTTP query parameters
fromandtoaccept Unix seconds or milliseconds. Values greater than10000000000are treated as milliseconds by the server. - OHLCV
open_timeuses Unix seconds; WebSocket envelopetimeuses Unix milliseconds. - Store timestamps in UTC and convert time zones only in the presentation layer.
Price and volume precision
open,high,low,close, andvolumemay benull.- Use high-precision decimal types or string storage for prices, volume, and market values when precision matters.
- Market API data may use different field types from K-Line OHLCV data.
Document version: v1.0.0 | Last updated: 2026-04-28