A GraphQL API that wraps the CoinGecko public REST API, built with Apollo Server v4 and Node.js. No database required — all data comes from CoinGecko in real time.
- 4 Queries — coin details, top coins by market cap, search, global market overview
- 1 Mutation — live currency conversion using CoinGecko prices
- Custom error handling — structured GraphQL errors (
NOT_FOUND,VALIDATION_ERROR,RATE_LIMITED,UPSTREAM_ERROR) - Dedicated data source — all CoinGecko HTTP calls are isolated in
CoinGeckoAPI - Zero config — no API key needed (uses CoinGecko's free tier)
# Install dependencies
npm install
# Start the server (port 4000 by default)
npm start
# Or start with auto-reload during development
npm run devOpen http://localhost:4000 in your browser to access the Apollo Sandbox.
| Variable | Default | Description |
|---|---|---|
PORT |
4000 |
HTTP port to listen on |
Start the server with npm start and open http://localhost:4000. Apollo Sandbox provides an interactive editor with autocomplete, schema docs, and a history of past queries.
# Fetch Bitcoin details
curl -s http://localhost:4000/ \
-H 'Content-Type: application/json' \
-d '{"query":"{ coin(id: \"bitcoin\") { name currentPrice marketCapRank } }"}' | jq
# Top 5 coins
curl -s http://localhost:4000/ \
-H 'Content-Type: application/json' \
-d '{"query":"{ topCoins(limit: 5) { name currentPrice priceChangePercentage24h } }"}' | jq
# Search
curl -s http://localhost:4000/ \
-H 'Content-Type: application/json' \
-d '{"query":"{ searchCoins(query: \"sol\") { coins { id name symbol } } }"}' | jq
# Global market
curl -s http://localhost:4000/ \
-H 'Content-Type: application/json' \
-d '{"query":"{ globalMarket { totalMarketCap marketCapPercentage { btc eth } } }"}' | jq
# Convert 1 ETH to USD
curl -s http://localhost:4000/ \
-H 'Content-Type: application/json' \
-d '{"query":"mutation { convertCurrency(fromCoinId: \"ethereum\", toCurrency: \"usd\", amount: 1) { convertedAmount rate timestamp } }"}' | jqTip: Pipe through
jqfor pretty-printed output. Remove| jqif you don't have it installed.
| Query | Description |
|---|---|
coin(id) |
Detailed data for a single cryptocurrency |
topCoins |
Top coins ranked by market cap |
searchCoins |
Search coins by name or symbol |
globalMarket |
Global crypto market overview |
| Mutation | Description |
|---|---|
convertCurrency |
Convert an amount from one crypto to another currency |
query GetBitcoin {
coin(id: "bitcoin") {
id
name
symbol
currentPrice
marketCap
marketCapRank
priceChangePercentage24h
high24h
low24h
circulatingSupply
ath
athDate
description
homepage
}
}query TopCoins {
topCoins(currency: "usd", limit: 5, page: 1) {
id
name
symbol
currentPrice
marketCap
marketCapRank
priceChangePercentage24h
totalVolume
}
}query Search {
searchCoins(query: "ethereum") {
coins {
id
name
symbol
marketCapRank
thumb
}
}
}query GlobalOverview {
globalMarket {
activeCryptocurrencies
markets
totalMarketCap
totalVolume
marketCapPercentage {
btc
eth
}
marketCapChangePercentage24h
updatedAt
}
}mutation Convert {
convertCurrency(fromCoinId: "bitcoin", toCurrency: "usd", amount: 2.5) {
from
to
amount
convertedAmount
rate
timestamp
}
}Invalid coin ID:
query {
coin(id: "not_a_real_coin") {
name
}
}Response:
{
"errors": [
{
"message": "CoinGecko resource not found (Not Found)",
"extensions": { "code": "NOT_FOUND" }
}
],
"data": { "coin": null }
}Validation error (negative amount):
mutation {
convertCurrency(fromCoinId: "bitcoin", toCurrency: "usd", amount: -5) {
convertedAmount
}
}Response:
{
"errors": [
{
"message": "amount must be a positive number",
"extensions": { "code": "VALIDATION_ERROR" }
}
],
"data": null
}crypto_ql/
├── src/
│ ├── index.js # Apollo Server entry point
│ ├── schema.js # GraphQL type definitions
│ ├── resolvers.js # Query & mutation resolvers
│ ├── datasources/
│ │ └── CoinGeckoAPI.js # All CoinGecko REST calls
│ └── errors/
│ └── index.js # Custom GraphQL error classes
├── .gitignore
├── package.json
└── readme.md
| Code | HTTP Status | Description |
|---|---|---|
NOT_FOUND |
404 | Requested coin/resource not found |
VALIDATION_ERROR |
400 | Invalid input (empty ID, negative amount, etc.) |
RATE_LIMITED |
429 | CoinGecko rate limit exceeded |
UPSTREAM_ERROR |
502 | Unexpected CoinGecko API failure |
- Runtime: Node.js
- GraphQL Server: Apollo Server v4
- Data Source: CoinGecko public API (no key required)
- HTTP Client: node-fetch v2
MIT