# Best Onchain Data APIs for Trading Apps: Common Integration Pitfalls and How to Avoid Them

> Building a trading app or wallet on top of the best onchain data APIs for trading apps can be a huge accelerant, if you integrate them correctly.

Source: https://www.codex.io/blog/on-chain-data-apis-integration-pitfalls
Published: 2026-08-05
Author: Codex

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.[1]

### 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)[2]
  - Prediction market order book / trade streams
- **Webhooks**
  - Backend workflows (alerts, [compliance checks](https://www.codex.io/blog/on-chain-data-security-compliance))
  - 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**.[3]

### 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.[4]

### Codex example: webhook handler that returns 2xx fast

Codex’s webhook docs state:[5]

- 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)[6]
- [ ] Always wait for `connection_ack` and 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](https://www.codex.io/blog/best-onchain-data-apis-trading), field semantics matter as much as endpoint choice. Codex’s `Balance` and `Price` types distinguish raw amounts, UI‑friendly balances, and pricing provenance.[7][8]

### Common misinterpretations

- **Raw vs UI balance**
  - `rawBalance` is the on‑chain amount in smallest units (e.g., wei)
  - `uiBalance` is already adjusted for token decimals
- **USD balance vs token USD price**
  - `usdPrice` is the price per token in USD
  - `usdBalance` is 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

### 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 `rawBalance` vs `uiBalance` in your UI
- [ ] Use `usdPrice` for per‑unit price and `usdBalance` for 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.[9] 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.[10]

### 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:[9]

```
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-After` seconds elapse
- Avoid hot‑loops that immediately retry
- Prefer batching: e.g., `getTokenPrices` supports up to **25 tokens per call**; `balances` supports up to **200 tokens**.[3][7]

### Checklist: rate limits and over‑fetching

- [ ] Use batching (up to documented limits) instead of N=1 calls
- [ ] Use [cursor‑based pagination](https://www.codex.io/blog/on-chain-data-api-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.[2]

### 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.[6]

### 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](https://www.codex.io/blog/blockchain-reorgs-application-data) (“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.[11] 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`).[12]

### 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.[12]

### 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.[11]
- **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**.[13]

Codex exposes dedicated prediction market endpoints (currently in beta) for events, markets, trades, and trader analytics.[14] 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 `filterPredictionEvents` to discover events and resolution states
- Use `filterPredictionMarkets` to 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.[15] Codex’s positioning is a single GraphQL supergraph that covers tokens, wallets, charts, and prediction markets.[16]

By contrast, other providers sometimes differentiate between raw chain data and curated “trading cubes” (e.g., Bitquery).[17] 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

## Sources

1. Codex Docs – Concepts: Queries & Subscriptions, https://docs.codex.io/concepts/queries
2. Codex Docs – API Reference: Subscriptions, https://docs.codex.io/api-reference/subscriptions/oneventscreated
3. Codex Docs – `getTokenPrices` batching limits, https://docs.codex.io/api-reference/queries/gettokenprices
4. Codex Docs – Troubleshooting WebSockets, https://docs.codex.io/extra/troubleshooting
5. Codex Docs – Concepts: Webhooks, https://docs.codex.io/concepts/webhooks
6. Codex Docs – `onPricesUpdated` connection density guidance, https://docs.codex.io/api-reference/subscriptions/onpricesupdated
7. Codex Docs – Types: Balance, https://docs.codex.io/api-reference/types/balance
8. Codex Docs – Types: Price, https://docs.codex.io/api-reference/types/price
9. Codex Docs – Concepts: Rate Limits, https://docs.codex.io/concepts/rate-limits
10. GraphQL.org – Queries and Pagination, https://graphql.org/learn/queries/
11. Ethereum.org – Proof-of-stake and Finality, https://ethereum.org/developers/docs/consensus-mechanisms/pos/
12. Codex Docs – `onEventsCreated` commitment levels, https://docs.codex.io/api-reference/subscriptions/oneventscreated
13. 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/
14. Codex Docs – Prediction Markets, https://docs.codex.io/api-reference/queries/predictionmarkets
15. Codex Docs – Migrations & Unified API, https://docs.codex.io/migrations
16. Codex Docs – Learn GraphQL with Codex, https://docs.codex.io/learn-graphql
17. Bitquery Docs – Trading Data Overview (Trading vs Archive cubes), https://docs.bitquery.io/docs/trading/trading-data-overview/
18. Ethereum.org – Logging events and smart contracts, https://ethereum.org/developers/tutorials/logging-events-smart-contracts

## FAQ

### 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. 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).

### How to implement idempotency for webhooks?

To make webhook handlers idempotent: Use a deterministic key (e.g., event.id from Codex) as a unique identifier. Store processed IDs in a database or cache. On receiving a webhook: Check if event.id already exists. If yes, skip processing. If no, process and insert the ID. This approach ensures that retries (Codex retries failed deliveries up to two times) do not cause duplicate effects.

### 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. If you’re using raw logs: Decode the event signature Transfer(address,address,uint256) Map indexed topics to from and to Decode value from the data field Codex abstracts this for you by exposing normalized token transfer objects and wallet balances, so you can avoid parsing logs directly.

### 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 Batch requests where possible (e.g., up to 25 tokens in getTokenPrices) 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. With cursor pagination: Each page returns a cursor (or endCursor) 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. 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.

### What is a compute unit?

Usage is metered in compute units. Every query, subscription message and delivered webhook costs a number of compute units based on the operation and the data it returns; the dashboard lists the base cost of each operation. Overage on Growth plans bills at the plan's rate plus 15%, from $115 to $138 per 1M compute units.

### What networks does Codex support?

80+ networks and counting, including Ethereum, Solana, Base, BNB Chain, Arbitrum, and Optimism, with new networks added regularly.

### What payment methods does Codex accept?

Card payments through the dashboard; enterprise customers can arrange invoicing.

### Is it easy to migrate to Codex?

Yes: the GraphQL API, TypeScript SDK, and comprehensive docs make migrations straightforward, and our team helps enterprise customers move over.
