A crypto price API has two jobs. One is to answer a question: what is Bitcoin worth, what did it do last week, what are the top 100 coins. The other is to keep a screen current while someone is looking at it. REST does the first. A WebSocket does the second. Most apps need both, and using one for the other is where the cost and the stale prices come from.
Coinranking’s REST endpoints return a snapshot. The coin list updates about once a minute. A WebSocket pushes a new aggregated price and 24-hour volume as soon as they are calculated. For a website that only displays those prices, Server-Sent Events are the preferred stream. The messages are the same. That comparison is in SSE vs WebSockets for real-time crypto prices. This post is the REST versus WebSocket choice.
What REST is for
A REST call is one request and one response. You ask for the coin list, a single coin, or a window of candles, and the connection closes.
curl "https://api.coinranking.com/v2/coins?uuids[]=Qwsogvtv82FCd&uuids[]=razxDUgYGNAdQ" \
-H "x-access-token: YOUR_API_KEY"Qwsogvtv82FCd is Bitcoin and razxDUgYGNAdQ is Ethereum. The response is the snapshot: price, market cap, 24-hour volume, rank, change, sparkline, and the UUID you will subscribe with later. History and candles are REST too. Price history goes back to 2010. OHLCV goes back to one-minute candles from December 2018, on /v2/coin/:uuid/ohlcv. How to request those candles is in how to get OHLC candlestick data. REST also takes a reference currency, so the same call can return prices in EUR or MYR. The WebSocket cannot. Rates are USD only.
REST is the right call for a page load, a search, a chart backfill, a daily report, and anything you run on a schedule. It is a poor way to keep a ticker live. Polling /coins every second does not make the data newer than the minute update, and it spends the call quota on repeated snapshots.
What the WebSocket is for
A WebSocket stays open. After the handshake, the server sends a rate when it has a new one. You do not ask again.
const ws = new WebSocket(
"wss://api.coinranking.com/v2/real-time/rates?x-access-token=YOUR_API_KEY"
);
ws.onopen = () => {
ws.send(JSON.stringify({
currencyUuids: ["Qwsogvtv82FCd", "razxDUgYGNAdQ"],
throttle: "1s"
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(data);
};
ws.onclose = () => {
// Reconnect with backoff, then send the subscription again.
};The browser WebSocket API cannot set headers, so the key goes on the query string. A server-side client should send x-access-token as a header instead, the same way REST does. A key in a page is visible to every visitor, so a public site should connect from its own server and relay the messages.
A rate message looks like this:
{
"type": "rate",
"currencyUuid": "Qwsogvtv82FCd",
"price": "125423.835504191964312353",
"volume": "6270550403.287645846237386287"
}The first message is a confirmation, not a price. It lists the UUIDs you subscribed to and the throttle. Ignore anything whose type is not rate if all you want is the tick.
One connection is one topic. Rates are the aggregated price and 24-hour volume. The other two paths are wss://api.coinranking.com/v2/real-time/exchange-rates and wss://api.coinranking.com/v2/real-time/tickers. You can subscribe in the URL, with currency-uuids[], or with the JSON message above, and you can change that message later without reconnecting. A connection with no subscription is accepted. It stays quiet until you send one.
throttle is 1s or 10s, and it applies per coin. The default is 1s. One connection takes at most 100 UUIDs.
The socket does not send the current price when it opens, and it does not replay anything you missed. It sends a heartbeat every 25 seconds. A deploy ends every open connection. Load the starting values from REST, then attach the socket.
The difference that matters
| REST | WebSocket | |
|---|---|---|
| Model | You ask, the server answers, the connection closes | You subscribe, the server pushes |
| Freshness | Coin list updates about once a minute | Pushed when a new rate is calculated |
| History and candles | Yes | No. Updates only, no snapshot on connect |
| Currencies | USD by default, or any reference currency | USD only |
| Change what you receive | Make another request | Send a subscription message |
| A dropped connection | Nothing to restore. Call again | Reconnect, then subscribe again |
| Best fit | Page load, search, charts, reports | Tickers, alerts, dashboards, bots watching a fixed set |
Use both
A price page should do three things, in this order.
- Fetch the coins you show, including price, name, icon, and UUID.
- Draw that snapshot. The page is useful before the first tick arrives.
- Open one WebSocket, subscribe to those UUIDs, and replace the price and volume as rate messages come in.
const KEY = "YOUR_API_KEY";
const ids = ["Qwsogvtv82FCd", "razxDUgYGNAdQ"];
const listed = await fetch(
"https://api.coinranking.com/v2/coins?" +
ids.map((id) => "uuids[]=" + id).join("&"),
{ headers: { "x-access-token": KEY } }
).then((response) => response.json());
const byId = new Map(listed.data.coins.map((coin) => [coin.uuid, coin]));
const ws = new WebSocket(
"wss://api.coinranking.com/v2/real-time/rates?x-access-token=" + KEY
);
ws.onopen = () => {
ws.send(JSON.stringify({ currencyUuids: ids, throttle: "1s" }));
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type !== "rate") return;
const coin = byId.get(message.currencyUuid);
if (coin) coin.price = message.price;
};For a chart, REST still does the heavy work. Request /v2/coin/Qwsogvtv82FCd/ohlcv?interval=hour&limit=200, draw the candles, and use the socket only to move the last point. Do not try to build history out of rate messages. A reconnect will leave a gap, and the socket will not fill it.
Which one to call
Use REST when the user is not waiting on the next tick. A market table that refreshes on load, a converter, a search box, a tax report, and a candlestick chart are all REST. So is a Notion dashboard that updates on a schedule, as in how to sync Coinranking API with Notion.
Use the WebSocket when the price should change while the page is open, and the client needs to change the subscription on the same connection. A watchlist the user edits, a backend process, and a bot that resubscribes as jobs come in are WebSocket jobs. Polling the coin list in a loop is the expensive version of the same idea, with older data.
Skip the WebSocket if you only need a price every few minutes. The REST snapshot is already on that cadence, and it includes market cap, rank, and change, which a rate message does not.
If the page only displays prices and never sends a subscription change, prefer Server-Sent Events over a WebSocket. EventSource reconnects on its own, and the feed is normal HTTP. The SSE docs cover that setup.
Bottom line
REST is the record. The WebSocket is the live edge of that record, for the cases where the client has to talk back. Load the coin list and the candles over REST, then subscribe to the UUIDs you already have. One connection, up to 100 coins. The full streaming picture is in the complete guide to real-time crypto price streaming. To compare providers, see the best crypto price streaming APIs in 2026.
Connection details are in the WebSocket docs and the real-time overview. The coin list is /v2/coins. Candles are the OHLCV endpoint.
REST works on a free key at coinranking.com/api. WebSockets are on the Professional plan, free for 30 days.




