diff --git a/.env.example b/.env.example
index 590702c..cf7cfc7 100644
--- a/.env.example
+++ b/.env.example
@@ -1,3 +1,12 @@
-# No API keys are required for the default setup.
+# Optional: CoinGecko API key (server-side only).
+# Preferred:
+# COINGECKO_PRO_API_KEY=
+# or
+# COINGECKO_DEMO_API_KEY=
+#
+# Fallback generic option:
+# COINGECKO_API_KEY=
+# COINGECKO_API_KEY_TYPE=demo # demo | pro
+#
# Optional: override the internal API route base when deploying behind a proxy.
# NEXT_PUBLIC_API_BASE_URL=
diff --git a/README.md b/README.md
index b8a821c..6520aa3 100644
--- a/README.md
+++ b/README.md
@@ -118,7 +118,22 @@ npm run sync:crypto-icons
## Environment Variables
-No API keys are required.
+CoinGecko key is optional but recommended to reduce rate-limit issues.
+
+Preferred server-side variables:
+
+```env
+COINGECKO_PRO_API_KEY=
+# or
+COINGECKO_DEMO_API_KEY=
+```
+
+Fallback generic option:
+
+```env
+COINGECKO_API_KEY=
+COINGECKO_API_KEY_TYPE=demo # demo | pro
+```
Optional variable (only if you want to call API routes through a custom base URL):
diff --git a/components/converter/converter-card.tsx b/components/converter/converter-card.tsx
index 54c6a32..b5f0767 100644
--- a/components/converter/converter-card.tsx
+++ b/components/converter/converter-card.tsx
@@ -222,7 +222,25 @@ export function ConverterCard({
variant="outline"
className="border-border/70 bg-background/50"
>
- Rates: {data.sources.fiat} • {data.sources.crypto}
+ Fiat rates by
+
+ {data.sources.fiat}
+
+ •
+ Price data by
+
+ {data.sources.crypto}
+
diff --git a/lib/api/crypto.ts b/lib/api/crypto.ts
index 235fffa..d3bd09a 100644
--- a/lib/api/crypto.ts
+++ b/lib/api/crypto.ts
@@ -7,6 +7,38 @@ export interface CryptoRateResult {
const COINGECKO_BASE_URL = "https://api.coingecko.com/api/v3";
+function buildCoinGeckoHeaders(): HeadersInit {
+ const headers: Record = {
+ accept: "application/json"
+ };
+
+ const proApiKey = process.env.COINGECKO_PRO_API_KEY?.trim();
+ const demoApiKey = process.env.COINGECKO_DEMO_API_KEY?.trim();
+ const genericApiKey = process.env.COINGECKO_API_KEY?.trim();
+ const genericApiKeyType =
+ process.env.COINGECKO_API_KEY_TYPE?.trim().toLowerCase() ?? "demo";
+
+ if (proApiKey) {
+ headers["x-cg-pro-api-key"] = proApiKey;
+ return headers;
+ }
+
+ if (demoApiKey) {
+ headers["x-cg-demo-api-key"] = demoApiKey;
+ return headers;
+ }
+
+ if (genericApiKey) {
+ if (genericApiKeyType === "pro") {
+ headers["x-cg-pro-api-key"] = genericApiKey;
+ } else {
+ headers["x-cg-demo-api-key"] = genericApiKey;
+ }
+ }
+
+ return headers;
+}
+
export async function fetchCryptoData(): Promise {
const ids = CRYPTO_ASSETS.map((asset) => asset.providerId).filter(
(id): id is string => Boolean(id)
@@ -18,9 +50,7 @@ export async function fetchCryptoData(): Promise {
const response = await fetch(url, {
next: { revalidate: 60 },
- headers: {
- accept: "application/json"
- }
+ headers: buildCoinGeckoHeaders()
});
if (!response.ok) {