API Reference
Complete reference for Prism's JSON-RPC API, HTTP endpoints, and custom extensions.
Table of Contents
HTTP Endpoints
Prism exposes the following HTTP endpoints:
/
POST
Single or batch JSON-RPC request
application/json
/health
GET
Health check and status information
application/json
/metrics
GET
Prometheus metrics
text/plain
Note: Batch requests are sent to
/as an array, not to a separate/batchendpoint.
/ - Single JSON-RPC Request
/ - Single JSON-RPC RequestSend a single JSON-RPC 2.0 request.
Request:
POST / HTTP/1.1
Host: localhost:3030
Content-Type: application/json
X-API-Key: your-api-key-here # Optional, if auth enabled
{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 1
}Response:
HTTP/1.1 200 OK
Content-Type: application/json
X-Cache-Status: MISS
{
"jsonrpc": "2.0",
"result": "0x11a6e3b",
"id": 1
}/ - Batch Requests
/ - Batch RequestsSend multiple JSON-RPC requests in a single HTTP call by passing an array:
Request:
POST / HTTP/1.1
Host: localhost:3030
Content-Type: application/json
[
{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 1
},
{
"jsonrpc": "2.0",
"method": "eth_chainId",
"params": [],
"id": 2
}
]Response:
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"jsonrpc": "2.0",
"result": "0x11a6e3b",
"id": 1
},
{
"jsonrpc": "2.0",
"result": "0x1",
"id": 2
}
]/health - Health Check
/health - Health CheckGet system health and upstream status.
Request:
GET /health HTTP/1.1
Host: localhost:3030Response:
{
"status": "healthy",
"version": "1.0.0",
"upstreams": [
{
"name": "alchemy-mainnet",
"healthy": true,
"chain_id": 1,
"latest_block": 18500000,
"finalized_block": 18499900,
"response_time_ms": 45,
"error_count": 0,
"circuit_breaker": "closed"
},
{
"name": "infura-mainnet",
"healthy": true,
"chain_id": 1,
"latest_block": 18500001,
"finalized_block": 18499901,
"response_time_ms": 52,
"error_count": 0,
"circuit_breaker": "closed"
}
],
"cache": {
"enabled": true,
"blocks_cached": 1500,
"logs_cached": 25000,
"transactions_cached": 10000,
"cache_hit_rate": 0.87
},
"metrics": {
"total_requests": 125000,
"total_errors": 145,
"average_latency_ms": 38.5
}
}/metrics - Prometheus Metrics
/metrics - Prometheus MetricsPrometheus-compatible metrics endpoint.
Request:
GET /metrics HTTP/1.1
Host: localhost:3030Response:
# HELP rpc_requests_total Total number of RPC requests
# TYPE rpc_requests_total counter
rpc_requests_total{method="eth_blockNumber",upstream="alchemy"} 1250
# HELP rpc_cache_hits_total Cache hits by method
# TYPE rpc_cache_hits_total counter
rpc_cache_hits_total{method="eth_getBlockByNumber"} 890
# HELP rpc_request_duration_seconds Request latency histogram
# TYPE rpc_request_duration_seconds histogram
rpc_request_duration_seconds_bucket{method="eth_getLogs",upstream="alchemy",le="0.05"} 450
rpc_request_duration_seconds_bucket{method="eth_getLogs",upstream="alchemy",le="0.1"} 780
rpc_request_duration_seconds_bucket{method="eth_getLogs",upstream="alchemy",le="+Inf"} 892
rpc_request_duration_seconds_sum{method="eth_getLogs",upstream="alchemy"} 45.2
rpc_request_duration_seconds_count{method="eth_getLogs",upstream="alchemy"} 892Supported RPC Methods
Prism supports the following Ethereum JSON-RPC methods:
Cached Methods
These methods use Prism's caching system for improved performance:
eth_getBlockByHash
Block Cache
Get block by hash (with or without transactions)
eth_getBlockByNumber
Block Cache
Get block by number (with or without transactions)
eth_getLogs
Log Cache
Get event logs with partial-range support
eth_getTransactionByHash
Transaction Cache
Get transaction by hash
eth_getTransactionReceipt
Transaction Cache
Get transaction receipt
Forwarded Methods (No Caching)
These methods are forwarded directly to upstream providers:
net_version
Get network ID
eth_blockNumber
Get latest block number
eth_chainId
Get chain ID
eth_gasPrice
Get current gas price
eth_getBalance
Get account balance
eth_getCode
Get contract code
Request Format
All requests must conform to JSON-RPC 2.0 specification.
Structure
{
"jsonrpc": "2.0",
"method": "method_name",
"params": [...],
"id": 1
}jsonrpc
string
Yes
Must be "2.0"
method
string
Yes
RPC method name (e.g., "eth_blockNumber")
params
array
No
Method parameters (can be empty [] or omitted)
id
number/string
Yes
Request identifier, echoed in response
Method-Specific Parameters
eth_getBlockByNumber
eth_getBlockByNumber{
"jsonrpc": "2.0",
"method": "eth_getBlockByNumber",
"params": [
"0x1000000", // Block number (hex) or "latest", "earliest", "pending"
true // Include full transaction objects (true) or hashes only (false)
],
"id": 1
}eth_getBlockByHash
eth_getBlockByHash{
"jsonrpc": "2.0",
"method": "eth_getBlockByHash",
"params": [
"0x1234567890abcdef...", // Block hash (32 bytes, hex-encoded)
false // Include transactions
],
"id": 1
}eth_getLogs
eth_getLogs{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [{
"fromBlock": "0x1000000", // Start block (hex) or "latest", "earliest"
"toBlock": "0x1000100", // End block (hex) or "latest", "earliest"
"address": "0x1234...", // Contract address or array of addresses
"topics": [ // Event topics filter (optional)
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", // Topic 0
null, // Topic 1 (any)
"0x000000000000000000000000abcdef1234567890abcdef1234567890abcdef" // Topic 2
]
}],
"id": 1
}eth_getTransactionByHash
eth_getTransactionByHash{
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
"params": [
"0x1234567890abcdef..." // Transaction hash (32 bytes, hex-encoded)
],
"id": 1
}eth_getTransactionReceipt
eth_getTransactionReceipt{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": [
"0x1234567890abcdef..." // Transaction hash (32 bytes, hex-encoded)
],
"id": 1
}Response Format
All responses conform to JSON-RPC 2.0 specification.
Success Response
{
"jsonrpc": "2.0",
"result": <result_data>,
"id": 1
}jsonrpc
string
Always "2.0"
result
any
Method-specific result data
id
number/string
Request ID echoed from request
Error Response
{
"jsonrpc": "2.0",
"error": {
"code": -32600,
"message": "Invalid Request",
"data": "Additional error information"
},
"id": 1
}jsonrpc
string
Always "2.0"
error.message
string
Human-readable error message
error.data
any
Optional additional error data
id
number/string/null
Request ID or null if ID couldn't be determined
Custom Headers
Prism adds custom headers to responses for observability and debugging.
X-Cache-Status
X-Cache-StatusIndicates how the request was served from cache or upstream.
Values:
MISS
Request served entirely from upstream (not in cache)
FULL
Complete cache hit, no upstream call needed
PARTIAL
Some data from cache, rest fetched from upstream
EMPTY
Cached empty result (e.g., no logs found in range)
PARTIAL_WITH_FAILURES
Partial cache hit with some upstream failures
Example:
HTTP/1.1 200 OK
Content-Type: application/json
X-Cache-Status: FULLRequest Headers
X-API-Key (Authentication)
X-API-Key (Authentication)Include your API key when authentication is enabled.
X-API-Key: your-api-key-hereAlternatively, use query parameter:
POST /?api_key=your-api-key-hereStandard Headers
Content-Type: application/json # Required for POST requests
Accept: application/json # OptionalBatch Requests
Send multiple requests in a single HTTP call to reduce latency.
Format
Array of JSON-RPC request objects:
[
{
"jsonrpc": "2.0",
"method": "eth_getBlockByNumber",
"params": ["0x1000000", false],
"id": 1
},
{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [{
"fromBlock": "0x1000000",
"toBlock": "0x1000010"
}],
"id": 2
}
]Response
Array of JSON-RPC response objects (order may not match request order):
[
{
"jsonrpc": "2.0",
"result": { /* block data */ },
"id": 1
},
{
"jsonrpc": "2.0",
"result": [ /* logs array */ ],
"id": 2
}
]Benefits
Reduced HTTP overhead: Single connection for multiple requests
Lower latency: Batch processing reduces round-trip time
Atomic execution: All requests processed together
Limitations
Maximum batch size: Configured by
max_concurrent_requestsEach request is still processed independently (no transaction semantics)
Cache status header applies to batch as a whole
Error Codes
Prism follows JSON-RPC 2.0 error codes with some extensions.
Standard JSON-RPC Errors
-32700
Parse error
Invalid JSON received
-32600
Invalid Request
Request object is malformed
-32601
Method not found
Method does not exist or is not supported
-32602
Invalid params
Invalid method parameters
-32603
Internal error
Internal server error
Ethereum-Specific Errors
-32000
Server error
Generic server error
-32001
Resource not found
Requested resource does not exist
-32002
Resource unavailable
Resource temporarily unavailable
-32003
Transaction rejected
Transaction would not be accepted
-32004
Method not supported
Method is not implemented
-32005
Limit exceeded
Request exceeds defined limit
Prism-Specific Errors
-32050
No healthy upstreams
All upstream providers are unavailable
-32051
Circuit breaker open
Upstream circuit breaker is open
-32052
Consensus failure
Upstreams disagree on response (consensus mode)
-32053
Rate limit exceeded
Request rate limit exceeded
-32054
Authentication failed
Invalid or missing API key
-32055
Method not allowed
API key does not have permission for this method
Upstream Provider Errors
Errors from upstream providers are passed through with their original error codes.
Example Upstream Error:
{
"jsonrpc": "2.0",
"error": {
"code": -32005,
"message": "Query returned more than 10000 results",
"data": "Try with a smaller block range"
},
"id": 1
}Code Examples
JavaScript / Node.js
const axios = require('axios');
async function getBlockNumber() {
const response = await axios.post('http://localhost:3030/', {
jsonrpc: '2.0',
method: 'eth_blockNumber',
params: [],
id: 1
}, {
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'your-api-key-here' // If auth enabled
}
});
console.log('Block number:', response.data.result);
console.log('Cache status:', response.headers['x-cache-status']);
}
getBlockNumber();Python
import requests
def get_block_number():
url = 'http://localhost:3030/'
headers = {
'Content-Type': 'application/json',
'X-API-Key': 'your-api-key-here' # If auth enabled
}
payload = {
'jsonrpc': '2.0',
'method': 'eth_blockNumber',
'params': [],
'id': 1
}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
print(f"Block number: {data['result']}")
print(f"Cache status: {response.headers.get('X-Cache-Status')}")
get_block_number()cURL
# Simple request
curl -X POST http://localhost:3030/ \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key-here" \
-d '{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 1
}'
# Batch request (array to same / endpoint)
curl -X POST http://localhost:3030/ \
-H "Content-Type: application/json" \
-d '[
{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1},
{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":2}
]'
# Get logs with cache status
curl -s -D - http://localhost:3030/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [{
"fromBlock": "0x1000000",
"toBlock": "0x1000100",
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}],
"id": 1
}' | grep -i cache-statusRust (using reqwest)
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let response = client
.post("http://localhost:3030/")
.header("Content-Type", "application/json")
.header("X-API-Key", "your-api-key-here")
.json(&json!({
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 1
}))
.send()
.await?;
let cache_status = response
.headers()
.get("x-cache-status")
.and_then(|v| v.to_str().ok());
let body: serde_json::Value = response.json().await?;
println!("Block number: {}", body["result"]);
println!("Cache status: {:?}", cache_status);
Ok(())
}Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
type JsonRpcRequest struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params []interface{} `json:"params"`
ID int `json:"id"`
}
type JsonRpcResponse struct {
Jsonrpc string `json:"jsonrpc"`
Result json.RawMessage `json:"result"`
ID int `json:"id"`
}
func main() {
req := JsonRpcRequest{
Jsonrpc: "2.0",
Method: "eth_blockNumber",
Params: []interface{}{},
ID: 1,
}
payload, _ := json.Marshal(req)
httpReq, _ := http.NewRequest("POST", "http://localhost:3030/", bytes.NewBuffer(payload))
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("X-API-Key", "your-api-key-here")
client := &http.Client{}
resp, _ := client.Do(httpReq)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var response JsonRpcResponse
json.Unmarshal(body, &response)
fmt.Printf("Block number: %s\n", response.Result)
fmt.Printf("Cache status: %s\n", resp.Header.Get("X-Cache-Status"))
}Web3 Library Integration
Prism can be used as a drop-in replacement for any Ethereum RPC endpoint.
ethers.js
const { ethers } = require('ethers');
const provider = new ethers.JsonRpcProvider('http://localhost:3030/', {
name: 'mainnet',
chainId: 1
});
// Use like any other provider
const blockNumber = await provider.getBlockNumber();
console.log('Block number:', blockNumber);
const block = await provider.getBlock(blockNumber);
console.log('Block:', block);web3.py
from web3 import Web3
w3 = Web3(Web3.HTTPProvider('http://localhost:3030/'))
# Use like any other Web3 instance
block_number = w3.eth.block_number
print(f'Block number: {block_number}')
block = w3.eth.get_block(block_number)
print(f'Block: {block}')web3.js
const Web3 = require('web3');
const web3 = new Web3('http://localhost:3030/');
// Use like any other Web3 instance
web3.eth.getBlockNumber().then(blockNumber => {
console.log('Block number:', blockNumber);
});
web3.eth.getBlock(18500000).then(block => {
console.log('Block:', block);
});Next: Learn about Caching or Routing Strategies.
Last updated