7Block Labs
Blockchain Development

ByAUJay

Which of These Are Ethereum APIs? A Practical Guide for Backend Engineers

Description: Feeling a bit lost with all the “Ethereum APIs” that seem so similar? This handy, up-to-date guide breaks down what's really standardized in Ethereum's stack--like Execution JSON-RPC, Beacon REST, Engine, and ERC-4337 Bundlers--compared to the provider add-ons. You’ll find real examples, some important caveats, and the latest best practices for building solid production backends.


TL;DR for decision‑makers

  • When people say “Ethereum API,” they’re usually talking about the Execution client JSON‑RPC (you know, those eth_ methods) that the community has put together. This is what clients like Geth, Nethermind, Besu, and Erigon use to read state and send transactions. It's pretty much the go-to interface for all that stuff. Check it out here: (github.com)
  • There are also some other official APIs that focus on different aspects, like the Beacon (consensus) REST, Engine API (which connects CL↔EL internally), and the ERC‑4337 Bundler RPC. You might notice a bunch of “extra” endpoints from providers, like alchemy_getAssetTransfers and qn_*, but keep in mind these are more about indexing and adding value rather than being standard Ethereum APIs. So, pick what you need thoughtfully! (github.com)

1) What counts as an “Ethereum API”?

  • Execution JSON-RPC (core “eth_”): This is basically the go-to way for users and tools to interact with the network. All the execution clients stick to this standard, so you’ll find consistent method names, types, and error handling thanks to EIPs and the execution-apis project. It's what you’ll use for reading/writing data, estimating gas and fees, looking at logs, and even for pub/sub activities. Check it out here: (github.com).
  • Consensus “Beacon API” (REST): This one’s made available by consensus clients and is all about validator and beacon details (think validators, finality, and sync committees). Just a heads up, it’s HTTP/REST, not JSON-RPC, and you won't use it for sending L1 transactions. Dive in: (github.com).
  • Engine API (JWT-auth JSON-RPC on 8551): This serves as the inner workings between the consensus layer and execution layer (like engine_newPayloadV3/V4 and fork choice updates). Just a tip: don’t build your dapps on this one since it’s meant for node operators and clients. It also changes with forks (like Deneb/Cancun for blobs). More details here: (docs.erigon.tech).
  • ERC-4337 Bundler RPC: This is a dedicated JSON-RPC for Account Abstraction, specifically for the UserOperation mempool. You'll find methods like eth_sendUserOperation and eth_estimateUserOperationGas defined by a new standard (EIP-7769). This is the one to use when you’re creating smart wallet flows. Get the scoop here: (eips.ethereum.org).

Provider-specific indexing APIs like alchemy_getAssetTransfers or qn_getTokenMetadataByContractAddress aren’t official Ethereum standards, but they can really speed things up for your product when you’re okay with depending on vendors. Check out more about it on alchemy.com.


2) The Execution JSON‑RPC you will use every day

2.1 Method families and block tags

  • Gossip: Keep an eye on the head and send transactions using (eth_blockNumber, eth_sendRawTransaction).
  • State: Check balances and storage with eth_getBalance, eth_getStorageAt, eth_getCode, eth_call, and eth_estimateGas.
  • History: Look up past info with eth_getBlockByNumber/Hash, eth_getTransactionByHash, eth_getTransactionReceipt, and eth_getLogs.
  • Block tags consist of "latest," "pending," along with the post-Merge "safe" and "finalized" for those extra solid confirmations. If you're working in systems that need reliable guarantees, go for "safe" or "finalized." Check it out more on ethereum.org.

Block Parameter Object

A bunch of methods allow you to specify a block using a hash (thanks to EIP-1898) to clear up any confusion with reorgs. This is super useful for making sure your reads are consistent in multi-call workflows. Check out the full details here: eips.ethereum.org

2.2 Gas and fees you should rely on in 2025

  • EIP‑1559 Dynamic Fees: To figure out maxPriorityFeePerGas, use eth_feeHistory along with reward percentiles--it's a much better approach than sticking with the old eth_gasPrice, especially when you're dealing with anything that’s time-sensitive. More details can be found here.
  • Blob Fees (EIP‑4844): For blob-carrying (type-3) transactions, you’ll need to add max_fee_per_blob_gas and keep an eye on the blob base fee market. Check eth_blobBaseFee to see what the current blob base fee is (in wei per blob gas) so you can plan your rollup data costs better. You can dive deeper here.

