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

Public JSON & Atom Feeds

The announcements shown on Latest Listings are also published as a free JSON file and as Atom feeds. No API key, no account: a plain HTTP GET.

These feeds are for dashboards, research, backfills and independent verification. They are read by polling and carry a summary of each event. To act on an announcement, use the WebSocket API: every message is pushed to you as it is dispatched, and free SpeedTrial and FreeDelayed keys are available — see Quick Start.

At a glance

FeedURL
Announcements, JSONhttps://cryptolisting.ws/data/recent-announcements.json
Announcements, Atom 1.0https://cryptolisting.ws/feed-listings.xml
Blog, Atom 1.0https://cryptolisting.ws/feed.xml

Both announcement feeds are built from the same data — listings, delistings, airdrops, Monitoring Tag changes and caution releases — newest first. The JSON file keeps every recorded event; the Atom feed carries the most recent ones. The blog feed carries blog posts and product announcements.

JSON feed

Request

GET https://cryptolisting.ws/data/recent-announcements.json
  • No authentication, no query parameters.
  • CORS: Access-Control-Allow-Origin: * — readable from browser code on any origin.
  • Every response carries ETag and Last-Modified. Send them back as If-None-Match / If-Modified-Since and you get 304 Not Modified, with no body, while nothing new has been recorded.
  • Compressed (gzip or zstd) when your client accepts it.

Response

{
  "updated_at_us": 1790573225386588,
  "events": [
    {"cex":"upbit","ticker":"CASHCAT","type":"spot_listing","detected_at_us":1790573225386588},
    {"cex":"bithumb","ticker":"PYUSD","type":"spot_listing","detected_at_us":1790571091315312},
    {"cex":"bithumb","ticker":"Q","type":"spot_listing","detected_at_us":1790571091315312}
  ]
}

The two Bithumb entries come from one announcement that listed two tokens: they share the same detected_at_us.

Top level

FieldTypeDescription
updated_at_usintegerWhen the content of the file last changed, in microseconds since the Unix epoch (UTC). It only moves when an event is recorded, so it is not a liveness signal.
eventsarrayRecorded events, newest first.

Each event

FieldTypeDescription
cexstringExchange that published the announcement, lowercase: binance, upbit or bithumb.
tickerstringOne token symbol, as written in the announcement. Can contain non-Latin characters.
typestringEvent type. Same values as listingType on the WebSocket — see Listing types.
detected_at_usintegerDetection time, in microseconds since the Unix epoch (UTC). Divide by 1,000,000 for Unix seconds.

type takes one of these values in this feed:

typeEvent
spot_listingNew spot market listing
futures_listingNew futures / perpetual listing (Binance)
spot_delistingSpot market delisting
futures_delistingFutures / perpetual delisting (Binance)
hodler_airdropBinance HODLer Airdrop
monitoring_tag_extendToken added to Binance’s Monitoring Tag
monitoring_tag_removeToken removed from Binance’s Monitoring Tag
caution_releasedCaution designation lifted (Upbit, Bithumb)

Rules worth knowing

  • One entry per token. An announcement that covers several tokens becomes one entry per token, all with the same detected_at_us. The WebSocket delivers the same announcement as a single message with a comma-separated ticker.
  • Newest first. Sort on detected_at_us if the order matters to you.
  • No repeat within 72 hours. The same cex + ticker + type seen again within 72 hours is recorded once, with its first detection time. A relisting days later is a new entry.
  • Identify an entry by cex + ticker + type + detected_at_us. Do not rely on its position or on the length of the list.
  • Not in this feed: not_listing announcements (maintenance, token swaps…), Robinhood events (wallet_listing, cex_listing — WebSocket only), announcement titles, Upbit’s markets and abnormalDetectionLatency.
  • Ignore what you don’t know. New fields or new type values can appear; skip them rather than fail.

Update behaviour

The file is rewritten when a new event is recorded, after it has been pushed to WebSocket subscribers. Otherwise it does not change: announcements can be hours apart, and every read in between returns the same content.

Fair use

  • Read it at most once every 30 seconds per client. Latest Listings refreshes itself at that pace.
  • Use conditional requests (If-None-Match or If-Modified-Since): an unchanged file then costs a 304 and no body.
  • Send a User-Agent that names your project and a way to reach you.
  • Share one reader across your own processes instead of having each of them poll.

Clients that poll much faster may be throttled or blocked. Terms of use: Legal.

Examples

Python, standard library only — prints each new event, with conditional requests:

import json, time, urllib.request, urllib.error

URL = "https://cryptolisting.ws/data/recent-announcements.json"
UA  = "my-listing-dashboard/1.0 (+https://example.com/contact)"   # say who you are

etag, seen = None, set()
while True:
    req = urllib.request.Request(URL, headers={"User-Agent": UA})
    if etag:
        req.add_header("If-None-Match", etag)
    events = []
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            etag = resp.headers.get("ETag")
            events = json.load(resp)["events"]
    except urllib.error.HTTPError as err:
        if err.code != 304:                    # 304 = nothing new since the last read
            print("HTTP", err.code)
    for ev in reversed(events):                # oldest first; the first pass prints the whole file
        key = (ev["cex"], ev["ticker"], ev["type"], ev["detected_at_us"])
        if key not in seen:
            seen.add(key)
            print(ev["cex"], ev["type"], ev["ticker"], ev["detected_at_us"])
    time.sleep(30)                             # fair use: one read every 30 s at most

JavaScript (browser, or Node.js 18+) — the ten most recent events:

const res = await fetch("https://cryptolisting.ws/data/recent-announcements.json");
const { events } = await res.json();

for (const ev of events.slice(0, 10)) {
  const when = new Date(ev.detected_at_us / 1000).toISOString();   // µs → ms
  console.log(when, ev.cex, ev.type, ev.ticker);
}

Atom feeds

Announcements feed

https://cryptolisting.ws/feed-listings.xml
  • Atom 1.0, generated on each request from the same data as the JSON file, so it is never behind it.
  • The latest announcements, newest first. Each <entry> names the exchange, the token and the event type, links to the announcement on cryptolisting.ws, and carries the detection time (UTC) in <published>.
  • Stable entry <id>s: a feed reader shows each event once.
  • Sent with Cache-Control: no-store. The same fair use applies: one read every 30 seconds at most — most feed readers poll far less often.

Blog feed

https://cryptolisting.ws/feed.xml

Atom 1.0 feed of the blog: guides and product announcements. It changes when a post is published. For changes to the WebSocket feed itself, see the Changelog.

Public feeds vs WebSocket

JSON and Atom feedsWebSocket API
AccessOpen, no keyAPI key (free SpeedTrial and FreeDelayed tiers)
DeliveryYou pollPushed to you
TimingWritten after WebSocket dispatch; your polling interval adds to itAt dispatch, plus your tier’s documented delay
ExchangesBinance, Upbit, BithumbBinance, Upbit, Bithumb, Robinhood
Event typesThe eight types aboveAll, including not_listing and the Robinhood types
Fieldscex, ticker, type, detected_at_usFull message: title, ticker, publisher, listingType, timestamps, markets, abnormalDetectionLatency
Multi-token announcementOne entry per tokenOne message, comma-separated ticker
Built forDashboards, research, backfills, verificationTrading bots

Next


CryptoListing.ws is a technical data feed, not financial advice. See Legal.