Endpoints · v1 / Exchanges
The exchange directory: name, slug, logo, links and fees for every exchange we track, and — where we have it — a 24-hour aggregate: volume, number of markets, number of coins, and when that aggregate was taken.
An exchange with no aggregate is still in the response, with "market": null. This is
the opposite call from /quotes, deliberately: there the subject is the price, so a coin
with no price is not a quote; here the subject is the exchange, and one we have no volume
for is still an exchange.
Query parameters
idcsv of integersUp to 100. Exact matchslugcsv of stringsUp to 100. Not unique upstream — treat it as a filter, not a lookuppageinteger ≥ 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|volume, optionally:asc/:descDefaultid:ascvolumesorts onmarket.volume_24h; exchanges withmarket: nullsort last on:descand first on:asc
Filters are ANDed. There is no symbol — exchanges have no ticker — and sending one is
ignored, like any parameter this endpoint does not read. sort=symbol is a 400.
Response
Item fields
| Field | Type | Notes |
|---|---|---|
id |
number | The exchange id, a JSON number like the asset id — see the note under /assets. Send it back to ?id= as-is |
name / slug / logo |
string | logo is a CoinMarketCap image URL, as on /assets |
links |
object | Always present. Six keys, each a string, empty when we have no such link. New link kinds may be added here; the object is the extension point |
fees |
object | Always present. maker and taker are strings — decimal(12,8) upstream — and "0" means a zero fee, not "unknown" |
market |
object or null |
null when we hold no aggregate for this exchange. When present, all four keys are present and carry a value — the four columns are NOT NULL upstream (db/schema-snapshots/exchange_markets.sql, 2026-09-17), so a present market has no holes in it — with one exception we make ourselves: data_time is null when upstream stored the zero datetime (0000-00-00 00:00:00, what a NOT NULL column with no DEFAULT receives from a write that omits it), because "0001-01-01T00:00:00Z" is a parseable timestamp and a false one. We log that case. Any other null inside market would mean upstream relaxed a constraint — possible, not expected |
market.volume_24h |
string or null |
24-hour volume in USD, decimal(20,8) |
market.markets_count / market.coins_count |
number or null |
Plain integers |
market.data_time |
string or null |
When the aggregate was taken. RFC3339, UTC, whole seconds, trailing Z — the format every timestamp in this API uses. null when upstream stored no usable time (the market row above) — never a placeholder date |
slugis not unique here, unlike the asset slug. Upstream's only unique index is onname(db/schema-snapshots/exchange_infos.sql, 2026-09-17), so?slug=xcan in principle return several rows. That snapshot also confirms the column isvarchar(3000)with no index at all — too wide for one under InnoDB's key-prefix limit — so?slug=is a full table scan. At 276 exchanges that is invisible; if the table grows we will say so here before it matters. Matching is case-insensitive and the value is passed through exactly as you send it — the comparison is the column's own collation (utf8mb4_unicode_ci), so?slug=Binanceand?slug=binancereturn the same rows, as on/assets.
Not implemented
description, register_url and country are not returned. register_url is never
populated — no row had a non-empty one on the 2026-09-17 snapshot — and country does not
exist upstream at all. description is a different case and the earlier wording here was
wrong: it said the text arrives truncated to 100 characters, and measurement disproved that
(262 of 276 rows are non-empty, the longest is 5436 characters, 250 are over 100). The prose
is intact; it is simply not part of this first version of the endpoint. Rank, score and
weekly visits are not returned either. Adding a field later is non-breaking; removing one is
not.
Examples
/exchanges reads id, slug, page, size, limit, offset and sort. Any other
parameter is ignored.
# Default listing (20 items, sorted by id ascending)
curl -H "X-Api-Key: <your-api-key>" \
"https://open-api.coinworldcap.com/openapi/v1/exchanges"
# Biggest exchanges by 24-hour volume; those with no aggregate come last
curl -H "X-Api-Key: <your-api-key>" \
"https://open-api.coinworldcap.com/openapi/v1/exchanges?sort=volume:desc&limit=10"
# Look up specific exchanges by id
curl -H "X-Api-Key: <your-api-key>" \
"https://open-api.coinworldcap.com/openapi/v1/exchanges?id=255,301"
# Show the response headers, including X-Request-Id
curl -i -H "X-Api-Key: <your-api-key>" \
"https://open-api.coinworldcap.com/openapi/v1/exchanges?limit=1"
Anything other than a 200 is in Errors, which covers every endpoint here.