Logo
New RPC users get 35% off their first monthView the offer
RPC Assistant

Solana RPC API Documentation: Endpoints, Methods, and Debug Path

Summary

Solana's RPC API is the JSON-RPC interface your app uses to read accounts, submit transactions, and subscribe to on-chain events. This reference walks through the endpoint shape, the method groups you will actually call, and how to debug the errors that show up in production.

It also covers when a public endpoint is enough and when a dedicated Solana node from OnFinality makes more sense for consistent throughput, WebSocket subscriptions, and heavier read workloads.

Solana does not expose a REST API for chain data. Everything your app reads or writes goes through a single JSON-RPC endpoint, which means the endpoint you pick and the methods you call shape your latency, your error rate, and your bill. This page is a working reference for that interface: how requests are shaped, which methods matter, how subscriptions behave, and how to debug the failures you will hit once real traffic arrives.

Which Solana endpoint should you connect to?

Start by matching the endpoint to the job. A quick script, a hackathon demo, or a read-only dashboard can usually run against a public endpoint. A wallet, a trading bot, an indexer, or anything that fans out many concurrent reads will feel the difference between shared and dedicated capacity almost immediately.

Your situationSensible starting pointWhy
Prototyping, one-off scripts, learning the APIPublic Solana endpointNo setup, fine for low request volume
Testing program logic before mainnetSolana Devnet RPCFree SOL from a faucet, safe to break things
Wallet or dApp with steady user trafficManaged Solana RPCPredictable capacity without running a validator
Indexer, bot, or high read fan-outDedicated Solana nodeIsolated throughput and your own WebSocket capacity
Need historical account or transaction stateArchive-capable nodeStandard nodes prune older ledger data

OnFinality runs Solana mainnet RPC over both HTTP and WebSocket, so you can point a single provider at both your request/response calls and your subscription calls. If you are still weighing providers, the RPC provider selection guide covers the evaluation criteria in more depth.

Endpoint shape and a first request

A Solana RPC endpoint is a single URL that accepts HTTP POST requests with a JSON body. There is no path per method; the method name lives in the body. The public OnFinality Solana endpoint is:

https://solana.api.onfinality.io/public

A minimal call to fetch the current slot looks like this:

curl https://solana.api.onfinality.io/public \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getSlot",
    "params": []
  }'

The response follows the JSON-RPC 2.0 envelope: a jsonrpc field, an id that echoes your request, and either a result or an error object. Every Solana method uses that same envelope, so once your client handles it correctly you can call any method without changing transport code.

Method groups you will actually call

Solana's method list is long, but production apps cluster around a handful of groups. Knowing which group a method belongs to tells you how expensive it is and how it fails.

GroupRepresentative methodsTypical useCost profile
Account readsgetAccountInfo, getMultipleAccounts, getProgramAccountsBalances, token accounts, program stateCheap per call, but getProgramAccounts can be heavy
Block and slot datagetSlot, getBlock, getBlockHeight, getLatestBlockhashConfirmations, transaction buildingModerate; getBlock returns large payloads
Transaction submissionsendTransaction, simulateTransactionSending signed transactionsSensitive to load; simulate first
Token and SPL helpersgetTokenAccountsByOwner, getTokenAccountBalanceWallet balances and token listsModerate fan-out per user
Fees and prioritygetRecentPrioritizationFees, getFeeForMessageSetting compute unit priceCheap, but call it fresh
Subscriptions (WebSocket)accountSubscribe, logsSubscribe, slotSubscribeLive updates without pollingLong-lived connections

Two practical notes. First, getProgramAccounts is the method most likely to time out on a shared endpoint, because it can scan a large account set; scope it with filters and a dataSlice whenever possible. Second, getLatestBlockhash results expire, so fetch a fresh blockhash close to the moment you sign rather than caching one for minutes.

Building a transaction with the JSON-RPC API

Most teams use @solana/web3.js or a similar client rather than hand-rolling JSON. The client still speaks the same RPC methods under the hood, so pointing it at your endpoint is a one-line change:

import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";

const connection = new Connection(
  "https://solana.api.onfinality.io/public",
  { commitment: "confirmed" }
);

const balance = await connection.getBalance(
  new PublicKey("11111111111111111111111111111111")
);

console.log("lamports:", balance, "SOL:", balance / LAMPORTS_PER_SOL);

The commitment level you pass matters. processed is fastest but can be rolled back; confirmed is the usual default for user-facing balances; finalized is the safest for settlement logic. Pick one deliberately and keep it consistent across your reads, because mixing commitment levels is a common source of confusing UI state.

WebSocket subscriptions and when to use them

Polling getSlot or getAccountInfo in a loop burns requests and still feels laggy. Solana's WebSocket interface pushes updates instead. The public OnFinality WebSocket endpoint is:

wss://solana.api.onfinality.io/public-ws

