Data providers
CoinGecko, CoinMarketCap, Alternative.me.
Where prices, charts, candles, coin data and the Fear & Greed index 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 (including community sentiment votes), line charts, candlesticks (OHLC), 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 |
| Alternative.me | The Crypto Fear & Greed Index card on the markets screen (GET /v1/feargreed) | None (keyless, free). Attribution required, see Fear & Greed index |
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, candlesticks, tickers, coin descriptions, links and community sentiment, 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, Firestore providerUsage/{provider}_{YYYY-MM}). Alternative.me calls are counted as alternative_{YYYY-MM} and are listed on the same page (in 2.0.0 that row is labelled "CoinMarketCap" there, see Operator console).
| 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. |
| Alternative.me calls per minute | 10 (fixed in code) | Not a console setting (ALTERNATIVE_PER_MINUTE in providers.ts). Alternative.me allows 60 per minute; with the 1-hour cache the backend makes about one call an hour. |
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 |
| Fear & Greed index | 3600 |
| Exchange tickers | 600 |
| Search | 3600 |
| Trending | 600 |
| Fiat rates | 600 |
| Coin list with contracts | 86400 |
Candlesticks use the chart caches: 24H candles (days=1) the "Charts 1h / 24h" time, longer ranges the "Charts 7d and longer" time. 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". The same applies to candlesticks (days=maxis served as 365 days). The app then shows "ALL limited to 1Y by the data plan". - 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.
06Candlesticks and community sentiment
- Candlesticks come from CoinGecko's
/coins/{id}/ohlcthroughGET /v1/coins/{id}/ohlc?vs=usd&days=1(docs/CONTRACT.md§3.5a,firebase/functions/src/api/market.ts). Alloweddays:1, 7, 14, 30, 90, 180, 365, max; anything else answers400 bad_request. CoinGecko picks the candle size: 30 minutes for 1 day, 4 hours up to 30 days, 4 days beyond. The API returns at most 200 candles (neighbours are merged), fetched once in USD and converted to the user's currency. Each fetch counts against your CoinGecko budget. - In the app, the coin chart has a Line / Candles switch. Candles start at 24H: the 1H range is disabled in candle mode on every plan ("Candles start at 24H"), because CoinGecko's smallest candle is 30 minutes. The line chart still offers 1H.
- CoinGecko down and nothing cached:
503 chart_unavailable; unknown coin:404 not_found. - Community sentiment is CoinGecko's community vote split (
sentiment_votes_up_percentageand…_down_percentage), normalised to 100 % and sent assentimentin the coin detail. The coin page shows it as "Community sentiment" with the note "Votes from the CoinGecko community. Not a forecast." Coins without votes have"sentiment": nulland the card is hidden. It is the coin detail's data, so no extra call and no extra cache.
07Fear & Greed index (Alternative.me)
The markets screen shows the Crypto Fear & Greed Index from Alternative.me: a gauge with today's value (0–100), its band and the values yesterday, last week and last month (app/lib/ui/screens/markets/fear_greed_card.dart).
- Source:
https://api.alternative.me/fng/, free and keyless, called only by the backend (firebase/functions/src/api/feargreed.ts). The API returns the latest value and up to 30 days of history (GET /v1/feargreed,docs/CONTRACT.md§3.18). - Bands (Alternative.me's): 0–24 Extreme Fear, 25–44 Fear, 45–55 Neutral, 56–75 Greed, 76–100 Extreme Greed. The app shows the band in the user's language.
- Limits: the index changes once a day. The backend caches it for 1 hour (Console → Data providers → cache time Fear & Greed index, default 3600 s) and allows itself 10 calls a minute; Alternative.me's own limit is 60 a minute.
- Switch: Console → Features → Fear & Greed index on Markets (on by default). Off: the API answers
404 not_foundwithout calling Alternative.me, and the app hides the card. - Source down: the last cached value is served with
"stale": true; with nothing cached the API answers503 upstream_unavailableand the app simply hides the card. The rest of the markets screen is not affected.
Alternative.me's "Fear and Greed Index API Rules" (on their index page, read on 2026-10-07) say: you must properly acknowledge the source and reference it prominently; commercial use is allowed as long as the attribution is given right next to the display of the data; and you may not use the data to impersonate them or to create a service that could be confused with theirs. The rules apply to all their fear and greed data. The API response carries "attribution": {"name": "Alternative.me", "url": "https://alternative.me/crypto/fear-and-greed-index/"} and the card always shows "Data by Alternative.me", linking to their page. Do not remove or move that link away from the card. Check the rules again before publishing, as they can change; if you cannot meet them, switch the card off in the console.
08Attribution
Market data is provided by CoinGecko and, as the failover, CoinMarketCap; the Fear & Greed index by Alternative.me (see above). 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.