Quickstart

Get from zero to your first RPC call in under 5 minutes. No signup, no subscription, no KYC.

Prerequisites

1. Install

npm install @nodius/sdk

Also available via:

npx @nodius/sdk        # run without installing
deno add @nodius/sdk   # Deno
bun add @nodius/sdk    # Bun
pip install nodius

No install needed โ€” just use curl, fetch, or urllib.

2. Get a Keypair

Already have a Solana wallet? Use its secret key (base58). Otherwise:

import { Keypair } from "@solana/web3.js";
import bs58 from "bs58";

const kp = Keypair.generate();
const secretKeyBase58 = bs58.encode(kp.secretKey);
console.log("Pubkey:", kp.publicKey.toBase58());
console.log("Secret (base58):", secretKeyBase58);
// Save this base58 string โ€” you'll pass it as SECRET_KEY_BASE58
from nacl.signing import SigningKey
import base58

sk = SigningKey.generate()
pubkey = base58.b58encode(bytes(sk.verify_key)).decode()
secret = base58.b58encode(bytes(sk) + bytes(sk.verify_key)).decode()
print("Pubkey:", pubkey)
print("Secret (base58):", secret)

Store your secret key securely โ€” it's your identity and controls your credits. Both examples output a base58-encoded secret key.

3. Buy Credits

Send USDC (SPL token) on Solana mainnet to the deposit address from the wallet you just generated:

Field Value
Token USDC (SPL)
Chain Solana mainnet
USDC mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Deposit address CQKviPv5QupKhE6MuhSuqP4uh1JfrL93nxtcx23tLMRk
Minimum deposit $0.01 USDC (10,000 base units)

Credits appear within seconds of the deposit confirming on-chain (~30 seconds). The deposit address is static โ€” you can send USDC to it at any time.

โš ๏ธ Do not send SOL or any token other than USDC. Only SPL USDC transfers to the deposit address are credited. Sending other tokens will result in permanent loss of funds.

Canonical source: The deposit address above is for convenience. Always obtain and verify it programmatically via GET /account/info (returns deposit_address and funding fields) or the 402 Payment Required response data.deposit_address. Bots should fetch it at runtime โ€” do not hardcode it in application logic.

4. Make Your First Call

Billable RPC calls require a positive credit balance โ€” if you skipped step 3, you'll get 402 Payment Required. Both SDKs' call() method returns the JSON-RPC result field directly (unwrapped from the response envelope). For example, getBalance returns {"value": 12345, ...} โ€” not the full {"jsonrpc":"2.0","result":{...}} envelope.

import { NodiusClient } from "@nodius/sdk";

const rpc = NodiusClient.fromSecretKey(
  "https://rpc.nodius.xyz",
  process.env.SECRET_KEY_BASE58!
);

const slot = await rpc.call("getSlot");
console.log("Slot:", slot);

const bal = await rpc.call("getBalance", [
  "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg",
]);
console.log("Balance:", bal.value, "lamports");
from nodius import NodiusClient

rpc = NodiusClient.from_base58(
    "https://rpc.nodius.xyz",
    secret_key="your_base58_secret_key",
)

slot = rpc.call("getSlot")
print("Slot:", slot)

bal = rpc.call("getBalance", ["vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg"])
print("Balance:", bal["value"], "lamports")
import time, hashlib, json, urllib.request, base58, os
from nacl.signing import SigningKey

SK = base58.b58decode("your_base58_secret_key")
key = SigningKey(SK[:32]) if len(SK) == 64 else SigningKey(SK)
pub = SK[32:] if len(SK) == 64 else bytes(key.verify_key)

body = json.dumps({"jsonrpc":"2.0","id":1,"method":"getSlot"}).encode()
ts = str(int(time.time()))
nonce = os.urandom(16).hex()
h = hashlib.sha256(body).hexdigest()
msg = f"solana-nodius:v2:POST:/:{ts}:{nonce}:{h}"
sig = key.sign(msg.encode()).signature

