Endpoints · v1 / Categories
Every category we track — "Layer 1", "Memes", "DeFi" — with its newest market aggregate: total market cap, 24-hour volume, how many coins are in it, its share of the categorised market, and the three coins inside it that moved most in the last 24 hours.
market is never null here. This is the opposite call from /exchanges, and worth
reading before you write a null check that will never fire: a category appears in this
response only if we hold a current aggregate for it, so a present item always has a present
market. See Which categories appear.
Query parameters
idcsv of integersUp to 100. Exact matchslugcsv of stringsUp to 100. Unique upstream — a single slug is a single-row lookup, unlike/exchanges. URL-encode it: see the warning belowpageinteger ≥ 1Page mode. Takes precedence overlimit/offsetsizeinteger 1–100Default20Page mode only. Over 100 is a400, not a truncationlimitinteger 1–100Default20Offset modeoffsetinteger ≥ 0Default0Offset mode. Max 100000sortid|name|slug|market_cap|volume_24h, optionally:asc/:descDefaultmarket_cap:descNotid:asc. See the note below
Filters are ANDed. There is no symbol — a category has no ticker — and sending one is
ignored, like any parameter this endpoint does not read.
⚠️ URL-encode
slugbefore you put it in a query string. Real slugs contain characters that a URL does not treat as data.lending-&-borrowingis a live category slug, and?slug=lending-&-borrowingis parsed as two parameters —slug=lending-plus a stray-borrowing— so you get a200with an empty list and no error at all. Send?slug=lending-%26-borrowing. Parentheses are safe but common too (bnb-smart-chain-(bep20)). Every HTTP client can do this for you; the failure is silent, so it is worth checking that yours did.
The default sort is different here, and on
/chains, from every other list in this API. The others default toid:asc; these two default tomarket_cap:desc. A leaderboard whose first page is ordered by whatever was catalogued first is not a leaderboard. Passsort=idexplicitly if you want the old behaviour.
sort=volumeis a400here./exchangesspells that keyvolume; on/categoriesand/chainsit isvolume_24h, because on these two endpoints every sort key is named after the field it orders by —market_caporders bymarket.market_cap, andvolume_24horders bymarket.volume_24h.
Which categories appear
A category is in the response when all three of these hold:
- it is live upstream (not disabled, not deleted);
- we hold at least one market snapshot for it; and
- its newest snapshot is within one hour of the newest snapshot in the whole table.
The third rule is what keeps abandoned groups off the board. Snapshots are written every ten
minutes for every group at once, so under normal operation this excludes nothing — 291 of 291
categories passed it when the rule was measured. It exists for the case where upstream stops
aggregating one particular group: that group keeps its old rows, stops being updated, and
would otherwise sit in a public ranking looking exactly like a live one. On /chains the same
rule removes three groups today.
Note what it does not do. The window is relative, so if upstream stops writing altogether,
every group ages together and the whole list is still returned — with numbers frozen at
whenever the last run happened. We log that condition on our side; there is nothing in the
response that marks it, and market.snapshot_time is what you should check if it matters to
you.
Response
Item fields
| Field | Type | Notes |
|---|---|---|
id |
number | The category id, a JSON number like the asset and exchange ids. Send it back to ?id= as-is. It is ours, not CoinMarketCap's — the same is true of the coin ids inside top_gainers, so do not use them against a CMC endpoint |
name / slug |
string | slug is unique upstream |
market |
object | Always present, never null — see above. Every key inside it is always present too |
market.market_cap |
string | Total market cap of the coins in this category, decimal(36,8) |
market.volume_24h |
string | Summed 24-hour volume of those coins — the same per-coin figure /quotes reports as volume |
market.coins_count |
number | How many coins are in the category |
market.market_cap_share |
string | A ratio between 0 and 1, not a percentage. Read the note below before using it |
market.snapshot_time |
string | When upstream computed this aggregate. RFC3339, UTC, whole seconds |
market.top_gainers |
array | Up to three coins, by 24-hour price change within this category, highest first. May be shorter than three, and may be empty — see below. Each entry is id (number), symbol, name, slug, logo |
What
market_cap_shareactually measures. It is this category's market cap divided by the sum of every categorised coin's market cap — and a coin that belongs to three categories is counted three times in that denominator. So the shares within one snapshot add up to 1, but each one is lower than the category's true share of the market, by roughly the average number of categories a coin belongs to.Two consequences worth stating plainly. It is not "dominance" in the usual sense — this is not BTC-dominance-style share of total crypto market cap, and it is not comparable with such a figure. And
/categoriesand/chainscompute their denominators separately, so a share on one is not comparable with a share on the other. If you want a true share of the whole market, dividemarket.market_capby/global'stotal_market_capyourself.
top_gainerscan be short. It carries at most three coins, and fewer when one of the coins upstream picked is no longer in our coin directory — a delisting between the snapshot and your request, for example. We drop such an entry rather than return a coin with no name. An empty array is a valid response; it does not mean the category is empty (coins_countanswers that).
Not implemented
description and title are not returned, nor is CoinMarketCap provenance (external_id,
source) or the internal display flags. title in particular is not a second name for the
category: it is the page heading our own website uses ("Top DeFi Tokens by Market
Capitalization"), filled in for five categories and equal to name for the rest — our
presentation copy rather than a property of the category. There is no logo: upstream has no image for a
category, and nothing to derive one from — /chains has one only because a chain has a
native coin. There is no rank field: the default market_cap:desc ordering reproduces it
exactly, and a stored rank would contradict its own position as soon as you changed the sort
or paged. There is no tvl, and that is not an oversight — upstream's column of that name
holds a copy of the market cap rather than a locked value. Volume change percentages (1h,
24h, 7d, 30d) are not in this version. Adding a field later is non-breaking; removing one is
not.
Examples
/categories reads id, slug, page, size, limit, offset and sort. Any other
parameter is ignored.
# Default listing: 20 categories, biggest market cap first
curl -H "X-Api-Key: <your-api-key>" \
"https://open-api.coinworldcap.com/openapi/v1/categories"
# One category by slug — unique upstream, so this is a lookup
curl -H "X-Api-Key: <your-api-key>" \
"https://open-api.coinworldcap.com/openapi/v1/categories?slug=layer-1"
# Busiest categories by 24-hour volume
curl -H "X-Api-Key: <your-api-key>" \
"https://open-api.coinworldcap.com/openapi/v1/categories?sort=volume_24h:desc&limit=10"
# Show the response headers, including X-Request-Id
curl -i -H "X-Api-Key: <your-api-key>" \
"https://open-api.coinworldcap.com/openapi/v1/categories?limit=1"
Anything other than a 200 is in Errors, which covers every endpoint here.