Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Message Reference

All messages are delivered as binary WebSocket frames containing UTF-8 JSON. Every message has a type field.

Welcome

Sent once, immediately after a successful connection.

{
  "type": "welcome",
  "tier": "premium",
  "maxConnections": 5,
  "allowedCex": "*",
  "expiresInSecs": 2592000
}
FieldTypeDescription
typestringAlways "welcome"
tierstringYour subscription tier: basic, premium, or enterprise
maxConnectionsintegerMaximum simultaneous connections allowed with your key
allowedCexstringExchanges you will receive announcements from (effective filter after applying key restrictions and your cex preference). "*" means all exchanges
expiresInSecsinteger|nullSeconds until your key expires, or null if no expiration

Announcement

Sent whenever a listing or other exchange announcement is detected on a monitored exchange.

Single ticker:

{
  "type": "announcement",
  "title": "Binance Will List TOKEN (TOKEN)",
  "ticker": "TOKEN",
  "publisher": "binance",
  "listingType": "spot_listing",
  "publishTimestampUs": 1710345000000000,
  "detectedTimestampUs": 1710345000005000,
  "dispatchTimestampUs": 1710345000006000
}

Multiple tickers (one announcement listing several assets at once):

{
  "type": "announcement",
  "title": "Binance Will List ABC, DEF and GHI",
  "ticker": "ABC,DEF,GHI",
  "publisher": "binance",
  "listingType": "spot_listing",
  "publishTimestampUs": 1710345000000000,
  "detectedTimestampUs": 1710345000005000,
  "dispatchTimestampUs": 1710345000006000
}
FieldTypeDescription
typestringAlways "announcement"
titlestringOriginal announcement title from the exchange
tickerstringAsset symbol(s). Comma-separated when multiple tickers are listed in the same announcement (e.g. "BTC" or "ABC,DEF,GHI")
publisherstringExchange name in lowercase (e.g. "binance", "upbit", "bithumb")
listingTypestringOne of the listing types below
publishTimestampUsintegerWhen the exchange published the announcement (microseconds since UNIX epoch)
detectedTimestampUsintegerWhen our detection engine captured it (microseconds since UNIX epoch)
dispatchTimestampUsintegerWhen the dispatch server broadcasted it (microseconds since UNIX epoch)

Always handle ticker as a potentially comma-separated list. Some exchange announcements list multiple assets at once. Split on , to get individual tickers:

tickers = data["ticker"].split(",")  # ["ABC", "DEF", "GHI"]

Supported exchanges (publisher)

ValueExchange
binanceBinance
upbitUpbit
bithumbBithumb

More exchanges coming soon. This list will grow over time. Use the cex query parameter when connecting to filter which exchanges you receive.

Listing types

ValueMeaning
spot_listingNew spot market listing
futures_listingNew futures/perpetual listing
spot_delistingSpot market delisting (coming soon)
futures_delistingFutures/perpetual delisting (coming soon)
not_listingOther exchange announcement (maintenance, airdrop, token swap, etc.)

Delistings coming soon. The spot_delisting and futures_delisting types are reserved for future use. Currently, announcements that are not listings are sent with listingType: "not_listing".

Measuring your latency

All timestamps are in microseconds since UNIX epoch (not milliseconds, not nanoseconds).

Detection delay    = detectedTimestampUs - publishTimestampUs
Dispatch delay     = dispatchTimestampUs - detectedTimestampUs
Your network delay = your_receive_time_us - dispatchTimestampUs
Total end-to-end   = your_receive_time_us - publishTimestampUs

Python example:

import time

def on_announcement(msg):
    now_us = int(time.time() * 1_000_000)
    detection_ms = (msg["detectedTimestampUs"] - msg["publishTimestampUs"]) / 1000
    dispatch_ms  = (msg["dispatchTimestampUs"] - msg["detectedTimestampUs"]) / 1000
    network_ms   = (now_us - msg["dispatchTimestampUs"]) / 1000
    total_ms     = (now_us - msg["publishTimestampUs"]) / 1000

    print(f"Detection: {detection_ms:.2f}ms")
    print(f"Dispatch:  {dispatch_ms:.2f}ms")
    print(f"Network:   {network_ms:.2f}ms")
    print(f"Total:     {total_ms:.2f}ms")

Test Announcement

You can request a fake announcement to verify your integration. Send a JSON message to the server:

{"type":"test"}

The server replies with a test_announcement — identical to a real announcement except for the type field:

{
  "type": "test_announcement",
  "title": "Binance Will List MOCKX (MOCKX)",
  "ticker": "MOCKX",
  "publisher": "binance",
  "listingType": "spot_listing",
  "publishTimestampUs": 1743850000000000,
  "detectedTimestampUs": 1743850001999800,
  "dispatchTimestampUs": 1743850002000000
}

The fields are the same as a regular Announcement. The timestamps are simulated: publishTimestampUs is 1 second before dispatch, and detectedTimestampUs is 200µs before dispatch.

This message is only sent to you, not broadcast to other subscribers. The exchange, listing type, ticker, and title are randomized from realistic templates.

Test rate limit

Test requests are rate-limited to 1 per minute per API key (shared across all connections using the same key). If you exceed the limit, the server responds with an error instead of a test announcement:

{
  "type": "error",
  "code": "test_rate_limited",
  "retryAfterSecs": 42
}
FieldTypeDescription
typestringAlways "error"
codestringError code: "test_rate_limited"
retryAfterSecsintegerSeconds to wait before retrying

Heartbeat

Sent every 30 seconds to indicate the server is alive.

{
  "type": "heartbeat",
  "timestampNs": 1710345030000000000,
  "timeUtc": "2024-03-13T10:30:30.000000Z"
}
FieldTypeDescription
typestringAlways "heartbeat"
timestampNsintegerCurrent server time in nanoseconds since UNIX epoch
timeUtcstringCurrent server time in ISO 8601 UTC format

If you do not receive a heartbeat within 35 seconds, your connection is likely dead. Initiate a reconnection.