Stablecoin Earn Benchmark
The Bitcompare Earn Index — Stablecoin (bei-stable) is the citable market reference for what stablecoin yield pays: the median USDC/USDT lending APY across every servable provider, with CeFi and DeFi splits, a TVL-weighted DeFi variant, day/week/month deltas, and a daily print history that is never rewritten. It is a market number, not a single provider's quote.
The headline endpoint is anonymous and public — cite it freely. History is open to everyone for the most recent 90 days; full depth and per-print constituents are Earn Intelligence (Pro/Enterprise). The public methodology page is at bitcompare.net/stablecoin-earn-benchmark (it is landing alongside this release and is the methodologyUrl every response cites). Agents can call the same index as the stablecoin_earn_benchmark MCP tool.
Access and plan gating
| Plan | /benchmarks/stablecoin | /benchmarks/stablecoin/history depth | include=constituents |
|---|---|---|---|
| Anonymous (no key) | Full | Most recent 90 days (clamped: true if you asked for more) | Silently omitted |
| Free | Full | 90 days, clamped | Silently omitted |
| Starter | Full | 90 days, clamped | Silently omitted |
| Growth | Full | 90 days, clamped | Silently omitted |
| Pro | Full | Full depth, back to the first print | Returned |
| Enterprise | Full | Full depth, back to the first print | Returned |
Nothing on this page returns 403. The tier shows up as the clamped flag and the presence or absence of constituents. Pass your key as a Bearer token (see Authentication) to lift the clamp; issue one from your dashboard or compare plans at pro.bitcompare.net/pricing.
Methodology in brief
Methodology v1.0. The full specification lives on the methodology page; the points you need to read the numbers are:
- Constituent grain — one
(provider, symbol)pair is one vote. A provider offering both USDC and USDT contributes two constituents. - Median is the headline. It is robust to a single outlier promo rate. Mean, min, max, p25 and p75 are published alongside on every history print.
- Segments —
overall(every constituent, including hybrid platforms),cefi, anddefi. Hybrid platforms count inoverallonly. - Minimum constituents — 5 for
overall, 3 for each split. Below that, no print is published for that segment that day: a gap is the honest signal, never a thin number. - TVL-weighted rate — the
defisegment only, and only when at least 60% of the segment's constituents (and at least 3) carry on-chain TVL. CeFi has no TVL, and an "overall" TVL weight would be a DeFi-only number wearing the overall label, sotvlWeightedRateisnullforcefiandoverall. - Backfill is labelled. Prints before live daily computation began are reconstructed from historical rate data and carry
methodologyVersion: "v1.0-backfill"andbackfilled: true. The Coverage endpoint reports how many print days are live versus backfilled. - Provider attestation is activating. As providers attest to their terms through Bitcompare, their attested rates enter the constituent set with
provider_confirmedprovenance;coverage.providers.attestingtracks the count.
Headline
The latest print per segment, with deltas and a 30-point sparkline. Anonymous, no parameters, Cache-Control: public, max-age=300, s-maxage=900, stale-while-revalidate=3600.
Response properties
- Name
benchmarkKey- Type
- string
- Description
Always
"bei-stable".
- Name
name- Type
- string
- Description
Human-readable index name.
- Name
methodologyVersion- Type
- string
- Description
Methodology the latest live print was computed under, e.g.
"v1.0".
- Name
methodologyUrl- Type
- string
- Description
Public methodology page to cite alongside the number.
- Name
segments- Type
- array
- Description
One entry each for
overall,cefi,defi(a segment is absent on a day it did not print).
- Name
updatedAt- Type
- string
- Description
ISO 8601 instant this response was assembled.
Segment properties
- Name
segment- Type
- string
- Description
overall,cefi, ordefi.
- Name
day- Type
- string
- Description
YYYY-MM-DDof the latest print.
- Name
medianRate- Type
- number
- Description
The headline: median APY in percent.
- Name
tvlWeightedRate- Type
- number | null
- Description
TVL-weighted APY;
defionly,nullotherwise or when coverage is too thin.
- Name
constituentCount- Type
- integer
- Description
Number of
(provider, symbol)votes in the print.
- Name
providerCount- Type
- integer
- Description
Distinct providers among the constituents.
- Name
dayChange- Type
- number | null
- Description
medianRateminus the print one day earlier, in percentage points.nullwhen no comparable print exists.
- Name
weekChange- Type
- number | null
- Description
Same, versus seven days earlier.
- Name
monthChange- Type
- number | null
- Description
Same, versus thirty days earlier.
- Name
sparkline- Type
- array
- Description
The last 30 daily prints as
{ day, medianRate, backfilled }, oldest first.
Request
curl https://api.bitcompare.net/api/v1/benchmarks/stablecoin
Response (captured 2026-09-16, sparklines trimmed)
{
"data": {
"benchmarkKey": "bei-stable",
"name": "Bitcompare Earn Index — Stablecoin (BEI-Stable)",
"methodologyVersion": "v1.0",
"methodologyUrl": "https://bitcompare.net/stablecoin-earn-benchmark",
"segments": [
{
"segment": "overall",
"day": "2026-09-15",
"medianRate": 5.00427767,
"tvlWeightedRate": null,
"constituentCount": 33,
"providerCount": 19,
"dayChange": 0.04820470999999937,
"weekChange": 0.22427766999999932,
"monthChange": null,
"sparkline": [
{ "day": "2026-08-17", "medianRate": 4.25, "backfilled": false },
{ "day": "2026-08-18", "medianRate": 4.5753355, "backfilled": false },
{ "day": "2026-08-19", "medianRate": 4.80378808, "backfilled": false },
"… 30 daily points, oldest first …",
{ "day": "2026-09-15", "medianRate": 5.00427767, "backfilled": false }
]
},
{
"segment": "cefi",
"day": "2026-09-15",
"medianRate": 11.5,
"tvlWeightedRate": null,
"constituentCount": 13,
"providerCount": 8,
"dayChange": 0,
"weekChange": 0,
"monthChange": null,
"sparkline": [
{ "day": "2026-08-17", "medianRate": 10.22, "backfilled": false },
{ "day": "2026-08-18", "medianRate": 10.5, "backfilled": false },
{ "day": "2026-08-19", "medianRate": 10.95, "backfilled": false },
"… 30 daily points, oldest first …",
{ "day": "2026-09-15", "medianRate": 11.5, "backfilled": false }
]
},
{
"segment": "defi",
"day": "2026-09-15",
"medianRate": 4.50033326,
"tvlWeightedRate": 17.977598863526225,
"constituentCount": 20,
"providerCount": 11,
"dayChange": 0.31202529499999976,
"weekChange": 0.9057847599999995,
"monthChange": null,
"sparkline": [
{ "day": "2026-08-17", "medianRate": 3.3763116, "backfilled": false },
{ "day": "2026-08-18", "medianRate": 3.362756465, "backfilled": false },
{ "day": "2026-08-19", "medianRate": 3.95733107, "backfilled": false },
"… 30 daily points, oldest first …",
{ "day": "2026-09-15", "medianRate": 4.50033326, "backfilled": false }
]
}
],
"updatedAt": "2026-09-16T02:37:51.135Z"
}
}
History
The daily print series for one segment, oldest first. Without a key, or on Free/Starter/Growth, the window is clamped to the most recent 90 days counted from today — not from to — so the archive cannot be paged in 90-day steps. Pro and Enterprise keys get the full series back to the first print.
Optional attributes
- Name
segment- Type
- string
- Description
overall(default),cefi, ordefi.
- Name
from- Type
- string
- Description
YYYY-MM-DDstart day, inclusive. Defaults to 90 days beforeto. Clamped on non-Intelligence plans.
- Name
to- Type
- string
- Description
YYYY-MM-DDend day, inclusive. Defaults to today.
- Name
include- Type
- string
- Description
constituentsto attach each print's frozen constituent list. Intelligence tier only; silently ignored otherwise.
Response properties
- Name
benchmarkKey- Type
- string
- Description
Always
"bei-stable".
- Name
segment- Type
- string
- Description
The segment you asked for.
- Name
prints- Type
- array
- Description
One print per day, ascending. Each carries
day,methodologyVersion,medianRate,tvlWeightedRate,meanRate,minRate,maxRate,p25Rate,p75Rate,constituentCount,providerCount,tvlCoveredCount,backfilled, and — on the Intelligence tier withinclude=constituents—constituents.
- Name
count- Type
- integer
- Description
Number of prints returned.
- Name
clamped- Type
- boolean
- Description
truewhen yourfromwas moved forward to the 90-day floor. If you see this on a paid key, the key's plan does not include Earn Intelligence.
Responses carry Vary: Authorization, and Cache-Control is public, max-age=900 for clamped tiers and private, max-age=300 for the Intelligence tier.
Request
curl -G https://api.bitcompare.net/api/v1/benchmarks/stablecoin/history \
-d segment=overall \
-d from=2026-01-01
Response (anonymous, captured 2026-09-16, prints trimmed)
{
"data": {
"benchmarkKey": "bei-stable",
"segment": "overall",
"prints": [
{
"day": "2026-06-18",
"benchmarkKey": "bei-stable",
"segment": "overall",
"methodologyVersion": "v1.0-backfill",
"medianRate": 4.7406498599999995,
"tvlWeightedRate": null,
"meanRate": 5.5568166346153856,
"minRate": 0.01,
"maxRate": 12,
"p25Rate": 3.121655,
"p75Rate": 8.4778,
"constituentCount": 26,
"providerCount": 16,
"tvlCoveredCount": 0,
"backfilled": true
},
"… 89 prints, oldest first …",
{
"day": "2026-09-15",
"benchmarkKey": "bei-stable",
"segment": "overall",
"methodologyVersion": "v1.0",
"medianRate": 5.00427767,
"tvlWeightedRate": null,
"meanRate": 10.140602731212121,
"minRate": 0.01,
"maxRate": 73.99068834,
"p25Rate": 3.89749917,
"p75Rate": 12,
"constituentCount": 33,
"providerCount": 19,
"tvlCoveredCount": 13,
"backfilled": false
}
],
"count": 89,
"clamped": true
}
}
Constituents
Every print freezes the exact list of (provider, symbol) rates that went into it, so any published number can be reproduced. On the Intelligence tier, include=constituents attaches that list to each print in the history response. The list is served as frozen — later corrections to a provider's rate do not alter a past print.
Constituent properties
- Name
provider- Type
- string
- Description
Provider slug.
- Name
symbol- Type
- string
- Description
USDCorUSDT.
- Name
rate- Type
- number
- Description
The lending APY that constituent contributed, in percent.
- Name
platformType- Type
- string
- Description
cefi,defi, orhybrid.
- Name
tvlUsd- Type
- number | null
- Description
On-chain TVL in USD at print time;
nullfor CeFi.
- Name
source- Type
- string
- Description
Where the rate came from — a collection method such as
pull_api,onchain, orprovider_confirmed.
A print with constituents (shape)
{
"day": "2026-09-15",
"benchmarkKey": "bei-stable",
"segment": "defi",
"methodologyVersion": "v1.0",
"medianRate": 4.50033326,
"tvlWeightedRate": 17.977598863526225,
"meanRate": 9.87,
"minRate": 0.01,
"maxRate": 73.99068834,
"p25Rate": 2.41,
"p75Rate": 8.9,
"constituentCount": 20,
"providerCount": 11,
"tvlCoveredCount": 13,
"backfilled": false,
"constituents": [
{
"provider": "aave-v3",
"symbol": "USDC",
"rate": 4.81,
"platformType": "defi",
"tvlUsd": 812340000,
"source": "onchain"
},
{
"provider": "morpho",
"symbol": "USDT",
"rate": 5.62,
"platformType": "defi",
"tvlUsd": 143900000,
"source": "onchain"
}
]
}
Errors
- Name
422 VALIDATION_ERROR- Description
from/tonotYYYY-MM-DD, an impossible calendar date, an unknownsegment, or anincludevalue other thanconstituents.
- Name
429 RATE_LIMIT_EXCEEDED- Description
Anonymous calls share the per-IP Free budget (30 req/min). Pass a key to use your plan's budget. See Rate Limiting.
There is no 403 on these endpoints — a non-Intelligence caller gets the clamped series instead. The full error envelope is described on the Errors page.
422 VALIDATION_ERROR
{
"error": {
"message": "from/to must be real calendar dates (YYYY-MM-DD)",
"code": "VALIDATION_ERROR"
}
}
See also
- Methodology: bitcompare.net/stablecoin-earn-benchmark — the public specification every response cites
- Coverage — live versus backfilled print days, constituent and attestation counts
- Rate Changes — the observation log the index is computed from
- Earn Products — the terms behind each constituent's rate
- Stablecoin Index — peg stability, a different index
- MCP Tool Catalog —
stablecoin_earn_benchmarkfor agents