req = urllib.request.Request("https://rpc.nodius.xyz", data=body, headers={
    "Content-Type":"application/json",
    "X-Pubkey": base58.b58encode(pub).decode(),
    "X-Signature": base58.b58encode(sig).decode(),
    "X-Timestamp": ts, "X-Nonce": nonce,
})
with urllib.request.urlopen(req) as r:
    print("Credits:", r.headers.get("X-Credits-Remaining"))
    print("Slot:", json.loads(r.read())["result"])
const crypto = require("crypto");
const nacl = require("tweetnacl");
const bs58 = require("bs58");

const SK = bs58.decode("your_base58_secret_key");
const kp = SK.length === 32 ? nacl.sign.keyPair.fromSeed(SK) : {
  secretKey: SK, publicKey: SK.slice(32)
};

const body = JSON.stringify({jsonrpc:"2.0",id:1,method:"getSlot"});
const ts = Math.floor(Date.now()/1000).toString();
const nonce = crypto.randomBytes(16).toString("hex");
const h = crypto.createHash("sha256").update(body).digest("hex");
const msg = `solana-nodius:v2:POST:/:${ts}:${nonce}:${h}`;
const sig = nacl.sign.detached(new TextEncoder().encode(msg), kp.secretKey);

const res = await fetch("https://rpc.nodius.xyz", {
  method:"POST", body,
  headers:{
    "Content-Type":"application/json",
    "X-Pubkey": bs58.encode(kp.publicKey),
    "X-Signature": bs58.encode(sig),
    "X-Timestamp": ts, "X-Nonce": nonce,
  },
});
console.log("Credits:", res.headers.get("X-Credits-Remaining"));
console.log("Slot:", (await res.json()).result);
# curl uses API key auth. Get one first:
# POST /account/api-key with wallet sig, then:
curl -X POST https://rpc.nodius.xyz \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: srpc_live_..." \
  -d '{"jsonrpc":"2.0","id":1,"method":"getSlot"}'

5. Generate an API Key

API keys avoid per-request signing and give you the lowest latency. They also enable drop-in compatibility with standard Solana libraries:

const result = await rpc.generateApiKey();
console.log("API key:", result.api_key);
// The SDK auto-stores the API key for subsequent calls
result = rpc.generate_api_key()
print("API key:", result["api_key"])
# The SDK auto-stores the API key for subsequent calls

Once you have an API key, you can use it in any standard Solana library by embedding it in the URL:

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

// Drop-in: paste one URL, every standard method works
const conn = new Connection("https://rpc.nodius.xyz/?api-key=srpc_live_...");
const slot = await conn.getSlot();
from solana.rpc.api import Client

# Drop-in: paste one URL, every standard method works
client = Client("https://rpc.nodius.xyz/?api-key=srpc_live_...")
slot = client.get_slot()
curl -X POST "https://rpc.nodius.xyz/?api-key=srpc_live_..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"getSlot"}'

Or pass it as a header โ€” both work:

curl -X POST https://rpc.nodius.xyz \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: srpc_live_..." \
  -d '{"jsonrpc":"2.0","id":1,"method":"getSlot"}'

6. Check Your Balance

Every response includes an X-Credits-Remaining header. Or check programmatically:

const info = await rpc.getBillingAccount();
console.log("Balance:", info.balance);
console.log("Deposit address:", info.deposit_address);
info = rpc.get_billing_account()
print("Balance:", info["balance"])
print("Deposit address:", info.get("deposit_address"))
import json, urllib.request
req = urllib.request.Request(
    "https://rpc.nodius.xyz/account/info",
    headers={"X-Api-Key": "srpc_live_..."},
)
with urllib.request.urlopen(req) as r:
    info = json.loads(r.read())
    print("Balance:", info["balance"])
const res = await fetch("https://rpc.nodius.xyz/account/info", {
  headers: { "X-Api-Key": "srpc_live_..." },
});
const info = await res.json();
console.log("Balance:", info.balance);
curl https://rpc.nodius.xyz/account/info \
  -H "X-Api-Key: srpc_live_..."

Connection Hygiene

For latency-sensitive workloads, hold persistent HTTP connections. A cold TLS handshake adds 2-5s to the first request; reusing a warm connection eliminates that entirely.

Next Steps