Draft for discussion · July 2026
Stablecoins API v2
A smaller, clearer public API for stablecoin assets, chains, and historical data. The same contract should work for the DefiLlama app and for API users building something entirely different.
Summary
The proposal has three current-data resources and three historical resources. Global and
chain pages use the same endpoints; adding chain only changes the scope.
Historical data uses [timestamp, value] tuples, with Unix timestamps in
seconds as JSON numbers.
Responses contain data and identity metadata, not ECharts options or frontend view names. Total, breakdown, dominance, pie, bar, and treemap are presentations of these resources—not separate API concepts.
Endpoint reference
This is the proposed surface area. Parameters not listed for an endpoint are not accepted;
unsupported parameters or combinations return 400 rather than being
silently ignored.
Current data
| Endpoint | Parameters | Returns |
|---|---|---|
GET /v2/assets |
chain?: stringCanonical chain slug. Omit for global data. |
Asset identities and their current snapshot in the requested scope. |
GET /v2/assets/:asset |
:asset: stringRequired canonical asset slug. No query parameters. |
One asset, its current global snapshot, and current values by chain. |
GET /v2/chains |
None. | Chain identities and current stablecoin snapshots. |
Historical data
Scope and grouping are separate. chain=ethereum limits the dataset;
groupBy=asset splits that dataset into asset series.
Omit groupBy for one total; add it for the complete breakdown.
Scope one asset or chain directly instead of sending a list of selections.
| Endpoint | Scope parameters | groupBy values |
Endpoint-only parameters |
|---|---|---|---|
GET /v2/history/market-cap |
chain? · asset? |
asset · chain |
None. |
GET /v2/history/volume |
chain? · asset? |
asset · chain · pegCurrency |
None. |
GET /v2/history/supply |
asset required · chain? |
chain |
includeUnreleased?: boolean, default false. |
Combination rule: a request cannot scope and group by the same dimension.
For example, chain=ethereum&groupBy=chain is invalid because the result could
only contain Ethereum. chain=ethereum&groupBy=asset is valid. Supplying both
chain and asset returns the total for that exact intersection.
Date parameters accepted by every history endpoint
| Parameter | Type | Default | Meaning |
|---|---|---|---|
start |
Unix seconds | First available point | Inclusive start of the requested range. Must be a JSON-safe integer. |
end |
Unix seconds | Latest available point | Inclusive end of the requested range. Must be a JSON-safe integer. |
Example requests
GET /v2/history/market-cap
Global market-cap total
GET /v2/history/market-cap?chain=ethereum
Ethereum market-cap total
GET /v2/history/market-cap?asset=tether
Tether market-cap history across all chains
GET /v2/history/volume?groupBy=pegCurrency&start=1735689600&end=1767225600
Global volume by peg currency for an explicit time range
GET /v2/history/supply?asset=tether&groupBy=chain
Tether supply history split by chain
Legacy to v2
The v2 URLs name the resource being requested. Legacy implementation names, special
all values, numeric IDs, and frontend chart modes stay out of the public contract.
| Use case | Legacy | Proposed v2 |
|---|---|---|
| Asset directory | GET /stablecoins |
GET /v2/assets |
| Chain-scoped assets | GET /stablecoins + /stablecoincharts2/:chain |
GET /v2/assets?chain=ethereum |
| Asset detail | GET /config → /stablecoin/:numericId |
GET /v2/assets/tether |
| Market-cap history | GET /stablecoincharts2/all-llama-app |
GET /v2/history/market-cap |
| Market cap by asset | breakdown inside a 36 MB response |
GET /v2/history/market-cap?groupBy=asset |
| Volume by currency | GET /chart/volume/currency-breakdown |
GET /v2/history/volume?groupBy=pegCurrency |
Response shape
The current app proxy converts upstream records into chart-library configuration. The v2 API should stop at a portable data contract and let each client decide how to render it. There are only three shapes to learn: a current-data list, a historical total, and a grouped historical response.
Grouped history
GET /v2/history/market-cap?chain=ethereum&groupBy=asset
A series is simply one returned line: one asset when groupBy=asset, one chain
when groupBy=chain, or one currency when groupBy=pegCurrency.
Timestamps and values are JSON numbers. The request URL already describes the metric,
scope, grouping, and selection, so the response does not repeat them.
Historical total
GET /v2/history/market-cap?chain=ethereum
{
"unit": "usd",
"data": [
[1728345600, 137000000000],
[1728432000, 137500000000]
]
}
Current asset list
GET /v2/assets?chain=ethereum
{
"assets": [
{
"id": 1,
"slug": "tether",
"name": "Tether",
"symbol": "USDT",
"pegCurrency": "USD",
"circulatingUsd": 119000000000
}
]
}
The complete selector data comes from /v2/assets or /v2/chains.
A grouped request returns every matching series. For one asset or chain, use the singular
asset or chain scope. The frontend can filter a complete breakdown
locally or combine individually cached histories; the API does not accept arbitrary
selection lists or create an “Other” series.
Keeping responses small
Measurements below are rough, uncompressed JSON estimates captured on July 27, 2026. They are useful for comparing shapes, not performance guarantees.
| Payload | Current | Proposed | Change |
|---|---|---|---|
| Global market-cap total | 36 MB | ~35 KB | ~99.9% smaller |
| Full asset breakdown | 36 MB | ~6.6 MB | ~81.7% smaller |
| Asset directory + snapshots | Separate responses | ~115 KB | No history embedded |
| One asset detail | Mixed config + metadata | TBD | No history embedded |
Full breakdowns are cacheable and compressible. A client that needs only one asset or chain can use the singular scope instead. Date ranges reduce transfer size further without introducing frontend selection concepts into the API.
How the app would use it
Pie, horizontal bar, and treemap views read current table data. Historical endpoints power
total, breakdown, and dominance views. The API never receives names such as
treemap or dominance.
/stablecoins and /stablecoins/:chain
| UI data | Request |
|---|---|
| Asset table, pie, HBar, treemap | GET /v2/assets[?chain=:chain] |
| Market-cap total | GET /v2/history/market-cap[?chain=:chain] |
| Market-cap breakdown and dominance | GET /v2/history/market-cap?groupBy=asset[&chain=:chain] |
| Volume total | GET /v2/history/volume[?chain=:chain] |
| Volume by token | GET /v2/history/volume?groupBy=asset[&chain=:chain] |
| Volume by chain | GET /v2/history/volume?groupBy=chain (global page only) |
| Volume by peg currency | GET /v2/history/volume?groupBy=pegCurrency[&chain=:chain] |
| USD and token inflows | Not included in v2 until the calculation is defined. |
/stablecoins/chains
| UI data | Request |
|---|---|
| Chain table, pie, HBar, treemap | GET /v2/chains |
| Market-cap total | GET /v2/history/market-cap |
| Market cap by chain | GET /v2/history/market-cap?groupBy=chain |
| Volume total and breakdowns | GET /v2/history/volume[?groupBy=chain|pegCurrency] |
/stablecoin/:asset
| UI data | Request |
|---|---|
| Metadata and current chain distribution | GET /v2/assets/:asset |
| Supply total | GET /v2/history/supply?asset=:asset |
| Supply by chain | GET /v2/history/supply?asset=:asset&groupBy=chain |
| Volume total and by chain | GET /v2/history/volume?asset=:asset[&groupBy=chain] |
Decisions in this draft
- Identity
- Stable URL slugs are public identifiers. Immutable internal IDs remain in responses for joins and migrations.
- Global scope
- Omitting
chainmeans global. There is noallorall-llama-appsentinel. - Time
- Unix timestamps remain seconds on the wire and are always JSON numbers.
startandendare inclusive. - Units
- Historical responses state their unit once, such as
"unit": "usd". Values are raw numbers, never preformatted strings. - Missing values
nullmeans unknown or unavailable. Zero means a measured value of zero; the two are never interchangeable.- Presentation
- Colors, encodes, stacks, tooltip settings, and UI view names belong to clients—not the API response.
- Cache units
- Cache totals, complete breakdowns, and singular asset or chain histories. The API does not create cache entries for arbitrary selector combinations.
Still to decide
- Market-cap semantics: confirm whether the source is price-adjusted market cap or circulating supply expressed in USD; rename the endpoint and fields if “market cap” is inaccurate.
- Net flows: define whether this means daily deltas, rolling sums, or transfer-derived flows before proposing an endpoint name or response.
- Double counting: what is the canonical treatment of bridged representations in global totals and chain breakdowns?
- Unreleased supply: is
includeUnreleasedenough, or should released and unreleased amounts always be separate named series? - Incomplete periods: should the latest partial day be returned with an explicit completeness flag, or omitted until final?
- Large breakdowns: should an unfiltered grouped response always return every series, and what response-size safeguards are needed?
- Rollout: deprecation window, cache headers, rate limits, and whether legacy URLs redirect or run in parallel.