ChainRegistry
All coins
04:20:21Z · 12/12 VENUES · SNAPSHOT 9fcdd61f BTC$76,828.24-2.22% ETH$2,251.85-2.39% USDT$0.9985-0.03% BNB$696.09-2.54% XRP$1.25-0.39% SOL$92.17-3.45% TRX$0.3211+2.09% STETH$2,264.29-2.10% ZEC$1,135.38-11.32% HYPE$83.41-5.84% DOGE$0.0741-2.61% XMR$606.55+0.56% USDS$1.00-0.06% WBTC$76,761.23-2.34% WBT$73.83-1.81% LEO$9.33-0.81% LINK$11.13-2.37% ADA$0.1883-2.58% XLM$0.162-4.20% BCH$274.39-3.80% NEAR$3.84-10.66% USDE$0.99970.00% DAI$0.99990.00% RAIN$0.006349+7.23%

Ref. API · v1

The registry, as JSON

The coins, exchanges, prices and daily history behind this site, through an open API. Reading needs no key and no sign-up.

EndpointsOpen /stats

Price feedFresh

04:20:21UTC Last markets run

Last read 2 minutes ago. 12 venues answered in the last two hours. The sync runs every five minutes; /up/data calls the feed stale after 20 minutes without a run.

Base URL
https://chainregistry.net/api/v1
Key
None to read
Limit
120 requests a minute per IP address
Caching
60 seconds and an ETag on most reads
Browsers
CORS open to any site
Format
JSON, US dollars, UTC

Start here

Every route lives under https://chainregistry.net/api/v1. Send Accept: application/json and you get JSON back, errors included. This is the registry's headline reading:

Request
curl "https://chainregistry.net/api/v1/stats" -H "Accept: application/json"
Responsechainregistry.net, Oct 26, 2026 at 12:24 UTC
{
  "data": {
    "updated_at": "2026-10-26T12:20:45Z",
    "coins_ranked": 2155,
    "venues_live": 11,
    "venues_total": 12,
    "market_cap": 2708778581796.619,
    "volume_24h": 12628536326.38349,
    "btc_dominance": 59.57,
    "history_from": "2013-03-31"
  }
}
  • A list comes as {"data": [...], "meta": {"page", "per_page", "total", "last_page"}}; ask for the next one with ?page=2. A single thing comes as {"data": {...}}.
  • Prices, caps and volumes are plain numbers in US dollars, and null when the registry has no figure.
  • Changes are percentages: -0.21 means down 0.21%.
  • Times are ISO 8601 in UTC, like 2026-10-26T12:20:45Z. Days are written 2026-10-26.
  • Prices are volume-weighted across the exchanges the registry reads every five minutes. None of it comes from a market-data aggregator.

Limits

Each IP address gets 120 requests a minute, all routes together. Some routes also keep a count of their own, with a lower limit:

Routes with a limit of their own
RouteLimit
GET /search 60 a minuteper IP address
POST /auth/register 5 a minuteper IP address
POST /auth/login 10 a minuteper IP address
POST /auth/forgot 5 a minuteper IP address
POST /coins/{}/vote POST /watchlist/{} DELETE /watchlist/{} 60 a minuteper member
POST /posts 10 a minuteper member
POST /posts/{}/replies 20 a minuteper member
POST /posts/{}/report POST /replies/{}/report 10 a minuteper member
POST /devices 10 a minuteper IP address
PATCH /devices/me DELETE /devices/me GET /alerts POST /alerts DELETE /alerts/{} 30 a minuteper device key

Every answer carries X-RateLimit-Limit and X-RateLimit-Remaining for the limit that applies to it. Past the limit you get 429 with Retry-After, the seconds to wait. Failed requests count too: a 401 or a 404 uses up a request like any other. In a browser on another site, CORS keeps those headers from your script, so watch for the 429 itself.

Caching

The figures change with the five-minute sync, so most reads say you can keep their answer for 60 seconds: Cache-Control: public, max-age=60 and an ETag. Send the ETag back as If-None-Match and you get an empty 304 Not Modified until something changes. A 304 still counts toward the limit.

Headers of the /stats answerchainregistry.net, Oct 26, 2026 at 12:24 UTC
HTTP/2 200
content-type: application/json
cache-control: max-age=60, public
etag: "1e46cfbed4526354674177bf74596641"
x-ratelimit-limit: 120
x-ratelimit-remaining: 119
access-control-allow-origin: *

Left out: the security headers every page sends.

Request
curl -i "https://chainregistry.net/api/v1/stats" -H 'If-None-Match: "1e46cfbed4526354674177bf74596641"'

/coins and /coins/{slug} cache the same way when you send no token. With a token, the body carries your own votes, so the answer is private, and Vary: Authorization says so. Search, the community, your account and alerts aren't cached. Each endpoint below shows how long its answer keeps.

Errors