Quick Snippet: Combining EIP‑1559 Fee and Blob Fee

To calculate a dynamic EIP‑1559 fee alongside a blob fee, you can follow these steps:

  1. Determine the base fee: Get the base fee from the latest block header using JSON-RPC. This is the starting point for your EIP-1559 fee calculation.

    {
      "jsonrpc": "2.0",
      "method": "eth_getBlockByNumber",
      "params": ["latest", false],
      "id": 1
    }
  2. Calculate the priority fee: You'll want to decide how much extra you're willing to pay to prioritize your transaction. This is typically a fixed value you can adjust based on network conditions.
  3. Get the blob fee: If you’re working with layer-2 solutions or rollups, there's often an additional fee structure. Make sure to fetch the latest blob fee data from your provider or relevant network information.
  4. Add it all together: Once you’ve got both the EIP-1559 fee (base fee + priority fee) and the blob fee, sum them up for your total transaction fee:

    const totalFee = baseFee + priorityFee + blobFee;
  5. Submit your transaction: Make sure to use this calculated total fee when signing and sending your transaction.

By following these steps, you’ll be able to derive a dynamic fee that includes both EIP-1559 and blob considerations, ensuring your transaction is competitive in the current network landscape!

// 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 goes hand in hand with EIP-1559 and the fresh blob fee market that EIP-4844 brought into play. You can check out more about it here: (eips.ethereum.org).

2.3 Events and logs without foot‑guns

  • If you're aware of which block you’re scanning, go for eth_getLogs with a blockHash filter (EIP-234). This way, you dodge any confusion from reorgs, and it’s super clear even if the result comes back empty. (eips.ethereum.org)
  • When you’re working with longer ranges, make sure to keep an eye on provider limits (usually around 10k blocks per call or something close). Break your requests into chunks; many providers have caps on range and/or response size. So, it’s a good idea to build in some chunkers and retry logic. (quicknode.com)

Example: a straightforward, one-block 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 gives you the option to use blockHash objects in state queries such as eth_call and eth_getStorageAt, ensuring everything stays consistent across multi-call reads. You can check it out more here.

2.4 Real‑time subscriptions (WebSockets)

Use eth_subscribe via WebSocket for updates on new heads, logs, new pending transactions, and syncing. Try to steer clear of polling when you can. Keep in mind that your subscriptions will drop when the WebSocket connection goes down--so you'll need to 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"]}

Check out Ethereum.org’s WebSocket tutorial if you’d rather use a client library. You can find it here.

2.5 Big‑picture JSON‑RPC hygiene

  • Batch requests: With JSON‑RPC 2.0, you can group multiple requests into a single HTTP round-trip. This is a great way to combine dependent reads and cut down on latency. Check it out here.
  • Standard encoding and errors: Make sure to stick to EIP‑1474 for value encoding (like hex quantities with a 0x-prefix) and pay close attention to JSON‑RPC error codes. You can find more info here.

3) Newer and advanced Execution RPC you should know

3.1 eth_getProof for verifiable reads (EIP‑1186)

eth_getProof gives you Merkle proofs for accounts or storage tied to a specific block. This feature is fantastic for supporting stateless or light-client verification. It’s especially handy for trust-minimized bridges, rollups, or any compliance processes that require on-chain verifiability. Check out more details here!

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 introduces type-1 transactions that come with access lists. These lists let you pre-define addresses and storage, which helps reduce costs for warm accesses. Plus, clients now offer eth_createAccessList, making it easy to simulate and create these lists for your calls. This can lead to better predictability and less fluctuation in gas estimation. Check it out here: (eips.ethereum.org)

3.3 Blob‑aware block fields (EIP‑4844)

