ByAUJay
Which of These Are Ethereum APIs? A Practical Guide for Backend Engineers
Description: Confused by “Ethereum APIs” that all look alike? This practical, up-to-date guide maps what’s actually standardized in Ethereum’s stack (Execution JSON‑RPC, Beacon REST, Engine, ERC‑4337 Bundlers) versus provider add‑ons, with concrete examples, caveats, and emerging best practices for production backends.
TL;DR for decision‑makers
- “Ethereum API” usually means the Execution client JSON‑RPC (eth_ methods) defined by community specs and implemented by clients like Geth, Nethermind, Besu, Erigon. It’s the canonical interface for reading state and sending transactions. (github.com)
- There are other official APIs with different scopes: Beacon (consensus) REST, Engine API (CL↔EL internal), and ERC‑4337 Bundler RPC. Many “extra” endpoints you see from providers (e.g., alchemy_getAssetTransfers, qn_*) are indexing/value‑add services, not Ethereum‑standard APIs. Choose each with intent. (github.com)
1) What counts as an “Ethereum API”?
- Execution JSON‑RPC (core “eth_”): the canonical interface between users/tooling and the network. All execution clients implement this spec; method names, types, and error semantics are standardized via EIPs and the execution-apis project. Use this for reads/writes, gas/fee estimation, logs, pubsub. (github.com)
- Consensus “Beacon API” (REST): exposed by consensus clients for validator/beacon data (validators, finality, sync committees). This is HTTP/REST, not JSON‑RPC, and is not used to send L1 transactions. (github.com)
- Engine API (JWT‑auth JSON‑RPC on 8551): the internal CL↔EL interface (e.g., engine_newPayloadV3/V4, forkchoice updates). Don’t build dapps on this; it’s for node operators/clients. It evolves with forks (e.g., Deneb/Cancun for blobs). (docs.erigon.tech)
- ERC‑4337 Bundler RPC: a separate JSON‑RPC for Account Abstraction (UserOperation mempool). Methods like eth_sendUserOperation, eth_estimateUserOperationGas are defined by an emerging standard (EIP‑7769). Use when building smart‑wallet flows. (eips.ethereum.org)
Provider‑specific indexing APIs (e.g., alchemy_getAssetTransfers or qn_getTokenMetadataByContractAddress) are not Ethereum standards, but excellent for product velocity when you accept vendor coupling. (alchemy.com)
2) The Execution JSON‑RPC you will use every day
2.1 Method families and block tags
- Gossip: track head and submit txs (eth_blockNumber, eth_sendRawTransaction).
- State: eth_getBalance, eth_getStorageAt, eth_getCode, eth_call, eth_estimateGas.
- History: eth_getBlockByNumber/Hash, eth_getTransactionByHash, eth_getTransactionReceipt, eth_getLogs.
- Block tags include "latest", "pending", plus post‑Merge "safe" and "finalized" for stronger confirmations. Prefer "safe"/"finalized" in systems that require stronger guarantees. (ethereum.org)
Block parameter object: many methods let you specify a block by hash (EIP‑1898) to avoid reorg ambiguity. Use it for consistent reads across multi‑call workflows. (eips.ethereum.org)
2.2 Gas and fees you should rely on in 2025
- EIP‑1559 dynamic fees: use eth_feeHistory + reward percentiles to derive maxPriorityFeePerGas and set maxFeePerGas. Do not rely on legacy eth_gasPrice for anything latency‑sensitive. (eips.ethereum.org)
- Blob fees (EIP‑4844): blob‑carrying (type‑3) transactions add max_fee_per_blob_gas and interact with the blob base fee market; check eth_blobBaseFee for current blob base fee (in wei per blob gas) to estimate costs for rollup data. (eips.ethereum.org)
Quick snippet: derive a dynamic EIP‑1559 fee and blob fee together.
// Node.js (fetch) — fee strategy using feeHistory + blob base fee const RPC = process.env.RPC_URL; const body = (method, params, id) => ({ jsonrpc: "2.0", id, method, params }); const [fh, blobBase] = await Promise.all([ fetch(RPC, { method: "POST", headers: {"content-type":"application/json"}, body: JSON.stringify(body("eth_feeHistory", [20, "latest", [5,25,50,75,95]], 1)) }).then(r=>r.json()), fetch(RPC, { method: "POST", headers: {"content-type":"application/json"}, body: JSON.stringify(body("eth_blobBaseFee", [], 2)) }).then(r=>r.json()), ]); const baseFees = fh.result.baseFeePerGas.map(x=>BigInt(x)); const nextBase = baseFees[baseFees.length-1]; // base fee for next block const tips = fh.result.reward.map(a=>BigInt(a[2])); // use p50 (index 2 as example) const p50Tip = tips.reduce((a,b)=>a+b, 0n) / BigInt(tips.length || 1); // Example policy: cap priority fee, 2× base fee buffer, and add blob fee headroom const maxPriorityFeePerGas = p50Tip > 1_000_000_000n ? p50Tip : 1_000_000_000n; // ≥1 gwei const maxFeePerGas = nextBase * 2n + maxPriorityFeePerGas; const blobBaseFee = BigInt(blobBase.result); // per blob gas (wei) console.log({ maxFeePerGas: maxFeePerGas.toString(), maxPriorityFeePerGas: maxPriorityFeePerGas.toString(), blobBaseFee: blobBaseFee.toString() });
This aligns with EIP‑1559 and the new blob fee market introduced by EIP‑4844. (eips.ethereum.org)
2.3 Events and logs without foot‑guns
- Prefer eth_getLogs with a blockHash filter (EIP‑234) when you know which block you’re scanning; it avoids reorg ambiguity and is unambiguous even when the result is empty. (eips.ethereum.org)
- For long ranges, respect provider limits (commonly 10k blocks per call or similar) and chunk requests; many providers cap by block range and/or response size. Build chunkers and retries. (quicknode.com)
Example: one‑block, unambiguous scan.
curl -s -H 'content-type: application/json' -d '{ "jsonrpc":"2.0","id":1,"method":"eth_getLogs", "params":[{"blockHash":"0x<32-byte-block-hash>","topics":["0xddf252ad..."]}] }' $RPC_URL
EIP‑1898 also lets you pass blockHash objects on state queries like eth_call/eth_getStorageAt for consistency across multi‑call reads. (eips.ethereum.org)
2.4 Real‑time subscriptions (WebSockets)
Use eth_subscribe over WebSocket for newHeads, logs, newPendingTransactions, syncing. Avoid polling where possible; remember subscriptions die with the WS connection—reconnect and resubscribe. (geth.ethereum.org)
# Using wscat to subscribe to new block headers wscat -c $WSS_URL > {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
See also Ethereum.org’s WebSocket tutorial if you prefer a client library. (ethereum.org)
2.5 Big‑picture JSON‑RPC hygiene
- Batch requests: JSON‑RPC 2.0 allows batching multiple requests in one HTTP round‑trip. Use it to coalesce dependent reads and reduce latency. (json-rpc.org)
- Standard encoding and errors: follow EIP‑1474 value encoding (hex quantities, 0x‑prefixed) and handle JSON‑RPC error codes carefully. (eips.ethereum.org)
3) Newer and advanced Execution RPC you should know
3.1 eth_getProof for verifiable reads (EIP‑1186)
eth_getProof returns Merkle proofs for account/storage given a block, enabling stateless or light‑client verification. Useful for trust‑minimized bridges, rollups, or compliance flows needing on‑chain verifiability. (eips.ethereum.org)
curl -s -H 'content-type: application/json' -d '{ "jsonrpc":"2.0","id":1,"method":"eth_getProof", "params":["0x0000000000000000000000000000000000000000",[], "finalized"] }' $RPC_URL
3.2 Access lists (EIP‑2930) and eth_createAccessList
EIP‑2930 adds type‑1 txs with access lists that pre‑declare addresses/storage to discount warm accesses; clients also expose eth_createAccessList to simulate and generate lists for a call. This can improve predictability and reduce variance in gas estimation. (eips.ethereum.org)
3.3 Blob‑aware block fields (EIP‑4844)
Post‑Dencun blocks carry blob_gas_used and excess_blob_gas, and type‑3 transactions include max_fee_per_blob_gas and blob_versioned_hashes. If you build rollup infra or batch data to L1, you must estimate the blob fee via eth_blobBaseFee and set a competitive max_fee_per_blob_gas. (eips.ethereum.org)
3.4 State and block overrides in simulations
Geth/Erigon support state overrides in eth_call and block overrides in advanced simulate endpoints. This is invaluable for “what‑if” simulations (e.g., pre‑upgrade checks) without redeploying contracts. Treat it as a debugging tool; do not assume universal provider support. (geth.ethereum.org)
# Simulate a balance change before a read-only call curl -s -H 'content-type: application/json' -d '{ "jsonrpc":"2.0","id":1,"method":"eth_call", "params":[ {"to":"0xToken","data":"0x70a08231...<owner>"}, "latest", {"0xOwner":{"balance":"0x56BC75E2D63100000"}} # 100 ETH in wei ] }' $RPC_URL
3.5 Bulk receipts in one call
Many clients (e.g., Nethermind) expose eth_getBlockReceipts to fetch an entire block’s receipts in one request—a huge win over per‑tx queries. Check your provider/client before relying on it. (docs.nethermind.io)
4) Production patterns for logs, fees, and throughput
- Chunk your getLogs by block range and constrain topics/addresses. Expect provider limits (e.g., 10k‑block ranges; 150MB response caps). Build retry/backoff and idempotency. (quicknode.com)
- Use “safe”/“finalized” tags for read‑models where consistency beats freshness (accounting, reporting, compliance). (ethereum.org)
- Batch JSON‑RPC requests for “N small reads” per page/API call. It’s specified and widely supported. (json-rpc.org)
- Prefer blockHash‑scoped logs (EIP‑234) for deterministic replay. (eips.ethereum.org)
5) L2s are “Ethereum‑compatible”—mind the differences
- Most major L2s implement the same eth_* JSON‑RPC, but add chain‑specific methods and tracing namespaces.
- Arbitrum: arbtrace_* (pre‑Nitro ranges) and debug_trace* for newer ranges, plus differences in tx types/fields. (quicknode.com)
- OP Stack (Optimism/Base): op‑node exposes rollup data (e.g., optimism_outputAtBlock, optimism_syncStatus) separate from the standard execution RPC. Use eth_* for app logic; use rollup RPC for ops/observability. (docs.optimism.io)
- Blob fee RPC on L2s: many providers expose eth_blobBaseFee on Base/OP as well; if you post blobs from L2 infra to L1, read both L2 tx fees and L1 blob fee if relevant. (alchemy.com)
6) The APIs that are NOT Ethereum (but are useful)
Examples:
- Alchemy Transfers: alchemy_getAssetTransfers (indexed transfers across ERC‑20/721/1155).
- QuickNode Token/NFT API: qn_getTokenMetadataByContractAddress, qn_getTransactionsByAddress, etc.
These are indexing/value‑add endpoints—great for speed, unsuitable as the sole source of truth for consensus‑critical logic. Treat them like any external database and pair with canonical on‑chain verification when needed. (alchemy.com)
7) Beacon and Engine APIs for infrastructure teams
- Beacon API (REST): query validators, finality checkpoints, committee assignments, node health; ideal for staking dashboards, validator ops, and CL observability. Don’t use it to build app‑layer state reads. (github.com)
- Engine API: CL↔EL coordination (forkchoice, payload execution). It added versions across forks (e.g., V2 for withdrawals in Shanghai, V3 for blobs in Cancun/Deneb). Only for nodes; JWT‑auth; do not expose publicly. (docs.erigon.tech)
8) ERC‑4337 Bundler RPC (Account Abstraction)
If you’re building smart‑wallet experiences (sponsored gas, custom validation), you’ll talk to a Bundler via methods like eth_sendUserOperation, eth_estimateUserOperationGas, eth_getUserOperationReceipt. The formal JSON‑RPC surface is being standardized (EIP‑7769) and implemented by major bundlers; verify Entrypoint version support (v0.6–v0.8) and EIP‑7702 interactions where relevant. (eips.ethereum.org)
# Submit a UserOperation (simplified) curl -s -H 'content-type: application/json' -d '{ "jsonrpc":"2.0","id":1,"method":"eth_sendUserOperation", "params":[ { "sender":"0x...", "nonce":"0x0", "initCode":"0x", "callData":"0x...", "callGasLimit":"0x5208", "verificationGasLimit":"0x1e8480","preVerificationGas":"0x186a0", "maxPriorityFeePerGas":"0x3b9aca00","maxFeePerGas":"0x2540be400", "paymasterAndData":"0x", "signature":"0x..." }, "0xEntryPoint" ] }' $BUNDLER_URL
9) Code patterns you can drop into a backend today
9.1 Deterministic, reorg‑safe read of token balances
- Read ERC‑20 balances for N addresses at a specific blockHash; return both the values and the block metadata you actually queried.
// Batch eth_call using blockId object (EIP-1898) const calls = addresses.map((addr,i)=>({ jsonrpc:"2.0", id:i+1, method:"eth_call", params:[{to: TOKEN, data: "0x70a08231"+addr.slice(2).padStart(64,'0')},{blockHash: BLOCK_HASH, requireCanonical:false}] })); const res = await fetch(RPC, {method:"POST", headers:{'content-type':'application/json'}, body: JSON.stringify(calls)}); const out = await res.json();
This avoids “slipping blocks” across multiple calls. (eips.ethereum.org)
9.2 Efficient receipts fetch for analytics
When supported, prefer eth_getBlockReceipts over N×eth_getTransactionReceipt.
curl -s -H 'content-type: application/json' -d '{ "jsonrpc":"2.0","id":1,"method":"eth_getBlockReceipts","params":["0x<block-number-hex>"] }' $RPC_URL
Check client/provider support (e.g., Nethermind implements it). (docs.nethermind.io)
9.3 WebSocket subscription with fallback
- Subscribe to newHeads; on disconnect, resume by polling getLogs with blockHash for each missed block.
This combines pubsub for freshness and EIP‑234 for deterministic backfill. (geth.ethereum.org)
10) Emerging practices (late‑2025)
- Prefer “safe”/“finalized” block tags where business logic requires confirmations; switch to “latest” only where UX demands it (e.g., mempool‑sensitive features). (ethereum.org)
- Use feeHistory+percentiles and watchdog blob base fee for blob‑heavy workflows; recalibrate alerts post‑Dencun as blob markets fluctuate. (quicknode.com)
- For L2 tracing and rollup internals, use the rollup‑specific namespaces (arbtrace_, optimism_). Keep app logic on standard eth_* for portability. (docs.arbitrum.io)
- Treat provider indexers as caches, not sources of truth; audit‑critical paths should verify on-chain via standard RPC (e.g., check receipts/logs by blockHash). (alchemy.com)
11) A quick “is this an Ethereum API?” checklist
- Is it part of Execution JSON‑RPC (eth_, net_, web3_) or documented in ethereum.org/execution‑apis? Yes → Standard. (github.com)
- Is it Beacon REST (GET /eth/v1/...)? Yes → Consensus/validator data, not dapp state. (github.com)
- Is it Engine API (engine_*), on port 8551 with JWT? Yes → Node‑internal; don’t use for apps. (docs.erigon.tech)
- Is it ERC‑4337 bundler RPC (eth_sendUserOperation, etc.)? Yes → Standardizing, for AA smart wallets. (eips.ethereum.org)
- Is it alchemy_* or qn_* or other vendor‑prefixed? It’s provider‑specific indexing—use with care. (alchemy.com)
12) Final guidance from 7Block Labs
- Start with the standard Execution JSON‑RPC for correctness and portability; augment with provider indexers as read‑through caches when you need speed. (github.com)
- For higher assurance, adopt EIP‑1898 blockHash parameters and “safe/finalized” tags; build a block‑indexed data model. (eips.ethereum.org)
- If you’re writing rollup or wallet infrastructure, add Engine/Beacon/Bundler where appropriate—but keep them behind service boundaries, not your public app API. (docs.erigon.tech)
If you want an architecture review or a build partner, 7Block Labs designs, scales, and operates these stacks for startups and enterprises. Let’s map the APIs to your goals and ship faster—with fewer surprises.
References (selected)
- Ethereum Execution APIs (canonical JSON‑RPC spec) and EIP‑1474. (github.com)
- Ethereum.org JSON‑RPC guide (block tags, method families). (ethereum.org)
- EIP‑1898 (block parameter by hash) and EIP‑234 (blockHash in filters). (eips.ethereum.org)
- EIP‑1559 fee market and eth_feeHistory usage. (eips.ethereum.org)
- EIP‑4844 blobs and eth_blobBaseFee. (eips.ethereum.org)
- EIP‑1186 eth_getProof and EIP‑2930 access lists. (eips.ethereum.org)
- WebSocket pubsub (eth_subscribe). (geth.ethereum.org)
- Beacon API (REST) and Engine API notes. (github.com)
- ERC‑4337 Bundler RPC (EIP‑7769). (eips.ethereum.org)
- Provider log limits and guidance. (quicknode.com)
Like what you're reading? Let's build together.
Get a free 30‑minute consultation with our engineering team.