A subscription request uses the same JSON-RPC envelope, sent over the socket:

const ws = new WebSocket("wss://solana.api.onfinality.io/public-ws");

ws.onopen = () => {
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "logsSubscribe",
    params: [
      { mentions: ["YourProgramPublicKeyHere"] },
      { commitment: "confirmed" }
    ]
  }));
};

ws.onmessage = (event) => {
  const payload = JSON.parse(event.data);
  if (payload.method === "logsNotification") {
    console.log("program log:", payload.params.result.value.logs);
  }
};

Subscriptions are long-lived, so plan for reconnection. Shared endpoints may close idle or overloaded sockets, and a dropped socket that your app does not notice looks exactly like a stalled chain. Add a heartbeat, reconnect with backoff, and re-subscribe on reconnect. If your workload depends on many concurrent subscriptions, that is a strong signal to move to a dedicated node where the connection budget is yours.

Debug path for common Solana RPC errors

When something breaks, the error text usually points at the layer. Use this table to route the fix.

SymptomLikely causeNext step
429 or rate-limit responseShared endpoint under loadBack off, batch reads, or move to dedicated capacity
Blockhash not foundStale or expired blockhashFetch a fresh blockhash immediately before signing
Transaction confirms then disappearsCommitment level mismatchAlign reads and confirmation logic on confirmed or finalized
getProgramAccounts times outUnfiltered account scanAdd filters and dataSlice, or use a dedicated node
WebSocket stops updatingSocket closed silentlyAdd heartbeat, reconnect, and re-subscribe
-32002 transaction simulation failureProgram logic rejected the txRun simulateTransaction and read the logs before resending

A useful habit is to log the raw JSON-RPC error object, not just a friendly message. Solana returns structured error data, including logs for simulation failures, and that detail is usually enough to identify the failing instruction.

Production readiness checklist

Before you point real users at an endpoint, confirm these items:

  • Commitment levels are explicit across every read and confirmation path.
  • Retries use backoff, not tight loops, so a slow moment does not become a self-inflicted spike.
  • Blockhash freshness is handled at signing time, not cached.
  • WebSocket reconnection is implemented and tested by killing the socket on purpose.
  • Heavy reads are scoped with filters, dataSlice, and batching where the API allows it.
  • A fallback endpoint is configured so a single provider issue does not take the app down.
  • Request volume is measured so you can tell whether shared capacity still fits.

If several of these are hard to satisfy on a shared endpoint, that is the point to look at dedicated nodes or review RPC pricing to compare options.

Devnet, mainnet, and moving between them

Devnet mirrors the mainnet API surface, so code that works against mainnet generally works against Solana Devnet RPC with a different URL and a faucet-funded keypair. Keep the endpoint in configuration rather than hard-coded, and keep a separate keypair per environment. The most common migration bug is a program ID or token mint that was updated in one environment but not the other.

OnFinality exposes Solana mainnet and devnet as separate network entries, so you can register both and switch by config. See the Solana network page for the current endpoint details and transport support, and supported RPC networks for the full list.

Key Takeaways

  • Solana exposes one JSON-RPC interface for reads, writes, and subscriptions; the method name lives in the request body, not the URL.
  • Match the endpoint to the workload: public for prototypes, managed for steady traffic, dedicated for high fan-out or subscription-heavy apps.
  • getProgramAccounts and long-lived WebSockets are the two areas most likely to push you off a shared endpoint.
  • Most production bugs trace back to commitment levels, stale blockhashes, or unnoticed socket drops, not to the API itself.
  • OnFinality serves Solana RPC over HTTP and WebSocket, with dedicated node options when shared capacity is not enough.

Frequently Asked Questions

Is the Solana RPC API the same as the Solana JSON-RPC API?

Yes. When people say "Solana RPC API" they mean the JSON-RPC 2.0 interface served over HTTP and WebSocket. There is no separate REST API for chain data.

Do I need an API key to call a Solana RPC endpoint?

Public endpoints typically work without a key, which is fine for low-volume use. Managed and dedicated endpoints use keys or private URLs so your traffic is isolated and measurable.

Why does my transaction fail with "Blockhash not found"?

The blockhash you signed against expired before the transaction landed. Fetch a fresh blockhash right before signing and retry with backoff.

Should I poll or use WebSocket subscriptions?

Use subscriptions for anything that needs to react to on-chain events, and reserve polling for occasional checks. Subscriptions reduce request volume and usually feel faster, but they require reconnection handling.

When should I move from a public endpoint to a dedicated node?

When you see rate limiting, when getProgramAccounts or similar heavy reads time out, when you need many concurrent WebSocket subscriptions, or when you need historical state that standard nodes prune. A dedicated node gives you isolated capacity for those cases.

RPC Knowledge Base

Related RPC details

Never Worry about Infrastructure Again

OnFinality takes away the heavy lifting of DevOps so you can build smarter and faster.

Get Started