# API integration

Source: https://docs.graphops.xyz/rpc/api

Use this reference to configure endpoints, shape requests, match batch responses, and handle
errors. GraphOps RPC exposes Ethereum-compatible JSON-RPC over HTTPS and WebSocket, plus Bitcoin
JSON-RPC over HTTPS. For individual methods, see [Supported methods](./methods).

## Endpoint patterns

```text
https://rpc.graphops.xyz/v1/evm/<CHAIN_ID>
wss://rpc.graphops.xyz/v1/evm/<CHAIN_ID>

```

_An RPC endpoint names the network in its path: the namespace, then the EVM chain ID. This example is Base (8453). Send the API key in the Authorization header or append it to the path._

```text
https://rpc.graphops.xyz/v1/evm/8453
Authorization: Bearer <GRAPHOPS_API_KEY>
```

- RPC host: `https://rpc.graphops.xyz`
- Namespace: `evm`
- EVM chain ID: `8453`

Endpoint preview. Replace placeholders with your identifier and API key before making requests.

```text
https://rpc.graphops.xyz/v1/evm/1
Authorization: Bearer <GRAPHOPS_API_KEY>
```

[Get query endpoint](https://platform.graphops.xyz/organizations/current/overview/endpoint?product=rpc&networkId=eip155%3A1)
[Supported networks](/rpc/networks)

Use the concrete URL for your target chain in application configuration or client setup.

See [Supported networks](./networks) for current query endpoints and archive coverage.

### Bitcoin endpoints

Bitcoin RPC uses HTTPS and a network name instead of an EVM chain ID. The endpoint route is:

```text
https://rpc.graphops.xyz/v1/bitcoin/<NETWORK>

```

For example, this request reads Bitcoin mainnet chain information. EVM client libraries do not
support Bitcoin JSON-RPC, so the programs use an HTTP client:

CLI · curl

Prerequisites

1. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

[Example project](/examples/rpc.api.sh-3.tar.gz)

```sh
curl --fail-with-body --silent --show-error "https://rpc.graphops.xyz/v1/bitcoin/mainnet" \
  -H "Authorization: Bearer ${GRAPHOPS_API_KEY}" \
  -H "Content-Type: application/json" \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getblockchaininfo",
    "params": []
  }'

```

TypeScript · fetch

Prerequisites

1. Install Node.js.

2. Install tsx. `npm install tsx`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Node.js 24.22.1, tsx 4.23.15.

[Example project](/examples/rpc.api.ts-14.tar.gz)

```typescript
export {};

const response = await fetch("https://rpc.graphops.xyz/v1/bitcoin/mainnet", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.GRAPHOPS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "getblockchaininfo",
    params: [],
  }),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);

console.log(JSON.stringify(await response.json()));

```

Go · net/http

Prerequisites

1. Install Go.

2. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Go 1.26.0.

[Example project](/examples/rpc.api.go-15.tar.gz)

```go
package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

func main() {
	payload := []byte(`{"jsonrpc":"2.0","id":1,"method":"getblockchaininfo","params":[]}`)
	req, err := http.NewRequest(http.MethodPost,
		"https://rpc.graphops.xyz/v1/bitcoin/mainnet", bytes.NewReader(payload))
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("GRAPHOPS_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	resp, err := (&http.Client{Timeout: 30 * time.Second}).Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		log.Fatalf("HTTP %d: %s", resp.StatusCode, body)
	}
	fmt.Println(string(body))
}

```

Rust · reqwest

Prerequisites

1. Install Rust.

2. Install reqwest, serde\_json, and tokio. `cargo add reqwest serde_json tokio -F reqwest/json -F tokio/macros -F tokio/rt-multi-thread`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Rust 1.98.1, reqwest 0.13.5, serde\_json 1.0.145, tokio 1.48.0.

[Example project](/examples/rpc.api.rust-16.tar.gz)

```rust
use serde_json::{json, Value};
use std::{env, error::Error, time::Duration};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let response = reqwest::Client::new()
        .post("https://rpc.graphops.xyz/v1/bitcoin/mainnet")
        .bearer_auth(env::var("GRAPHOPS_API_KEY")?)
        .timeout(Duration::from_secs(30))
        .json(&json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "getblockchaininfo",
            "params": [],
        }))
        .send()
        .await?
        .error_for_status()?;
    let result: Value = response.json().await?;
    println!("{result}");
    Ok(())
}

```

Python · requests

Prerequisites

1. Install Python.

2. Install requests. `python -m pip install requests`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Python 3.12.12, requests 2.34.2.

[Example project](/examples/rpc.api.python-17.tar.gz)

```python
import json
import os

import requests

response = requests.post(
    "https://rpc.graphops.xyz/v1/bitcoin/mainnet",
    headers={
        "Authorization": f"Bearer {os.environ['GRAPHOPS_API_KEY']}",
    },
    json={
        "jsonrpc": "2.0",
        "id": 1,
        "method": "getblockchaininfo",
        "params": [],
    },
    timeout=30,
)
response.raise_for_status()
print(json.dumps(response.json()))

```

Clients that cannot attach headers can use the route-token form instead:

```text
https://rpc.graphops.xyz/v1/bitcoin/mainnet/<GRAPHOPS_API_KEY>

```

## Authentication

Authenticate with an organization-scoped API key. RPC supports header authentication and route-token
authentication. See [Authentication](./authentication) for key creation,
rotation, WebSocket connections, and secret handling.

## Request envelope

Every EVM and Bitcoin JSON-RPC call uses the standard request envelope. Method names and parameter
formats are network-specific; the examples in this section use EVM methods.

| Field     | Type                    | Required                            | Notes                                                                     |
| --------- | ----------------------- | ----------------------------------- | ------------------------------------------------------------------------- |
| `jsonrpc` | string                  | Yes                                 | Must be `"2.0"`.                                                          |
| `id`      | string, number, or null | Required for request/response calls | Use a stable value so clients can match responses, especially in batches. |
| `method`  | string                  | Yes                                 | Standard Ethereum-compatible method name, such as `eth_blockNumber`.      |
| `params`  | array or object         | Method-specific                     | Ethereum JSON-RPC methods usually use positional arrays.                  |

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_blockNumber",
  "params": []
}

