JSON-RPC connection guide
Subglow's JSON-RPC endpoint is a drop-in replacement for any standard Solana mainnet-beta RPC URL. Your existing client code works unchanged — only the URL moves.
Endpoint
https://rpc.subglow.io/<YOUR_API_KEY>
Alternative (header auth)
https://rpc.subglow.io· Authorization: Bearer <YOUR_API_KEY>
Your quotas
Every paid plan bundles JSON-RPC on the same API key as gRPC. sendTransaction has its own bucket.
Sniper · $99/mo
50,000 RPC/day · 2,000 sendTransaction/day
Pro · $249/mo
500,000 RPC/day · 20,000 sendTransaction/day
TypeScript / @solana/web3.js
import { Connection, PublicKey } from "@solana/web3.js";
const conn = new Connection(
`https://rpc.subglow.io/${process.env.SUBGLOW_API_KEY}`,
"confirmed",
);
// Reads
const slot = await conn.getSlot();
const { blockhash } = await conn.getLatestBlockhash();
const account = await conn.getAccountInfo(
new PublicKey("So11111111111111111111111111111111111111112"),
);
// Writes — sendTransaction lives in a dedicated daily bucket
const sig = await conn.sendRawTransaction(signedTx.serialize(), {
skipPreflight: false,
maxRetries: 3,
});Python / solders
import os, httpx
from solders.rpc.requests import GetSlot, GetLatestBlockhash, GetAccountInfo
from solders.pubkey import Pubkey
URL = f"https://rpc.subglow.io/{os.environ['SUBGLOW_API_KEY']}"
with httpx.Client(base_url=URL, timeout=10.0) as c:
slot = c.post("/", content=GetSlot().to_json()).json()["result"]
blockhash = c.post("/", content=GetLatestBlockhash().to_json()).json()["result"]
info = c.post(
"/",
content=GetAccountInfo(
Pubkey.from_string("So11111111111111111111111111111111111111112")
).to_json(),
).json()["result"]Rust / solana-client
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_sdk::{commitment_config::CommitmentConfig, pubkey::Pubkey};
use std::env;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let url = format!(
"https://rpc.subglow.io/{}",
env::var("SUBGLOW_API_KEY")?,
);
let client = RpcClient::new_with_commitment(url, CommitmentConfig::confirmed());
let slot = client.get_slot().await?;
let hash = client.get_latest_blockhash().await?;
let wsol: Pubkey = "So11111111111111111111111111111111111111112".parse()?;
let info = client.get_account(&wsol).await?;
println!("slot = {slot}, blockhash = {hash}, lamports = {}", info.lamports);
Ok(())
}Go / solana-go
package main
import (
"context"
"fmt"
"os"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
)
func main() {
url := fmt.Sprintf("https://rpc.subglow.io/%s", os.Getenv("SUBGLOW_API_KEY"))
client := rpc.New(url)
slot, _ := client.GetSlot(context.Background(), rpc.CommitmentConfirmed)
bh, _ := client.GetLatestBlockhash(context.Background(), rpc.CommitmentConfirmed)
wsol := solana.MustPublicKeyFromBase58("So11111111111111111111111111111111111111112")
info, _ := client.GetAccountInfo(context.Background(), wsol)
fmt.Println(slot, bh.Value.Blockhash, info.Value.Lamports)
}Method policy
Allowed on all paid plans
- getAccountInfo · getBalance
- getTokenAccountsByOwner
- getLatestBlockhash · getSlot
- getTransaction (recent slots)
- getSignatureStatuses
- simulateTransaction
- sendTransaction · sendRawTransaction (separate bucket)
Dedicated tier only
- getProgramAccounts (unfiltered)
- getSignaturesForAddress (historical)
- getBlock / getBlocks (historical)
Rejected with -32001 archival-disabled on shared plans.
Error codes you should handle
-32001 archival-disabled— archival method attempted on a shared tier. Upgrade to Dedicated or refactor your query.429 rate_limited— your daily RPC or sendTransaction bucket is exhausted. Counters reset at midnight UTC.401 invalid_api_key— key missing, banned, or plan expired. Check your dashboard at /dashboard/usage.5xx upstream_error— rare; retry with jittered backoff. We surface upstream Helius errors verbatim.
Also need streaming?
Same API key opens Yellowstone gRPC at grpc.subglow.io:443. Server-side filters, pre-parsed JSON, 30–80ms p50.