# Hyperflow GraphQL API — reference for AI agents > Unified GraphQL API for onchain data (Ethereum mainnet): blocks, transactions with > gas, event logs, ERC-20 transfers/approvals/balances, ERC-721 transfers, Uniswap V2 > swaps, native balances, and read-only RPC (ethCall, estimateGas). One endpoint. ## Connect - Endpoint: `https://api.hyperflowlabs.com/ethereum/graphql` (POST; subscriptions via WebSocket at the same URL) - Auth: header `x-api-key: ` — create a key self-serve in the console: https://console.hyperflowlabs.com/signup - Full schema (SDL): https://hyperflowlabs.com/docs/schema.graphql - Human docs: https://hyperflowlabs.com/docs/ - Introspection is enabled — you can also fetch the schema directly from the endpoint. - MCP server (Deep Research tools): `https://api.hyperflowlabs.com/mcp/research` (Streamable HTTP, same `x-api-key` auth); setup instructions in the console under "MCP Connect". Quick test: ```sh curl -s https://api.hyperflowlabs.com/ethereum/graphql \ -H 'content-type: application/json' -H 'x-api-key: YOUR_KEY' \ -d '{"query":"{ metadata { chainId } }"}' ``` ## Query model (read this once, everything follows the same shape) Every top-level list query takes `input: { filters, pagination, orderBy }` and returns `{ items [...], pageInfo { totalCount hasNextPage currentPage totalPages } }`. (Token-scoped helpers are the exception: `erc20Token.erc20Holders(minBalance, limit, offset)` takes direct arguments and returns a plain list — no `input:` wrapper, no `pageInfo`.) - Filters are per-field operator objects: `{ fromAddress: { eq: "0x..." } }`. String ops: eq/ne/contains/startsWith/endsWith/regex/in/isNull. Numeric (Int/BigInt) ops: eq/gt/gte/lt/lte/in. Combine with `and:`, `or:`, `not:`. - Pagination: `{ limit: 50, offset: 0 }` (max limit 1000). - Ordering: `[{ field: BLOCK_NUMBER, direction: DESC }]`. - Numeric chain values (wei, gas) are decimal or hex strings — never floats. `parsedTransfer` / `parsedSwap` / `balance.decimal` give human-readable amounts. - PERFORMANCE: `transactions` is a multi-billion-row table. Always bound scans with a `blockNumber` range (~7,200 blocks/day); point lookups need `hash` AND `blockNumber` together. Avoid selecting `internalTransactions` in latency-sensitive paths. ## Canonical queries ### 1. Latest transactions SENT by an address, with gas fees (One direction per query: run it again with `toAddress` instead of `fromAddress` for inbound. The combined `or:` form is valid but expensive on this table — avoid it in latency-sensitive paths.) ```graphql query LatestTxs($addr: String!, $fromBlock: Int!) { transactions(input: { filters: { fromAddress: { eq: $addr } blockNumber: { gte: $fromBlock } # always bound transaction scans } pagination: { limit: 20 } orderBy: [{ field: BLOCK_NUMBER, direction: DESC }] }) { pageInfo { totalCount hasNextPage } items { hash blockNumber fromAddress toAddress valueWei gasUsed gasPrice success } } } ``` Fee per tx in wei = `gasUsed * gasPrice` (both decimal strings). ### 2. Drill into one transaction (its event logs) ```graphql query TxDetail($hash: String!, $block: Int!) { transactions(input: { filters: { hash: { eq: $hash }, blockNumber: { eq: $block } } }) { items { hash gasUsed gasPrice success logs { address topic0 data logIndex } } } } ``` (`internalTransactions` is also available here but is expensive — use it sparingly.) ### 3. ERC-20 transfers with human-readable amounts ```graphql query Transfers($addr: String!) { erc20TokenTransfers(input: { filters: { or: [{ fromAddress: { eq: $addr } }, { toAddress: { eq: $addr } }] } pagination: { limit: 50 } orderBy: [{ field: BLOCK_NUMBER, direction: DESC }] }) { items { tokenAddress fromAddress toAddress txHash blockNumber parsedTransfer { amountFormatted decimals } } } } ``` ### 4. Wallet snapshot: native balance + token balance + top holders ```graphql query Wallet($addr: String!, $token: String!) { balance(walletAddress: $addr) { chainId balance { decimal wei } } erc20Token(tokenAddress: $token) { erc20BalanceOf(walletAddress: $addr) { balance { decimal } } erc20Holders(limit: 10) { walletAddress balance { decimal } } } } ``` (`balance` and `erc20BalanceOf` return a response object nesting `balance { hex wei decimals decimal }`.) ### 5. DEX activity: Uniswap V2 swaps for a pair ```graphql query Swaps($pair: String!) { erc20TokenSwapEvents(input: { filters: { pairAddress: { eq: $pair } } pagination: { limit: 20 } orderBy: [{ field: BLOCK_NUMBER, direction: DESC }] }) { items { txHash blockNumber parsedSwap { tokenIn { address amountFormatted } tokenOut { address amountFormatted } } } } } ``` ### 6. Raw event logs by contract and topic ```graphql query ContractLogs($contract: String!, $topic0: String!, $fromBlock: Int!) { logs(input: { filters: { address: { eq: $contract } topic0: { eq: $topic0 } # event signature hash; drop for all events blockNumber: { gte: $fromBlock } } orderBy: [{ field: BLOCK_NUMBER, direction: DESC }] pagination: { limit: 20 } }) { items { address topic0 topic1 data blockNumber txHash logIndex } } } ``` ## Other query roots blocks, erc20TokenApprovals, erc721Transfers, ethCall, ethGetTransactionCount, ethGetCode, getStorageAt, estimateGas, web3Sha3, metadata, ethSyncing, dbSyncStatus. See the SDL for exact shapes — every field carries a docstring with (db)/(rpc) provenance. Fields marked (rpc) proxy to a node and can be slower or intermittently unavailable; prefer (db) fields when both exist. ## Site-wide overview https://hyperflowlabs.com/llms.txt