```

Output

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x191161d"
}
```

JSON-RPC version

Matches the id you sent

Latest block in decimal: 26,285,597

## HTTPS requests

HTTPS requests use `POST` with `Content-Type: application/json`. The examples below use Ethereum
mainnet.

CLI · curl

Prerequisites

1. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

[Example project](/examples/rpc.api.sh-6.tar.gz)

```sh
curl --fail-with-body --silent --show-error "https://rpc.graphops.xyz/v1/evm/1" \
  -H "Authorization: Bearer ${GRAPHOPS_API_KEY}" \
  -H "Content-Type: application/json" \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_blockNumber",
    "params": []
  }'

```

Output

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x191161d"
}
```

JSON-RPC version

Matches the id you sent

Latest block in decimal: 26,285,597

TypeScript · viem

Prerequisites

1. Install Node.js.

2. Install tsx and viem. `npm install tsx viem`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Node.js 24.22.1, tsx 4.23.15, viem 2.57.10.

[Example project](/examples/rpc.api.ts-7.tar.gz)

```typescript
import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";

const client = createPublicClient({
  chain: mainnet,
  transport: http("https://rpc.graphops.xyz/v1/evm/1", {
    fetchOptions: {
      headers: {
        Authorization: `Bearer ${process.env.GRAPHOPS_API_KEY}`,
      },
    },
  }),
});

const blockNumber = await client.getBlockNumber();
console.log(blockNumber.toString());

```

Output

```json
26285599
```

Latest block in decimal: 26,285,599

Go · ethclient

Prerequisites

1. Install Go.

2. Install github.com/ethereum/go-ethereum. `go get github.com/ethereum/go-ethereum`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Go 1.26.0, github.com/ethereum/go-ethereum v1.17.7.

[Example project](/examples/rpc.api.go-12.tar.gz)

```go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/ethereum/go-ethereum/rpc"
)