After the Dencun upgrade, blocks now include blob_gas_used and excess_blob_gas. Meanwhile, type-3 transactions come with max_fee_per_blob_gas and blob_versioned_hashes. If you're working on rollup infrastructure or batching data to L1, it's important to estimate the blob fee using eth_blobBaseFee and set a competitive max_fee_per_blob_gas. Check out the details on the EIP page.

3.4 State and block overrides in simulations

Geth and Erigon now let you use state overrides in eth_call and block overrides in the advanced simulation endpoints. This feature is super handy for running "what-if" scenarios, like checks before an upgrade, all without the hassle of redeploying contracts. Think of it as a debugging tool, but keep in mind that not every provider will necessarily support it. Check out more details at 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

A lot of clients, like Nethermind, offer the eth_getBlockReceipts feature, which lets you grab all the receipts for a block in a single request. This is a major improvement compared to querying for each transaction individually. Just be sure to check with your provider or client to make sure it supports this feature. You can find more details here.


4) Production patterns for logs, fees, and throughput

  • When you're pulling logs, try to break it down by block range and narrow it down by topics or addresses. Be mindful of provider limits--like those 10k-block ranges and the 150MB cap on responses. Make sure you've got a plan for retries and backoff, and keep things idempotent. (quicknode.com)
  • For read models where you care more about consistency than having the freshest data--like in accounting, reporting, or compliance--it's a good idea to use the “safe” or “finalized” tags. (ethereum.org)
  • Don’t forget to batch your JSON-RPC requests for those “N small reads” per page or API call. This is a well-defined approach and is supported by a lot of systems. (json-rpc.org)
  • If you want deterministic replay, go for blockHash-scoped logs (EIP-234). It’s a solid choice! (eips.ethereum.org)

5) L2s are “Ethereum‑compatible”--mind the differences

  • A lot of the major Layer 2 networks are using the same eth_* JSON-RPC framework, but they throw in some chain-specific methods and tracing namespaces for good measure.
    • For example, Arbitrum has arbtrace_* (for pre-Nitro ranges) and debug_trace* for the newer ranges. They also have some unique transaction types and fields. You can check out more about it here.
    • Then there’s the OP Stack (Optimism/Base), which has op-node that reveals rollup data, like optimism_outputAtBlock and optimism_syncStatus. This data is separate from the usual execution RPC. So, for app logic, stick with eth_*, but for the rollup RPC stuff, that’s where you want to look for ops and observability. More details can be found here.
  • And let's talk about blob fee RPCs on Layer 2s. A bunch of providers are also offering eth_blobBaseFee on Base/OP. If you're posting blobs from L2 infrastructure to L1, don’t forget to check both the L2 transaction fees and the L1 blob fee if that applies to you. You can dive deeper into that here.

6) The APIs that are NOT Ethereum (but are useful)

Examples:

  • Alchemy Transfers: Check out alchemy_getAssetTransfers for tracking transfers across ERC‑20/721/1155 tokens.
  • QuickNode Token/NFT API: Use endpoints like qn_getTokenMetadataByContractAddress and qn_getTransactionsByAddress, among others.

These endpoints are all about indexing and adding value--they're super fast but aren't really meant to be the one-and-only source for important consensus-driven logic. Think of them like any other external database; it's a good idea to couple them with reliable on-chain verification whenever you need that extra layer of trust. (alchemy.com)


7) Beacon and Engine APIs for infrastructure teams

  • Beacon API (REST): This one's great for querying validators, finality checkpoints, committee assignments, and checking node health. It’s perfect for building staking dashboards, handling validator operations, and monitoring client observability. Just a heads-up: don't use it for app-layer state reads. You can check it out here.
  • Engine API: This API helps with CL↔EL coordination, including fork choice and payload execution. They’ve rolled out different versions across forks--like V2 for withdrawals in Shanghai and V3 for blobs in Cancun/Deneb. Remember, this is meant only for node use with JWT authentication, so it's not something you want to make public. Find more details here.

8) ERC‑4337 Bundler RPC (Account Abstraction)

