Skip to content

JSON-RPC

Each chain has a JSON-RPC endpoint at POST /{chain}, where {chain} is either the chain ID in decimal or the network's name: for example, https://bruno.mailam.app/sepolia. The methods are the same operations as REST. Each one takes the REST request as its only parameter and returns the REST response. The specification's interface is the normative reference.

Method REST equivalent Parameter Result
postpaid_config GET /v1/config none payee, tokens, maxGas, maxCallBytes
postpaid_quote GET /v1/quote {gas, callBytes, tokens, authority?, payer?, deployment?, verifyGas?} validUntilBlock, quotes: [{token, amount}]
postpaid_sendTransaction POST /v1/submissions the submission: {call, authorizationList?, gas, payment, deployment?, maxBlockNumber} id
postpaid_getStatus GET /v1/submissions/{id} id status, stage, attempts, transactionHash?, blockNumber?, confirmations?, reason?, revertData?
eth_estimateUserOperationGas POST /v1/user-operations/gas userOperation, entryPoint (two parameters, as ERC-7769 has them) preVerificationGas, verificationGasLimit, callGasLimit
postpaid_quoteUserOperation POST /v1/user-operations/quote userOperation, entryPoint, the op paying by its calls, its payment a placeholder validUntilBlock, quotes: [{token, amount}]: what to pay before it's signed
eth_sendUserOperation POST /v1/user-operations userOperation, entryPoint the op's hash
eth_getUserOperationReceipt GET /v1/user-operations/{hash} the op's hash ERC-7769's receipt, or null until it's included
pimlico_getUserOperationGasPrice, zd_getUserOperationGasPrice none none The price an op paying by its fees is asked, as both its fees: {slow, standard, fast} alike
eth_supportedEntryPoints none none EntryPoint v0.8's and v0.7's addresses
eth_chainId none none The chain's id
rpc.discover none none The OpenRPC document, with this chain's endpoint as its server

Any other method is refused as not found. The endpoint isn't a node: read the chain through your own.

The REST page explains each field and the shape of a submission, including signed transfers and smart wallets. The one difference is in a quote: REST takes a deployment as three parameters, account, factory and factoryData, and JSON-RPC takes it as one object, deployment: {account, factory, factoryData}, as a submission does.

Examples

From Sepolia:

$ curl -s https://bruno.mailam.app/sepolia -H 'content-type: application/json' -d @- <<'EOF' | jq
{"jsonrpc": "2.0", "id": 1, "method": "postpaid_config", "params": []}
EOF
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "payee": "0xfBC0cF0d2C09C57222C871B1cbF9b153bfFA0049",
    "tokens": [
      "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
      "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14",
      "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
    ],
    "maxGas": "0x1e8480",
    "maxCallBytes": "0xa000"
  }
}

$ curl -s https://bruno.mailam.app/sepolia -H 'content-type: application/json' -d @- <<'EOF' | jq
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "postpaid_quote",
  "params": [
    {
      "gas": "0x186a0",
      "callBytes": "0x200",
      "tokens": ["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]
    }
  ]
}
EOF
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "validUntilBlock": "0xb7127a",
    "quotes": [
      {
        "token": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
        "amount": "0x39825521640b6"
      }
    ]
  }
}

Errors

Errors use JSON-RPC's error object, with the codes listed in the specification, and the same data as over REST:

$ curl -s https://bruno.mailam.app/sepolia -H 'content-type: application/json' -d @- <<'EOF' | jq
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "postpaid_quote",
  "params": [
    {
      "gas": "0x01",
      "callBytes": "0x200",
      "tokens": ["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"]
    }
  ]
}
EOF
{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32602,
    "message": "gas: a quantity, as hex",
    "data": "gas"
  }
}

Try it

The methods are described by an OpenRPC 1.3.2 document. It's served at /openrpc.json, listing every chain's endpoint as a server, and rpc.discover returns it with just that chain's endpoint.

  • Browse it and try each method in the OpenRPC Playground: playground.open-rpc.org/?url=https://bruno.mailam.app/sepolia. Give the playground a chain's endpoint, not /openrpc.json. It reads the document from the endpoint with rpc.discover, and "Try It Now" sends to that endpoint. Given a .json file, it sends requests to its own site instead. "Try It Now" only opens the request in the inspector; press the inspector's play button to send it.
  • Send requests with the OpenRPC Inspector: inspector.open-rpc.org/?url=https://bruno.mailam.app/sepolia. The relay accepts requests from any origin, so the inspector can call it directly.

Getting terms, quotes and statuses is free. A submission needs a signed call, which the TypeScript client can make for you.