func main() {
	ctx := context.Background()
	rpcClient, err := rpc.DialOptions(ctx, "https://rpc.graphops.xyz/v1/evm/1",
		rpc.WithHeader("Authorization", "Bearer "+os.Getenv("GRAPHOPS_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	client := ethclient.NewClient(rpcClient)
	defer client.Close()

	blockNumber, err := client.BlockNumber(ctx)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(blockNumber)
}

```

Output

```json
26285612
```

Latest block in decimal: 26,285,612

Rust · alloy

Prerequisites

1. Install Rust.

2. Install alloy, reqwest, and tokio. `cargo add alloy reqwest tokio -F alloy/provider-ws -F alloy/sol-types -F alloy/contract -F reqwest/json -F tokio/macros -F tokio/rt-multi-thread`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Rust 1.98.1, alloy 2.5.0, reqwest 0.13.5, tokio 1.48.0.

[Example project](/examples/rpc.api.rust-13.tar.gz)

```rust
use alloy::providers::{Provider, ProviderBuilder};
use alloy::rpc::client::RpcClient;
use alloy::transports::http::Http;
use reqwest::header::{HeaderMap, AUTHORIZATION};
use std::{env, error::Error};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let mut headers = HeaderMap::new();
    headers.insert(
        AUTHORIZATION,
        format!("Bearer {}", env::var("GRAPHOPS_API_KEY")?).parse()?,
    );
    let http = reqwest::Client::builder()
        .default_headers(headers)
        .build()?;
    let provider = ProviderBuilder::new().connect_client(RpcClient::new(
        Http::with_client(http, "https://rpc.graphops.xyz/v1/evm/1".parse()?),
        false,
    ));

    let block_number = provider.get_block_number().await?;
    println!("{block_number}");
    Ok(())
}

```

Output

```json
26285610
```

Latest block in decimal: 26,285,610

Python · web3.py

Prerequisites

1. Install Python.

2. Install web3. `python -m pip install web3`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Python 3.12.12, web3 8.0.0.

[Example project](/examples/rpc.api.python-9.tar.gz)

```python
import os
from web3 import Web3

w3 = Web3(
    Web3.HTTPProvider(
        "https://rpc.graphops.xyz/v1/evm/1",
        request_kwargs={
            "headers": {
                "Authorization": f"Bearer {os.environ['GRAPHOPS_API_KEY']}",
            },
        },
    )
)

print(w3.eth.block_number)

```

Output

```json
26285600
```

Latest block in decimal: 26,285,600

## Batch requests

Batch requests are supported. Use them when several independent calls can share one HTTP round trip.
Do not use a batch when later calls depend on earlier results.

```json
[
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_blockNumber",
    "params": []
  },
  {
    "jsonrpc": "2.0",
    "id": 2,
    "method": "eth_chainId",
    "params": []
  },
  {
    "jsonrpc": "2.0",
    "id": 3,
    "method": "eth_getBalance",
    "params": ["0xnot-an-address", "latest"]
  }
]

```

Output

```json
[
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result": "0x191f63a"
  },
  {
    "jsonrpc": "2.0",
    "id": 2,
    "result": "0x1"
  },
  {
    "jsonrpc": "2.0",
    "id": 3,
    "error": {
      "code": -32602,
      "message": "Invalid params"
    }
  }
]
```

eth\_blockNumber in decimal: 26,342,970

Ethereum mainnet chain ID: 1

Only this call failed: invalid parameters

In the output, the third call fails because its address is invalid; the other two succeed.

Match responses by `id`; do not rely on response ordering. Retry only the failed items that are
retryable, as a smaller batch or as single requests.

## WebSocket connections

Use WebSocket endpoints for subscriptions and long-lived event streams. Route-token authentication
works with WebSocket clients that cannot attach custom headers during the handshake.

Prerequisites

1. Install Node.js.

2. Install tsx and ws. `npm install tsx ws`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Node.js 24.22.1, tsx 4.23.15, ws 8.22.0.

[Example project](/examples/rpc.api.ts-11.tar.gz)

```typescript
import WebSocket from "ws";

// Route-token URL: the API key is the final path segment.
const socket = new WebSocket(
  `wss://rpc.graphops.xyz/v1/evm/1/${process.env.GRAPHOPS_API_KEY}`,
);

socket.once("error", (error) => { throw error; });
socket.once("open", () => {
  console.log(JSON.stringify({ connected: true }));
  socket.close();
});

