Price WebSocket API
The Oracle server exposes a read-only WebSocket endpoint for live source ticks, aggregate price updates, and finalized source tick buckets.
Production WebSocket URL:
wss://api.coinpost.ai/oracle/ws/pricesUpstream endpoint path:
GET /ws/pricesAuthentication
WebSocket upgrade authentication follows the Oracle server rule. When auth.enabled or cp_auth.enabled is true, send the API key as a Bearer token:
Authorization: Bearer <api_key>Browser clients that cannot set custom WebSocket headers may pass the token on the WebSocket URL:
wss://api.coinpost.ai/oracle/ws/prices?token=<api_key>
wss://api.coinpost.ai/oracle/ws/prices?access_token=<api_key>Query-token auth is accepted only for the price WebSocket endpoint.
REST operation pages document REST API authentication separately.
Client Messages
Client messages are JSON. Unknown fields are ignored.
Subscribe
{
"type": "subscribe",
"id": "btc-live",
"symbols": ["BTC"],
"channels": ["aggregate", "sources", "ticks"],
"sources": ["bitbank", "binance_japan", "coinbase"],
"include_snapshot": true
}Fields:
id: optional subscription ID. The server echoes it assubscription_id.symbols: required list of canonical symbols.channels: optional list. Defaults to["aggregate", "sources"].sources: optional source filter. Omit or pass an empty list for all sources.include_snapshot: optional boolean. When true, the server sends the latest state immediately.
Channels:
aggregate: receivesnapshotaggregate data andaggregate_updatemessages.sources: receivesnapshotsource data andsource_updatemessages.ticks: receive finalizedtickmessages.
Unsubscribe
{
"type": "unsubscribe",
"id": "btc-live"
}If id is omitted, the default subscription is removed.
Ping
{
"type": "ping",
"ts": "2026-06-10T06:00:00Z"
}Response:
{
"type": "pong",
"ts": "2026-06-10T06:00:00Z"
}Server Messages
Snapshot
Sent after subscribe when include_snapshot is true. sources is a map of source name to the latest source tick.
{
"type": "snapshot",
"subscription_id": "btc-live",
"symbol": "BTC",
"asset_id": "d388491f-2ee0-337f-bad1-fd8f4444e076",
"tick_interval": "1m0s",
"aggregate": {
"source": "aggregated",
"selected_source": "bitbank",
"selected_pair": "btc_jpy",
"price_usd": "61363.4557105392479143",
"price_jpy": "9839303",
"tick_start": "2026-06-10T15:01:00+09:00",
"tick_interval": "1m0s",
"method": "source_vote",
"vote_band_pct": "0.003",
"vote_sources": ["bitbank", "bitflyer", "coinbase"],
"rejected_sources": ["binance_japan"],
"updated_at": "2026-06-10T15:01:24.347954002+09:00"
},
"sources": {
"bitbank": {
"symbol": "BTC",
"asset_id": "d388491f-2ee0-337f-bad1-fd8f4444e076",
"source": "bitbank",
"pair": "btc_jpy",
"tick_start": "2026-06-10T15:01:00+09:00",
"tick_interval": "1m0s",
"native_price": "9839303",
"native_currency": "JPY",
"price_jpy": "9839303",
"price_usd": "61363.4557105392479143",
"open": "9839303",
"high": "9839303",
"low": "9839303",
"close": "9839303",
"bid": "9837946",
"ask": "9837947",
"source_timestamp": "2026-06-10T15:01:10.046+09:00",
"received_at": "2026-06-10T15:01:11.420015171+09:00",
"transport": "websocket",
"sample_count": 12
}
}
}Source Update
Sent when channels includes sources. This is the lowest-latency public event for exchange source ticks.
{
"type": "source_update",
"subscription_id": "btc-live",
"symbol": "BTC",
"asset_id": "d388491f-2ee0-337f-bad1-fd8f4444e076",
"source": "bitbank",
"pair": "btc_jpy",
"tick_start": "2026-06-10T15:01:00+09:00",
"tick_interval": "1m0s",
"native_price": "9839303",
"native_currency": "JPY",
"price_jpy": "9839303",
"price_usd": "61363.4557105392479143",
"open": "9839303",
"high": "9839303",
"low": "9839303",
"close": "9839303",
"bid": "9837946",
"ask": "9837947",
"source_timestamp": "2026-06-10T15:01:10.046+09:00",
"received_at": "2026-06-10T15:01:11.420015171+09:00",
"transport": "websocket",
"sample_count": 12,
"updated_at": "2026-06-10T15:01:11.421000000+09:00"
}Field notes:
native_price: latest observed price in the source quote currency.price_usd/price_jpy: normalized prices when conversion is available.open,high,low,close: source tick bucket values for the currenttick_start.bid/ask: best bid and ask when the source ticker provides them.sample_count: number of source messages folded into the current bucket.source_timestamp: timestamp reported by the exchange or upstream source.received_at: local receive time in the worker.
Bid and ask availability:
| Source | Bid/ask |
|---|---|
bitbank | Yes |
binance_japan | Yes |
bitflyer | Yes |
coinbase | Yes |
gmo_coin | Yes |
coincheck | No, current collector uses trades |
coingecko | No, current collector uses simple price |
These are ticker-level best bid and ask values. They are not a full order book.
Aggregate Update
Sent when channels includes aggregate. The worker recalculates the current aggregate after each source update.
{
"type": "aggregate_update",
"subscription_id": "btc-live",
"symbol": "BTC",
"asset_id": "d388491f-2ee0-337f-bad1-fd8f4444e076",
"source": "bitbank",
"tick_start": "2026-06-10T15:01:00+09:00",
"tick_interval": "1m0s",
"aggregate": {
"source": "aggregated",
"selected_source": "bitbank",
"selected_pair": "btc_jpy",
"price_usd": "61363.4557105392479143",
"price_jpy": "9839303",
"tick_start": "2026-06-10T15:01:00+09:00",
"tick_interval": "1m0s",
"method": "source_vote",
"vote_band_pct": "0.003",
"vote_sources": ["bitbank", "bitflyer", "coinbase"],
"rejected_sources": ["binance_japan"],
"updated_at": "2026-06-10T15:01:24.347954002+09:00"
},
"updated_at": "2026-06-10T15:01:24.347954002+09:00"
}Tick
Sent when channels includes ticks and a tick bucket is finalized.
{
"type": "tick",
"subscription_id": "btc-live",
"symbol": "BTC",
"asset_id": "d388491f-2ee0-337f-bad1-fd8f4444e076",
"tick_start": "2026-06-10T15:01:00+09:00",
"tick_interval": "1m0s",
"aggregate": {
"source": "aggregated",
"selected_source": "bitbank",
"selected_pair": "btc_jpy",
"price_usd": "61363.4557105392479143",
"price_jpy": "9839303",
"method": "source_vote",
"vote_sources": ["bitbank", "bitflyer", "coinbase"],
"rejected_sources": ["binance_japan"]
},
"sources": {
"bitbank": {
"pair": "btc_jpy",
"native_price": "9839303",
"native_currency": "JPY",
"price_jpy": "9839303",
"price_usd": "61363.4557105392479143",
"open": "9839303",
"high": "9839303",
"low": "9839303",
"close": "9839303",
"bid": "9837946",
"ask": "9837947",
"transport": "websocket",
"sample_count": 12
}
},
"updated_at": "2026-06-10T15:02:02.000000000+09:00"
}Example Client
const ws = new WebSocket("wss://api.coinpost.ai/oracle/ws/prices");
ws.addEventListener("open", () => {
ws.send(JSON.stringify({
type: "subscribe",
id: "btc-live",
symbols: ["BTC"],
channels: ["aggregate", "sources"],
include_snapshot: true
}));
});
ws.addEventListener("message", (event) => {
const msg = JSON.parse(event.data);
if (msg.type === "source_update") {
console.log(msg.source, msg.bid, msg.ask, msg.native_price);
}
});Operational Notes
GET /prices/sources?symbol=BTCfilters stale source ticks. Through the production REST base URL, callhttps://api.coinpost.ai/oracle/prices/sources?symbol=BTC.- WebSocket
source_updatesends live updates as they arrive. source_updateincludes current bucket OHLC values, not finalized historical candles.- Full order book depth is not part of this endpoint. Use exchange order book streams if full depth is required.
