Data providers
CoinGecko, CoinMarketCap, failover.
Where prices, charts and coin data come from, how the backend stays inside each provider's free tier, and when you need a key or a paid plan.
01Sources
All market data is real public data, fetched by the backend only. The keys stay in config/private; the app never sees them.
| Provider | Used for | Key |
|---|---|---|
| CoinGecko, Public plan | Markets, global market, coin detail, charts, exchange tickers, search, trending, fiat exchange rates, the coin list with contract addresses (for wallet tokens) | None (keyless) |
| CoinGecko, Demo plan | The same, with a higher rate limit | Free Demo key from coingecko.com/en/developers/dashboard |
| CoinGecko, Pro plan | The same, on pro-api.coingecko.com | Paid Pro key |
| CoinMarketCap | Failover for the markets list and the global market | Required for CoinMarketCap: from pro.coinmarketcap.com/account |
Enter both in the console under Data providers. The Test button calls CoinGecko /ping (Demo) or /key (Pro) and CoinMarketCap /v1/key/info.
CoinGecko and CoinMarketCap each have their own API terms, attribution rules and plan limits, including rules for commercial apps. Read them and pick the plan that fits your use. Paid plans are billed by the provider to you and are not part of this purchase.
02Primary provider and failover
- Primary: CoinGecko (default) or CoinMarketCap.
- Failover (on by default): on an upstream error, an 8-second timeout, an HTTP 429 or an exhausted budget, the other provider is tried for the endpoints it supports.
- Charts, tickers, coin descriptions and links, and trending are CoinGecko-only. CoinMarketCap's free plan has no price history. With CoinGecko down these answer from the last cache, then
503 chart_unavailable. - If both providers fail, the last cached value is served with
"stale": true. With nothing cached the API answers503 upstream_unavailable. - CoinMarketCap rows are mapped to CoinGecko ids by slug, then by symbol and name, so the app sees one id per coin. CoinMarketCap rows have no 7-day sparkline.
- Implausible totals are dropped, not shown. If a provider reports a total 24-hour volume above the total market cap (seen in CoinGecko's
/global), the API returns no volume and the app shows "—" instead of the wrong figure (plausibleVolumeinfirebase/functions/src/api/market.ts).
03Budgets
Every upstream call first takes a token from a per-minute bucket and checks the monthly budget. Over budget counts like an error and triggers the failover. Usage is counted per provider and month (console page Provider usage).
| Setting | Default | Meaning |
|---|---|---|
| CoinGecko calls per minute (most) | 0 = the plan's limit | The backend uses 8 (Public), 25 (Demo) or 400 (Pro) when this is 0. Set a number to stay below. |
| CoinGecko calls per month (most) | 0 = the plan's default | 10,000 on the Demo plan, no cap otherwise. |
| CoinMarketCap calls per minute (most) | 25 | — |
| CoinMarketCap credits per month (most) | 10,000 | 0 = no cap. The free Basic plan allows 10,000. |
Source: firebase/functions/src/api/providers.ts, admin/src/manifest.ts.
04Caching
Everything is fetched once in USD and converted to the requested currency with the fiat rates, so one markets call (per_page=250, with sparklines) serves every page up to 250 coins and every currency. Responses are cached in memory and in Firestore (cache/*), concurrent requests for the same data share one upstream call, and public responses carry Cache-Control: s-maxage for a CDN.
| Cache (console field) | Default, seconds |
|---|---|
| Markets list | 60 |
| Global market | 120 |
| Coin detail | 600 |
| Charts 1h / 24h | 300 |
| Charts 7d and longer | 3600 |
| Exchange tickers | 600 |
| Search | 3600 |
| Trending | 600 |
| Fiat rates | 600 |
| Coin list with contracts | 86400 |
Each value can be set from 10 seconds to 7 days. Shorter caches mean fresher data and more upstream calls.
05Free tiers in practice
- CoinGecko keyless allows roughly 5 to 15 calls per minute; the backend's default bucket is 8 per minute. Fine for testing and a small audience. For a production app use at least a free CoinGecko Demo key.
- On the Public and Demo plans CoinGecko serves only 365 days of history, so the All chart range returns the last year and the response says
"limitedTo":"1y". - CoinMarketCap Basic (free): 10,000 credits per month and 30 calls per minute. The backend budgets 25 per minute and 10,000 credits by default and uses it only as the failover.
- Fiat currencies come from CoinGecko's exchange rates. The app offers the fiats you list in the console (30 by default) that the provider also prices.
06Attribution
Market data is provided by CoinGecko and, as the failover, CoinMarketCap. Coin images are loaded from the providers' image hosts.
The app shows a "Price data by CoinGecko" line, or "Price data by CoinMarketCap" when the rows came from the failover, at the end of the markets list and under the price chart. Tapping it opens the provider's website. The name follows the source field of the API response (DataAttribution in app/lib/ui/widgets/common.dart). Keep the line: the providers' free API terms ask for attribution. Check each provider's current attribution rules for your store listing and your About or Legal page too.