```

See [Authentication](./authentication) for header authentication, route-token authentication, and
security guidance.

## WebSocket subscriptions

GraphOps supports standard Ethereum subscription flows over WebSocket:

| Subscription             | Use it for                                                         |
| ------------------------ | ------------------------------------------------------------------ |
| `newHeads`               | Receive new block headers.                                         |
| `logs`                   | Receive logs matching an address and topic filter.                 |
| `newPendingTransactions` | Receive pending transaction hashes when available for the network. |
| `syncing`                | Receive node sync status updates.                                  |

Persist the last processed block or log cursor in your application. If a WebSocket disconnects, use
[WebSocket subscriptions](./guides/websocket-subscriptions) for recovery patterns.

## Error responses

JSON-RPC errors use the standard `error` object in place of `result`:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_getBalance",
  "params": [
    "invalid-address",
    "latest"
  ]
}

```

Output

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "odd number of digits"
  }
}
```

The call that failed

Present instead of result

Invalid params; see the table below

Points at the first parameter

Common error classes. GraphOps error responses carry a `code`; look it up in the
[gateway errors](/platform/errors/gateway) or [API key errors](/platform/errors/api-keys) reference.

| Code or status       | Meaning                                                                                                                                                                                                                                                                                          | Typical response                                                                                                                                                                  |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`                | Malformed HTTP request, invalid JSON, or a body that is not a JSON-RPC request object or batch. GraphOps rejects these before they reach a node, so they return HTTP `400` rather than JSON-RPC `-32700` or `-32600`. Over WebSocket, an invalid message closes the connection with code `1008`. | Fix request encoding and the JSON-RPC envelope.                                                                                                                                   |
| `401`                | Missing or invalid API key.                                                                                                                                                                                                                                                                      | Check header or route-token authentication.                                                                                                                                       |
| `403`                | The key is valid, but its limits do not include the network you called, the organization has no credits left, the key does not cover the route, or GraphOps support paused the organization or disabled the key.                                                                                 | Check the response `code`: allow the network in the key's limits, top up credits, check the endpoint, or contact support. See [Troubleshooting](./troubleshooting#403-forbidden). |
| `413`                | The request body is too large.                                                                                                                                                                                                                                                                   | Send a smaller request or split the batch.                                                                                                                                        |
| `415`                | The request uses an unsupported `Content-Encoding`.                                                                                                                                                                                                                                              | Send the body uncompressed or with gzip, deflate, br or zstd.                                                                                                                     |
| `429`                | Organization exceeded rate or concurrency limits.                                                                                                                                                                                                                                                | Back off and reduce concurrency.                                                                                                                                                  |
| `502`                | The node returned an invalid or oversized response, or the request to it failed.                                                                                                                                                                                                                 | Retry; for large results, request a smaller block range or fewer items.                                                                                                           |
| `503`                | The service is temporarily unavailable.                                                                                                                                                                                                                                                          | Retry with backoff.                                                                                                                                                               |
| `504`                | The node did not respond in time.                                                                                                                                                                                                                                                                | Retry, or reduce the work per request.                                                                                                                                            |
| `-32600`             | Invalid JSON-RPC request envelope reported by the node.                                                                                                                                                                                                                                          | Include `jsonrpc`, `method`, and valid `id` when needed.                                                                                                                          |
| `-32601`             | Method not found.                                                                                                                                                                                                                                                                                | Check method spelling, transport, and network support.                                                                                                                            |
| `-32602`             | Invalid params.                                                                                                                                                                                                                                                                                  | Check parameter order, hex encoding, and block tag.                                                                                                                               |
| `-32603`             | Internal JSON-RPC error.                                                                                                                                                                                                                                                                         | Retry if transient; contact support if persistent.                                                                                                                                |
| `-32000` to `-32099` | Server or EVM execution error.                                                                                                                                                                                                                                                                   | Inspect the message and method-specific context.                                                                                                                                  |

## Next steps

* [Supported methods](./methods): Check parameters, results, and transports for each EVM method.
* [Retries and reorgs](./guides/retries-and-reorgs): Decide which of these errors to retry and how.
* [Usage and limits](./usage-and-limits): Plan for rate, concurrency, batch, and response-size limits.