Best On‑Chain Data APIs for Trading Apps: Common Integration Pitfalls and How to Avoid Them
Building a trading app or wallet on top of the best on‑chain data APIs for trading apps can be a huge accelerant — if you integrate them correctly.
When teams wire up a real‑time crypto data API for trading use cases, the most common issues aren’t about missing features. They’re about how the API is used: wrong delivery mode, misread fields, over‑fetching, or ignoring finality and chain reorgs.
This list‑style guide walks through the most frequent integration pitfalls we see across Codex customers and other blockchain API users, plus concrete Codex‑specific patterns and checklists.
1. Picking the Wrong Delivery Mode (REST vs WebSocket vs Webhooks)
Pitfall: Treating every use case as a REST query, or conversely trying to stream everything, leads to brittle UX and unnecessary infra complexity.
Modern on‑chain blockchain data API providers, including Codex, typically expose three delivery modes on a unified GraphQL endpoint:
- Queries (HTTP / GraphQL) for one‑off or batched reads
- Subscriptions (WebSocket) for live updates
- Webhooks for backend event notifications
Codex documents these explicitly and maps each endpoint to the intended mode.[^codex-queries]
When to use each mode
Use this rule of thumb for trading‑adjacent apps:
-
Queries (REST/GraphQL)
- Portfolio snapshots (balances, holdings)
- Historical charts (OHLC, candles, volume)
- Point‑in‑time token prices
-
WebSocket subscriptions
- Live price and OHLC updates (
onPricesUpdated, live candles) - Real‑time on‑chain events (
onEventsCreated, trades, transfers)[^codex-subscriptions] - Prediction market order book / trade streams
- Live price and OHLC updates (
-
Webhooks
- Backend workflows (alerts, compliance checks)
- Asynchronous tasks (back‑office reconciliation)
- Notifications that can tolerate slight delay but must not be dropped
Codex example: batched price query (GraphQL)
Good: Use getTokenPrices with batching and a minimal selection set.
curl https://api.codex.io/graphql \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-d '{
"query": "query GetPrices($inputs: [TokenPriceInput!]!) {\n getTokenPrices(inputs: $inputs) {\n tokenAddress\n chainId\n usdPrice\n nativePrice\n updatedAt\n }\n}\n",
"variables": {
"inputs": [
{"chainId": "eth-mainnet", "tokenAddress": "0xC02aa..."},
{"chainId": "eth-mainnet", "tokenAddress": "0xA0b8..."}
]
}
}'
Codex documents a limit of up to 25 inputs per getTokenPrices request.[^codex-prices]
Codex example: WebSocket subscription with connection_ack and heartbeats
Good: Establish one connection, wait for connection_ack, then start subscribing.
import WebSocket from 'ws';
const ws = new WebSocket('wss://api.codex.io/graphql', {
headers: { Authorization: 'Bearer YOUR_API_KEY' },
});
ws.on('open', () => {
// Start the GraphQL WebSocket protocol
ws.send(JSON.stringify({
type: 'connection_init',
payload: {},
}));
});
ws.on('message', (data) => {
const msg = JSON.parse(data.toString());
if (msg.type === 'connection_ack') {
// Only subscribe after ack
ws.send(JSON.stringify({
id: 'prices-1',
type: 'start',
payload: {
query: `subscription OnPricesUpdated($inputs: [PricesSubscriptionInput!]!) {
onPricesUpdated(inputs: $inputs) {
tokenAddress
chainId
usdPrice
nativePrice
updatedAt
}
}`,
variables: {
inputs: [
{ chainId: 'eth-mainnet', tokenAddress: '0xC02aa...' },
{ chainId: 'eth-mainnet', tokenAddress: '0xA0b8...' },
],
},
},
}));
// Heartbeat every 20 seconds
setInterval(() => {
ws.send(JSON.stringify({ type: 'ping' }));
}, 20000);
}
if (msg.type === 'next') {
console.log('Price update:', msg.payload.data.onPricesUpdated);
}
});
Codex recommends waiting for connection_ack, sending heartbeats for custom clients, and explicitly closing connections because deactivating an API key does not automatically close them.[^codex-ws]
Codex example: webhook handler that returns 2xx fast
Codex’s webhook docs state:[^codex-webhooks]
- The receiver must return 2xx within 3 seconds
- Codex retries failed deliveries up to 2 additional times
- Messages can be lost if your service remains down
Good: A handler that responds quickly and enqueues work.
// Example using Express
import express from 'express';
const app = express();
app.use(express.json());
app.post('/codex-webhook', async (req, res) => {
const event = req.body;
// Enqueue for async processing (e.g., Kafka, SQS, Redis)
await enqueueCodexEvent(event.id, event);
// Return 2xx quickly to satisfy Codex's 3-second expectation
res.status(200).send('ok');
});
app.listen(3000, () => {
console.log('Webhook listener on :3000');
});
Checklist: choosing the right delivery mode
- [ ] Queries for snapshots and historical data
- [ ] WebSockets for real‑time UI updates
- [ ] Webhooks for backend workflows
- [ ] One WebSocket per logical group (e.g., ~100 tokens per connection, as Codex suggests)[^codex-prices-sub]
- [ ] Always wait for
connection_ackand send heartbeats - [ ] Webhook handlers respond within 3 seconds and enqueue work
2. Misinterpreting Fields and Token Semantics
Pitfall: Assuming every “balance” or “price” field means the same thing, or that token metadata is fully populated for every asset.
On the best on‑chain blockchain data API providers, field semantics matter as much as endpoint choice.
Codex’s Balance and Price types distinguish raw amounts, UI‑friendly balances, and pricing provenance.[^codex-balances][^codex-price-type]
Common misinterpretations
-
Raw vs UI balance
rawBalanceis the on‑chain amount in smallest units (e.g., wei)uiBalanceis already adjusted for token decimals
-
USD balance vs token USD price
usdPriceis the price per token in USDusdBalanceis the account’s value in USD for that holding
-
Token metadata completeness
- Fields like
symbol,name,logoUrl, or scam flags may be missing or partial for newly launched / long‑tail tokens - Some fields are only populated for verified or established tokens, which Codex documents in its metadata types
- Fields like
Codex example: minimal balance selection
Good (explicit):
query WalletBalances($wallet: String!, $chainId: ChainId!) {
getWalletBalances(walletAddress: $wallet, chainId: $chainId) {
tokenAddress
symbol
rawBalance
uiBalance
usdBalance
}
}
Bad (over‑assumptive):
query WalletBalances($wallet: String!, $chainId: ChainId!) {
getWalletBalances(walletAddress: $wallet, chainId: $chainId) {
tokenAddress
name # may be null for some tokens
logoUrl # may be null or unstable for new tokens
rawBalance
usdBalance
# omits uiBalance, forcing client to re‑compute decimals manually
}
}
Checklist: field semantics
- [ ] Explicitly choose
rawBalancevsuiBalancein your UI - [ ] Use
usdPricefor per‑unit price andusdBalancefor holdings - [ ] Treat metadata as best effort on long‑tail tokens
- [ ] Feature‑flag or guard against missing symbols/logos
- [ ] Read Codex’s type docs before mapping fields to your domain model
3. Over‑Fetching and Ignoring Rate Limits
Pitfall: Pulling entire objects, using offset pagination, or spamming small requests until you hit rate limits.
Codex documents rate limits of 5 requests per second on Free, 300 req/s on Growth, and custom limits for Enterprise tiers.[^codex-rate-limits] Excess requests return HTTP 429 with retry guidance.
Why over‑fetching hurts
- Direct cost: Codex bills per request/message
- Throttling: hitting per‑second limits triggers 429s
- Latency: multiple small requests instead of batched calls
Codex’s GraphQL guidance mirrors the official GraphQL best practice: ask only for what you need and use cursor pagination.[^graphql]
Example: over‑selected vs minimal selection set
Over‑selected query:
query TokenDetail($chainId: ChainId!, $address: String!) {
getToken(chainId: $chainId, tokenAddress: $address) {
tokenAddress
chainId
name
symbol
logoUrl
description
website
twitter
telegram
discord
tags
liquidity
volume24h
volume7d
volume30d
holdersCount
topHolders {
walletAddress
rawBalance
usdBalance
lastActiveAt
# plus other nested fields
}
}
}
Minimal query for a price tile:
query TokenTile($chainId: ChainId!, $address: String!) {
getToken(chainId: $chainId, tokenAddress: $address) {
tokenAddress
symbol
usdPrice
liquidity
}
}
The second query is dramatically smaller and faster, making it better suited for a trading UI.
Codex 429 example
Codex’s rate‑limit docs show that hitting limits returns HTTP 429 and headers like:[^codex-rate-limits]
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 1
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
{"error":"rate_limit_exceeded","message":"Too many requests"}
Your client should:
- Back off until
Retry-Afterseconds elapse - Avoid hot‑loops that immediately retry
- Prefer batching: e.g.,
getTokenPricessupports up to 25 tokens per call;balancessupports up to 200 tokens.[^codex-prices][^codex-balances]
Checklist: rate limits and over‑fetching
- [ ] Use batching (up to documented limits) instead of N=1 calls
- [ ] Use cursor‑based pagination, not offset, for large lists
- [ ] Minimize fields per query (GraphQL principle: ask only what you need)
- [ ] Implement exponential backoff when receiving 429 +
Retry-After - [ ] Monitor request volume per feature to avoid noisy endpoints
4. WebSocket vs REST for Real‑Time On‑Chain Data
Pitfall: Polling REST endpoints for live prices, trades, or prediction markets when a WebSocket subscription is available.
For trading‑grade UX, WebSocket streams are almost always the best real‑time crypto data API mechanism. Codex exposes subscription counterparts for many core queries, including prices and events.[^codex-subscriptions]
When WebSockets win
Use WebSockets when:
- You need continuous updates with sub‑second latency
- You’re building:
- Order books
- Live candlestick charts
- Real‑time portfolio P&L
- Prediction market dashboards
Codex notes there is no hard limit on subscriptions per connection, but recommends planning for ~100 tokens per connection and spreading high‑volume tokens across more connections.[^codex-prices-sub]
When REST/GraphQL is enough
Stick to queries when:
- You only need occasional refreshes (e.g., every few minutes)
- Data isn’t user‑visible in real‑time (reports, back office)
- You’re doing large historical backfills
Checklist: WebSocket vs REST
- [ ] Use WebSockets for UI components where latency <1s matters
- [ ] Use REST/GraphQL for periodic or offline workflows
- [ ] Group related subscriptions on shared connections
- [ ] Implement reconnect logic and backpressure (e.g., drop some updates)
5. How to Handle Reorgs and Finality with Blockchain APIs
Pitfall: Treating every event from the API as final, or ignoring the difference between processed and confirmed data.
On chains like Ethereum, blocks can be temporarily reorganized (“reorgs”), which means a transaction that looked confirmed can disappear or move. Ethereum’s proof‑of‑stake finality is implemented via the consensus protocol (e.g., Casper FFG), and a block is considered finalized when it has been justified and finalized by the consensus.[^eth-pos-finality] If a finalized block were reverted, validators would face large penalties (slashing).
Codex exposes commitment levels, distinguishing processed vs confirmed data on some streams (e.g., onEventsCreated).[^codex-on-events]
Processed vs confirmed data
-
Processed
- Earliest view of a transaction/event (e.g., a few blocks deep)
- Lower latency, but can be rolled back in a reorg
-
Confirmed
- Only emitted after a safer depth is reached
- Higher latency, but much more stable
- Suitable for user‑facing balances, charts, and history
Codex’s documentation recommends using confirmed data for trading interfaces, while processed data can be appropriate for speculative or low‑value signals.[^codex-on-events]
Example: Ethereum confirmation depths
Different ecosystems and exchanges use different confirmation counts. Common operational practices include:
-
Ethereum mainnet (PoS)
- Many wallets and exchanges treat 12–64 blocks (~3–16 minutes) as a safe confirmation window for high‑value transfers.
- The Ethereum Foundation describes finality as being reached when a block is justified and finalized in the consensus mechanism.[^eth-pos-finality]
-
Other chains
- Bitcoin: often 1–6 confirmations depending on risk appetite
- L2s: typically fewer confirmations due to faster blocks, but each has its own guidance
Your exact policy should match your risk tolerance and product requirements.
How to handle reorgs with blockchain APIs
-
Prefer confirmed streams/endpoints for:
- Balances and portfolio views
- Historical charts and OHLC
- User transaction history
-
Use processed only when:
- You’re showing tentative statuses (e.g., “pending”, “processing”)
- You clearly communicate to users that the state may change
-
Implement idempotent processing and compaction:
- Deduplicate events via deterministic IDs
- Support corrections where a previous event is later marked invalid or replaced
Checklist: finality and reorg handling
- [ ] Understand whether your endpoint delivers processed vs confirmed data
- [ ] Use confirmed data for any user‑visible, irreversible state
- [ ] Treat processed data as tentative and label it accordingly
- [ ] Implement idempotent handlers for both subscriptions and webhooks
- [ ] Document per‑chain confirmation policies in your runbooks
6. Ignoring Prediction Market Nuances
Pitfall: Treating prediction market data like spot token prices, with no awareness of platform‑specific semantics.
Prediction markets are rapidly becoming a core fintech surface. Pew Research reported that combined monthly trading volume on Kalshi and Polymarket rose from under $5B in September 2025 to about $24B in April 2026.[^pew]
Codex exposes dedicated prediction market endpoints (currently in beta) for events, markets, trades, and trader analytics.[^codex-prediction] Polymarket and Kalshi are both supported, though Codex notes that some trader data for Kalshi may be limited.
Common mistakes
- Ignoring event resolution state when showing prices
- Mixing yes/no markets with multi‑outcome markets without clear labels
- Assuming all platforms expose the same level of trader analytics
Codex guidance for prediction markets
- Use
filterPredictionEventsto discover events and resolution states - Use
filterPredictionMarketsto list markets for an event - Use trade and trader analytics endpoints for leaderboards and performance views
- Treat prediction markets as a separate product surface, not just another token
Checklist: prediction markets
- [ ] Represent event resolution and settlement status explicitly in the UI
- [ ] Differentiate yes/no vs multi‑outcome markets
- [ ] Use Codex’s beta endpoints with feature flags and fallbacks
- [ ] Be conservative in interpreting partial trader data, especially on Kalshi
7. Skipping Unified Data and Over‑Stitching Providers
Pitfall: Stitching together multiple providers for tokens, wallets, NFTs, and prediction markets, then spending months reconciling differences.
Unified APIs are replacing stitched‑together stacks.[^codex-migrations] Codex’s positioning is a single GraphQL supergraph that covers tokens, wallets, charts, and prediction markets.[^codex-learn-graphql]
By contrast, other providers sometimes differentiate between raw chain data and curated “trading cubes” (e.g., Bitquery).[^bitquery] You may still need those for deep archival analytics, but for live trading apps, a unified, enriched API typically wins.
Checklist: consolidating providers
- [ ] Prefer one source of truth for token + wallet + prediction data
- [ ] Use niche providers only where Codex (or your main provider) clearly lacks coverage
- [ ] Avoid double‑counting volume or liquidity by mixing provider definitions
FAQ: Common Questions on Blockchain Data API Integration
How many confirmations should I wait for mainnet Ethereum?
Operational practices vary by risk profile, but many trading and wallet apps treat 12–64 blocks on Ethereum mainnet (roughly 3–16 minutes) as a reasonable confirmation window for larger transfers.
The Ethereum Foundation explains that finality is achieved when a block is justified and finalized within the proof‑of‑stake consensus.[^eth-pos-finality] For small retail transfers, you may choose fewer confirmations, but you should document this as a product decision.
When should I use processed vs confirmed data from a blockchain API?
Use confirmed data for:
- Balances and portfolio values
- Historical charts, OHLCV, and analytics
- Transaction histories that users expect to be stable
Use processed data only when:
- You need ultra‑low latency signals (e.g., speculative bots)
- You label data as pending or subject to change
Codex explicitly documents processed vs confirmed semantics on some streams (like onEventsCreated).[^codex-on-events]
How to implement idempotency for webhooks?
To make webhook handlers idempotent:
- Use a deterministic key (e.g.,
event.idfrom Codex) as a unique identifier. - Store processed IDs in a database or cache.
- On receiving a webhook:
- Check if
event.idalready exists. - If yes, skip processing.
- If no, process and insert the ID.
- Check if
This approach ensures that retries (Codex retries failed deliveries up to two times) do not cause duplicate effects.[^codex-webhooks]
How to parse Ethereum logs for transfers?
Ethereum smart contracts emit events; ERC‑20 tokens use a standard Transfer event with indexed from and to addresses plus a value payload.[^eth-events]
If you’re using raw logs:
- Decode the event signature
Transfer(address,address,uint256) - Map indexed topics to
fromandto - Decode
valuefrom the data field
Codex abstracts this for you by exposing normalized token transfer objects and wallet balances, so you can avoid parsing logs directly.[^codex-balances]
How to avoid overfetching blockchain data?
To avoid overfetching when using on‑chain data APIs:
- Use GraphQL selection sets to request only the fields you need[^graphql]
- Batch requests where possible (e.g., up to 25 tokens in
getTokenPrices)[^codex-prices] - Use cursor‑based pagination for large lists
- Cache results for short intervals where real‑time freshness isn’t critical
These patterns reduce both latency and your API usage.
Pagination cursoring for large blockchain datasets?
Cursor‑based pagination is the default recommended pattern for large or fast‑changing datasets.[^graphql]
With cursor pagination:
- Each page returns a
cursor(orendCursor) - You pass that cursor back to fetch the next page
- New records do not shift your current page, unlike offset pagination
Codex’s paginated endpoints follow this principle, and its docs recommend cursor pagination for lists like trades, transfers, or holders.[^codex-rate-limits]
If you’re building a trading app, wallet, or prediction market frontend and want production‑ready token and prediction market data from a single API, Codex is designed to be that unified, trading‑grade layer. Read the Codex docs, benchmark your workloads, and adopt the patterns above to avoid the most common integration pitfalls.
[^codex-queries]: Codex Docs – Concepts: Queries & Subscriptions, https://docs.codex.io/concepts/queries
[^codex-subscriptions]: Codex Docs – API Reference: Subscriptions, https://docs.codex.io/api-reference/subscriptions/oneventscreated
[^codex-balances]: Codex Docs – Types: Balance, https://docs.codex.io/api-reference/types/balance
[^codex-price-type]: Codex Docs – Types: Price, https://docs.codex.io/api-reference/types/price
[^codex-rate-limits]: Codex Docs – Concepts: Rate Limits, https://docs.codex.io/concepts/rate-limits
[^codex-prices]: Codex Docs – getTokenPrices batching limits, https://docs.codex.io/api-reference/queries/gettokenprices
[^codex-prices-sub]: Codex Docs – onPricesUpdated connection density guidance, https://docs.codex.io/api-reference/subscriptions/onpricesupdated
[^codex-webhooks]: Codex Docs – Concepts: Webhooks, https://docs.codex.io/concepts/webhooks
[^codex-ws]: Codex Docs – Troubleshooting WebSockets, https://docs.codex.io/extra/troubleshooting
[^eth-pos-finality]: Ethereum.org – Proof-of-stake and Finality, https://ethereum.org/developers/docs/consensus-mechanisms/pos/
[^eth-events]: Ethereum.org – Logging events and smart contracts, https://ethereum.org/developers/tutorials/logging-events-smart-contracts
[^graphql]: GraphQL.org – Queries and Pagination, https://graphql.org/learn/queries/
[^pew]: Pew Research Center – “Trading volume on prediction markets has soared in recent months”, May 27, 2026, https://www.pewresearch.org/short-reads/2026/05/27/trading-volume-on-prediction-markets-has-soared-in-recent-months/
[^codex-prediction]: Codex Docs – Prediction Markets, https://docs.codex.io/api-reference/queries/predictionmarkets
[^codex-on-events]: Codex Docs – onEventsCreated commitment levels, https://docs.codex.io/api-reference/subscriptions/oneventscreated
[^bitquery]: Bitquery Docs – Trading Data Overview (Trading vs Archive cubes), https://docs.bitquery.io/docs/trading/trading-data-overview/
[^codex-migrations]: Codex Docs – Migrations & Unified API, https://docs.codex.io/migrations
[^codex-learn-graphql]: Codex Docs – Learn GraphQL with Codex, https://docs.codex.io/learn-graphql