If you're diving into smart-wallet experiences like sponsored gas or custom validation, you'll need to communicate with a Bundler using methods such as eth_sendUserOperation, eth_estimateUserOperationGas, and eth_getUserOperationReceipt. There's a formal JSON-RPC surface getting standardized with EIP-7769, and you'll find that major bundlers are starting to implement it. Just make sure to check which Entrypoint version support you have (between v0.6 and v0.8) and look into EIP-7702 interactions when it's relevant. You can find more details here.

# 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

  • Get the ERC‑20 balances for N addresses at a specific block hash. You'll receive both the balance values and the block metadata that you requested.
// 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 helps to prevent those pesky “slipping blocks” that can happen when you make multiple calls. (eips.ethereum.org)

9.2 Efficient receipts fetch for analytics

When it's available, go for eth_getBlockReceipts instead of using 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

Make sure to check out the client/provider support--like how Nethermind handles it. You can find more info here.

9.3 WebSocket subscription with fallback

  • Subscribe to newHeads. If you get disconnected, just pick up where you left off by polling getLogs using blockHash for each missed block.

This brings together pubsub to keep things fresh and EIP‑234 for a reliable backfill. You can check out more about it here.


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 on ethereum.org/execution‑apis? Yes → It’s a standard. (github.com)
  • Is it Beacon REST (GET /eth/v1/...)? Yes → This is for consensus/validator data, not your dapp state. (github.com)
  • Is it the Engine API (engine_*), running on port 8551 with JWT? Yup → That’s node‑internal stuff; don't use it for apps. (docs.erigon.tech)
  • Is it the ERC‑4337 bundler RPC (eth_sendUserOperation, etc.)? Yep → It’s in the process of being standardized, aimed at AA smart wallets. (eips.ethereum.org)
  • Is it alchemy_* or qn_* or any other vendor-prefixed stuff? That’s provider-specific indexing--handle with care. (alchemy.com)

12) Final guidance from 7Block Labs

  • Kick things off with the standard Execution JSON‑RPC to ensure everything's correct and can easily be moved around. If you need a speed boost, layer on some provider indexers as read-through caches. Check it out on GitHub.
  • For that extra peace of mind, make sure to use EIP‑1898 blockHash parameters and include "safe/finalized" tags. Build a block‑indexed data model while you're at it. More details can be found on EIPs.
  • If you're developing rollup or wallet infrastructure, consider adding Engine/Beacon/Bundler as needed. Just remember to keep them separate from your public app API--maintain those service boundaries! You can find more info at Erigon Docs.

If you're looking for an architecture review or a build partner, 7Block Labs is here to help! We specialize in designing, scaling, and operating tech stacks for both startups and enterprises. Let’s align the APIs with your objectives and get things rolling faster--without any unexpected bumps along the way.


References (selected)

  • Check out the Ethereum Execution APIs based on the canonical JSON-RPC spec and EIP-1474.
  • For a deep dive, the Ethereum.org JSON-RPC guide covers block tags and method families pretty well.
  • Don’t miss EIP-1898, which introduces a block parameter by hash, and EIP-234 for using blockHash in filters. You can find more info on these at EIP-1898.
  • EIP-1559 revolutionized the fee market. Learn how to use eth_feeHistory by checking out this link.
  • Interested in blobs? EIP-4844 covers that along with eth_blobBaseFee. Dive in here.
  • EIP-1186 introduces eth_getProof, and EIP-2930 has all the details on access lists. You can read more about it here.
  • If you’re into WebSockets, the pubsub feature (eth_subscribe) is a must-know. Check out the details on geth.
  • The Beacon API (REST) and Engine API have some crucial notes you won’t want to miss. Get the scoop on GitHub.
  • There’s also the ERC-4337 Bundler RPC, which aligns with EIP-7769. You can explore that here.
  • Lastly, don’t overlook the provider log limits and guidance available at QuickNode.

Like what you're reading? Let's build together.

Get a free 30-minute consultation with our engineering team.

7BlockLabs

Full-stack blockchain product studio: DeFi, dApps, audits, integrations.

7Block Labs is a trading name of JAYANTH TECHNOLOGIES LIMITED.

Registered in England and Wales (Company No. 16589283).

Registered Office address: Office 13536, 182-184 High Street North, East Ham, London, E6 2JA.

© 2026 7BlockLabs. All rights reserved.