An error is JSON with a message. When the input doesn't validate, errors says what's wrong with each field:

GET /search without qchainregistry.net, Oct 26, 2026 at 12:38 UTC
{"message": "The q field is required.", "errors": {"q": ["The q field is required."]}}
Error statuses
StatusWhenBody
401No token, or one that has been revoked. On the alert routes: no device key, or one the registry doesn't know.{"message": "Unauthenticated."} {"message": "Unknown device. Register it first."}
403The account is suspended, and its tokens are revoked with it. Removing someone else's post or reply is a 403 too.{"message": "This account has been suspended."}
404Nothing there: an unknown or hidden coin, a venue the registry doesn't read, a mistyped path.{"message": "Not found."}
405The route exists, but not for that method. Allow lists the ones it takes.{"message": "Method not allowed."}
422The input didn't validate.{"message": "…", "errors": {…}}
429Too many requests. Wait Retry-After seconds.{"message": "Too Many Attempts."}

Members and devices

Reading is open. Voting, posting, reporting, the watchlist and your own account need a member token. Sign in with your email address or username, and name the device the token is for:

Request
curl -X POST "https://chainregistry.net/api/v1/auth/login" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "your password", "device_name": "my laptop"}'

The answer holds a token and your profile. Send the token as Authorization: Bearer <token>; the examples below read it from $TOKEN. Tokens don't expire. POST /auth/logout revokes the one you used, and changing your password revokes all the others. When an account is suspended, its tokens stop working.

Price alerts belong to a phone, not to an account. An app registers with POST /devices and its Expo push token, gets a device_key back once, and sends it as X-Device-Key to /alerts and /devices/me; the examples read it from $DEVICE_KEY. An alert fires once, as a push notification, shortly after the sync that crosses its price.

Endpoints

The endpoint list isn't available right now: the file it's built from didn't load. Everything above still holds.

Live prices

The figures that refresh on this site's pages come from /api/live: the latest reading for up to 120 coins in one request. It's made for these pages, so it sits outside v1 and keeps its field names short. CORS covers /api/v1 only, so browser apps on other origins can't use it; call it from a server instead. For anything you mean to keep, use v1.

curl "https://chainregistry.net/api/live?coins=bitcoin,ethereum" -H "Accept: application/json"
Response
{
  "at": "2026-10-26T12:20:45Z",
  "coins": {
    "bitcoin": {
      "p": 80265.34069075,
      "c1": -0.0828,
      "c24": -0.20959655176109,
      "c7": -2.7871,
      "cap": 1613616224158.4,
      "vol": 4475175777.2506,
      "r": 1
    }
  }
}

Bitcoin at the 12:20:45 UTC reading of Oct 26, 2026: the figures of the /coins example, under this route's short names.

at is when the last markets run finished, and null before the first one. Each coin has p, its price in US dollars; c1, c24 and c7, its change over an hour, a day and a week in percent; cap, vol and r, its rank. A figure the registry doesn't have is null. Pass the slugs as ?coins=a,b or as a coins[] list. Unknown slugs are ignored, and so are hidden coins and coins that aren't ranked or haven't been priced in two days. The answer is the same for everyone and keeps for 30 seconds; send its ETag back as If-None-Match for a 304. Each IP address gets 120 requests a minute here.

Share cards

Every coin has a share card: a 1200 × 630 JPEG with its price, 24-hour change, rank, market cap and volume, stamped with the time of the reading. Link previews use it, and you can put it on any page:

HTML
<a href="https://chainregistry.net/coins/bitcoin">
  <img src="https://chainregistry.net/coins/bitcoin/card.jpg" width="600" height="315" alt="Bitcoin's price on ChainRegistry">
</a>

Swap bitcoin for any coin's slug, the last part of its address here. A card is drawn again once it's 10 minutes old, and sent with Cache-Control: public, max-age=600. Card images are limited to 30 a minute per IP address; every visitor's browser fetches its own, so a busy page is fine. If a card can't be drawn, the same address answers with the site's brand card.

Bitcoin's share card: its price, 24-hour change, rank, market cap and volume, with the time of the reading.
The card as it is now, drawn from the latest reading.

Health check

For an uptime monitor, use /up/data. It answers 200 with "status": "fresh" while the last markets run is under 20 minutes old, and 503 with "status": "stale" after that, so a plain HTTP check catches a stalled feed. It's never cached. Plain /up only tells you the app is answering.

curl -i "https://chainregistry.net/up/data"
Responsechainregistry.net, Oct 26, 2026 at 12:25 UTC
{"status": "fresh", "markets_age_seconds": 259, "last_markets_run": "2026-10-26T12:20:45Z", "venues_live": 12}

markets_age_seconds is how long ago that run finished, and venues_live counts the exchanges the registry read without an error in the last two hours. The instrument at the top of this page shows the same reading, refreshed every minute.