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
| Feed | URL |
|---|---|
| Announcements, JSON | https://cryptolisting.ws/data/recent-announcements.json |
| Announcements, Atom 1.0 | https://cryptolisting.ws/feed-listings.xml |
| Blog, Atom 1.0 | https://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
ETagandLast-Modified. Send them back asIf-None-Match/If-Modified-Sinceand you get304 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
| Field | Type | Description |
|---|---|---|
updated_at_us | integer | When 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. |
events | array | Recorded events, newest first. |
Each event
| Field | Type | Description |
|---|---|---|
cex | string | Exchange that published the announcement, lowercase: binance, upbit or bithumb. |
ticker | string | One token symbol, as written in the announcement. Can contain non-Latin characters. |
type | string | Event type. Same values as listingType on the WebSocket — see Listing types. |
detected_at_us | integer | Detection 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:
type | Event |
|---|---|
spot_listing | New spot market listing |
futures_listing | New futures / perpetual listing (Binance) |
spot_delisting | Spot market delisting |
futures_delisting | Futures / perpetual delisting (Binance) |
hodler_airdrop | Binance HODLer Airdrop |
monitoring_tag_extend | Token added to Binance’s Monitoring Tag |
monitoring_tag_remove | Token removed from Binance’s Monitoring Tag |
caution_released | Caution 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-separatedticker. - Newest first. Sort on
detected_at_usif the order matters to you. - No repeat within 72 hours. The same
cex+ticker+typeseen 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_listingannouncements (maintenance, token swaps…), Robinhood events (wallet_listing,cex_listing— WebSocket only), announcement titles, Upbit’smarketsandabnormalDetectionLatency. - Ignore what you don’t know. New fields or new
typevalues 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-MatchorIf-Modified-Since): an unchanged file then costs a304and no body. - Send a
User-Agentthat 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 feeds | WebSocket API | |
|---|---|---|
| Access | Open, no key | API key (free SpeedTrial and FreeDelayed tiers) |
| Delivery | You poll | Pushed to you |
| Timing | Written after WebSocket dispatch; your polling interval adds to it | At dispatch, plus your tier’s documented delay |
| Exchanges | Binance, Upbit, Bithumb | Binance, Upbit, Bithumb, Robinhood |
| Event types | The eight types above | All, including not_listing and the Robinhood types |
| Fields | cex, ticker, type, detected_at_us | Full message: title, ticker, publisher, listingType, timestamps, markets, abnormalDetectionLatency |
| Multi-token announcement | One entry per token | One message, comma-separated ticker |
| Built for | Dashboards, research, backfills, verification | Trading bots |
Next
- Quick Start — get a free key and connect to the WebSocket
- Message Reference — every field of a WebSocket message
- Latest Listings — the same data as a web page
CryptoListing.ws is a technical data feed, not financial advice. See Legal.