Bitquery API Integration
Bitquery is a GraphQL API over indexed data from 40+ blockchains. It appeals to developers by eliminating the need to run your own nodes and write indexers for each network. In practice, integration is more complex than the documentation promises: rate limits, differences between V1 and V2 (EAP) schemas, specific DEX query features — all this requires understanding nuances before building a production system.
V1 vs V2 (EAP): Fundamental Differences
Bitquery develops two parallel API versions. V1 (api.bitquery.io) — old, with broad network support. V2 (streaming.bitquery.io, EAP — Early Access Program) — new architecture with WebSocket subscription support for real-time data.
For new projects, orient toward V2 if required networks are supported. V1 is transitioning to maintenance mode without active development.
# V2: subscribe to new Uniswap V3 swaps in real-time
subscription {
EVM(network: eth) {
DEXTrades(
where: {
Trade: { Dex: { ProtocolName: { is: "uniswap_v3" } } }
}
) {
Block { Time Number }
Trade {
Buy { Amount Currency { Symbol Address } }
Sell { Amount Currency { Symbol Address } }
Dex { PoolAddress }
}
}
}
}
Typical Tasks and Queries
DEX Trading Monitoring
Task: get trade history for a specific pair on Uniswap V3 with OHLCV aggregation:
query DEXOHLCVQuery($since: ISO8601DateTime!, $poolAddress: String!) {
EVM(network: eth, dataset: archive) {
DEXTradeByTokens(
where: {
Trade: {
Dex: { SmartContract: { is: $poolAddress } }
}
Block: { Time: { since: $since } }
}
orderBy: { ascendingByField: "Block_Time" }
limit: { count: 1000 }
) {
Block { Time(interval: { in: minutes, count: 5 }) }
Trade {
open: PriceInUSD(minimum: Block_Time)
high: PriceInUSD(maximum: Trade_PriceInUSD)
low: PriceInUSD(minimum: Trade_PriceInUSD)
close: PriceInUSD(maximum: Block_Time)
volume: sum(of: Trade_Side_AmountInUSD)
}
}
}
}
Whale Transfer Tracking
query WhaleTransfers($minAmount: String!) {
EVM(network: eth) {
Transfers(
where: {
Transfer: {
Currency: { SmartContract: { is: "0xdac17f958d2ee523a2206206994597c13d831ec7" } }
Amount: { ge: $minAmount }
}
}
limit: { count: 50 }
orderBy: { descendingByField: "Block_Time" }
) {
Block { Time Number }
Transfer {
From To
Amount
Currency { Symbol }
}
Transaction { Hash }
}
}
}
Rate Limits and Strategies
Bitquery charges requests in "points" — each request costs a certain number of points depending on returned data volume. Main limitations on paid plans: number of requests per minute and monthly point limit.
Rate limit management strategy:
Application-level caching — historical data (trades from past days) doesn't change, can be cached in Redis or PostgreSQL for 24+ hours. Call Bitquery only for fresh data.
Pagination via cursor — requests with limit return maximum 1000–25000 records. To get the full set, use offset or cursor-based pagination:
async function fetchAllTrades(poolAddress: string, since: string) {
const allTrades = [];
let offset = 0;
const limit = 1000;
while (true) {
const data = await bitquery.request(TRADES_QUERY, {
poolAddress, since, limit, offset
});
const trades = data.EVM.DEXTradeByTokens;
allTrades.push(...trades);
if (trades.length < limit) break;
offset += limit;
// Respect rate limit
await delay(200);
}
return allTrades;
}
Request batching — GraphQL allows combining multiple operations in a single HTTP request, saving round-trip time, though points are still spent for each operation.
WebSocket for Real-Time: V2 Specifics
V2 supports subscriptions via graphql-ws protocol. Standard implementation in Node.js:
import { createClient } from "graphql-ws";
import WebSocket from "ws";
const client = createClient({
url: "wss://streaming.bitquery.io/eap",
webSocketImpl: WebSocket,
connectionParams: {
headers: { "X-API-KEY": process.env.BITQUERY_API_KEY }
},
retryAttempts: Infinity,
shouldRetry: () => true,
});
const unsubscribe = client.subscribe(
{ query: SWAP_SUBSCRIPTION },
{
next: (data) => processSwap(data.data.EVM.DEXTrades),
error: (err) => logger.error("subscription error", err),
complete: () => logger.info("subscription completed"),
}
);
Important: V2 WebSocket requires a separate API key (EAP access), which is issued on request separately from the main V1 key.
Limitations and When Bitquery Isn't Suitable
Bitquery is a managed service, meaning dependence: indexing may lag chain tip by 1–3 blocks, historical data sometimes contains gaps, support for non-standard or new networks is added with delay.
Scenarios where a custom indexer or alternatives are better:
- SLA < 1 second for data (Bitquery doesn't guarantee latency)
- Custom events from unpopular contracts without verified ABI
- Data volumes that hit monthly limits within reasonable budget
- Compliance requirements for data storage on your infrastructure
Alternatives by task: Dune Analytics — for ad-hoc SQL analytics; The Graph — for project-specific subgraph with guaranteed availability; Goldsky/Envio — for high-performance indexing with low latency.
Integrating Bitquery as a data source for a dashboard or alert system takes 1–2 weeks including data normalization, caching, and error handling.







