Everything you need to send your first request.

Authentication, request format, limits and error codes for the Iteradian gateway, with copy-paste examples in cURL, JavaScript, Python, Go, Rust, C#, Java and PHP, and setup for ethers, viem, web3.py and @solana/web3.js.

01

What Iteradian is

Iteradian is a multi-chain RPC gateway. You create an API key, send standard JSON-RPC 2.0 requests over HTTPS, and the gateway forwards each one to a healthy node for the network you named, failing over to another node when one does not answer. Keys, usage, request logs, alerts, your team and billing are managed in the dashboard or through the management API.

HostWhat it is
https://api.iteradian.comRPC gateway. Send your JSON-RPC requests here.
https://api.iteradian.com/api/v1Management API: accounts, organizations, API keys, usage, billing.
https://app.iteradian.comDashboard: sign up, sign in and manage everything.
02

Send your first request

  1. 1. Create an account

    Sign up with an email and password, or with Google or GitHub. Every account gets a personal organization, which starts on a 7-day trial of Developer RPC.

    Create an account →

  2. 2. Create an API key

    In the dashboard, open Organization → API Keys and create a key. The full key is shown once, so put it straight into a secret manager or an environment variable. The examples on this page read it from ITERADIAN_API_KEY.

  3. 3. Call the gateway

    POST a JSON-RPC 2.0 body to the network’s URL with the key in the X-Api-Key header.

    cURL
    curl -sS https://api.iteradian.com/rpc/v1/eth-mainnet \
      -H "Content-Type: application/json" \
      -H "X-Api-Key: $ITERADIAN_API_KEY" \
      -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
    # {"jsonrpc":"2.0","id":1,"result":"0x1502f8a"}
  4. 4. Read the response

    The body is the node’s JSON-RPC 2.0 response, passed through unchanged. For eth_blockNumber the result is the latest block number as a hex string. A 4xx or 5xx status means the gateway stopped the call — see Errors and retries.

03

Headers, body and batching

Every call is POST https://api.iteradian.com/rpc/v1/{network} with a standard JSON-RPC 2.0 body. {network} is a slug from the networks table — the path is always /rpc/v1/ followed by the slug.

ItemValue
AuthenticationX-Api-Key: <key> or Authorization: Bearer <key>
Content typeContent-Type: application/json
Request body limit1 MB
Upstream timeout30 seconds
TransportHTTPS, plus WebSocket at wss://rpc.iteradian.com/ws/v1/{network}.

X-Api-Key is the preferred header and wins when both are sent. Authorization: Bearer <key> takes the same API key — never a dashboard login token.

Bearer form — equivalent
curl -sS https://api.iteradian.com/rpc/v1/eth-mainnet \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ITERADIAN_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'

Batching

Send a JSON array of requests. Responses can come back in any order, so match them by id. A batch of N calls counts as N requests against the rate limit and the monthly quota: batching saves round trips, not allowance.

Batch request
curl -sS https://api.iteradian.com/rpc/v1/eth-mainnet \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: $ITERADIAN_API_KEY" \
  -d '[{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]},
       {"jsonrpc":"2.0","id":2,"method":"eth_chainId","params":[]}]'
# [{"jsonrpc":"2.0","id":2,"result":"0x1"},{"jsonrpc":"2.0","id":1,"result":"0x1502f8a"}]
# Responses can arrive in any order: match them by id. This batch counts as 2 requests.

Which methods work

Any JSON-RPC method is forwarded to the node; there is no method blocklist. Whether trace_*, debug_* or archive queries work depends on the node that serves the request, so test them before you depend on them.

Transaction submissions (eth_sendRawTransaction, eth_sendTransaction, sendTransaction, author_submitExtrinsic) go to one node and are never retried or replayed by the gateway. Every other call fails over across up to 3 nodes automatically.

Which networks are up

GET https://api.iteradian.com/rpc/v1/networks lists the networks available right now — only those with a healthy node. It needs no API key.

List available networks
# No API key needed. Lists networks with a healthy node right now.
curl -sS https://api.iteradian.com/rpc/v1/networks

Examples by language

The same eth_blockNumber call in each language, using only the standard HTTP client where one exists.

JavaScript (fetch)
// Node.js 18+ (built-in fetch)
const res = await fetch("https://api.iteradian.com/rpc/v1/eth-mainnet", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Api-Key": process.env.ITERADIAN_API_KEY,
  },
  body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] }),
});
const body = await res.json();
if (!res.ok) throw new Error(`HTTP ${res.status}: ${JSON.stringify(body)}`);
if (body.error) throw new Error(`RPC error ${body.error.code}: ${body.error.message}`);
console.log(BigInt(body.result));
Python (requests)
import os
import requests

res = requests.post(
    "https://api.iteradian.com/rpc/v1/eth-mainnet",
    headers={"X-Api-Key": os.environ["ITERADIAN_API_KEY"]},
    json={"jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber", "params": []},
    timeout=35,
)
res.raise_for_status()
body = res.json()
if "error" in body:
    raise RuntimeError(body["error"])
print(int(body["result"], 16))
Go (net/http)
package main

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

func main() {
	body := []byte(`{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}`)
	req, err := http.NewRequest("POST", "https://api.iteradian.com/rpc/v1/eth-mainnet", bytes.NewReader(body))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Api-Key", os.Getenv("ITERADIAN_API_KEY"))

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.StatusCode, string(out))
}
Rust (reqwest)
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] },
//             serde_json = "1", tokio = { version = "1", features = ["full"] }
use serde_json::{json, Value};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = std::env::var("ITERADIAN_API_KEY")?;
    let body: Value = reqwest::Client::new()
        .post("https://api.iteradian.com/rpc/v1/eth-mainnet")
        .header("X-Api-Key", key)
        .json(&json!({ "jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber", "params": [] }))
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;
    println!("{}", body["result"]);
    Ok(())
}
C# (HttpClient)
using System.Net.Http;
using System.Text;

using var http = new HttpClient();
using var req = new HttpRequestMessage(HttpMethod.Post, "https://api.iteradian.com/rpc/v1/eth-mainnet");
req.Headers.Add("X-Api-Key", Environment.GetEnvironmentVariable("ITERADIAN_API_KEY"));
req.Content = new StringContent(
    "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_blockNumber\",\"params\":[]}",
    Encoding.UTF8,
    "application/json");

using var res = await http.SendAsync(req);
Console.WriteLine($"{(int)res.StatusCode} {await res.Content.ReadAsStringAsync()}");
Java (java.net.http)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class BlockNumber {
    public static void main(String[] args) throws Exception {
        HttpRequest req = HttpRequest.newBuilder(URI.create("https://api.iteradian.com/rpc/v1/eth-mainnet"))
            .header("Content-Type", "application/json")
            .header("X-Api-Key", System.getenv("ITERADIAN_API_KEY"))
            .POST(HttpRequest.BodyPublishers.ofString(
                "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_blockNumber\",\"params\":[]}"))
            .build();
        HttpResponse<String> res = HttpClient.newHttpClient()
            .send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println(res.statusCode() + " " + res.body());
    }
}
PHP (curl)
<?php
$ch = curl_init("https://api.iteradian.com/rpc/v1/eth-mainnet");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "X-Api-Key: " . getenv("ITERADIAN_API_KEY"),
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "jsonrpc" => "2.0", "id" => 1, "method" => "eth_blockNumber", "params" => [],
    ]),
]);
$body = json_decode(curl_exec($ch), true);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), " ", $body["result"] ?? json_encode($body), PHP_EOL;

Using existing Web3 libraries

Libraries that speak JSON-RPC over HTTP work unchanged: give them the network URL and add the X-Api-Key header.

ethers v6
// ethers v6
import { ethers } from "ethers";

const req = new ethers.FetchRequest("https://api.iteradian.com/rpc/v1/eth-mainnet");
req.setHeader("X-Api-Key", process.env.ITERADIAN_API_KEY);
const provider = new ethers.JsonRpcProvider(req);
console.log(await provider.getBlockNumber());
viem
// viem
import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";

const client = createPublicClient({
  chain: mainnet,
  transport: http("https://api.iteradian.com/rpc/v1/eth-mainnet", {
    fetchOptions: { headers: { "X-Api-Key": process.env.ITERADIAN_API_KEY } },
  }),
});
console.log(await client.getBlockNumber());
@solana/web3.js
// @solana/web3.js
import { Connection } from "@solana/web3.js";

const connection = new Connection("https://api.iteradian.com/rpc/v1/sol-mainnet", {
  httpHeaders: { "X-Api-Key": process.env.ITERADIAN_API_KEY },
});
console.log(await connection.getSlot());
web3.py
# web3.py
import os
from web3 import Web3

w3 = Web3(Web3.HTTPProvider(
    "https://api.iteradian.com/rpc/v1/eth-mainnet",
    request_kwargs={"headers": {"X-Api-Key": os.environ["ITERADIAN_API_KEY"]}},
))
print(w3.eth.block_number)
04

Networks and slugs

The slug is the last part of the URL. Slugs are case-insensitive, and an underscore or a space is read as a hyphen. Each network accepts several slugs: examples use the dashboard slug, which is what the app shows, and the aliases work the same way. An unknown slug returns HTTP 400.

This table is the catalogue. A network is served only while it has a healthy node, so check GET https://api.iteradian.com/rpc/v1/networks for what is available right now rather than assuming every row is up.

Network catalogue with accepted slugs
NetworkDashboard slugAlso acceptedChain ID
Ethereum Mainneteth-mainnetethereum-mainnet1
Ethereum Sepoliaeth-testneteth-sepolia, ethereum-sepolia11155111
Polygon Mainnetpolygon-mainnetmatic-mainnet137
Polygon Amoypolygon-testnetpolygon-amoy, polygon-mumbai80002
Arbitrum Onearbitrum-mainnetarb-mainnet42161
OP Mainnetoptimism-mainnetop-mainnet10
Basebase-mainnet—8453
Avalanche C-Chainavalanche-mainnetavax-mainnet43114
BNB Smart Chainbsc-mainnetbnb-mainnet56
Fantom Operafantom-mainnetftm-mainnet250
Solana Mainnet Betasol-mainnetsolana-mainnet—
Solana Devnetsol-devnetsolana-devnet—
Bittensor (Finney)tao-mainnetbittensor-mainnet—
Bittensor Testnettao-testnetbittensor-testnet—
NEAR Mainnetnear-mainnet——
Cosmos Hubcosmos-mainnetatom-mainnet—
Lightchain AI Mainnetlcai-mainnetlightchain-mainnet—
Lightchain AI Testnetlcai-testnetlightchain-testnet—

The live listing could not be read when this page was generated, so this table says nothing about current availability.

05

Limits, quotas and overage

  • Limits belong to your organization’s subscription and are shared by all of its API keys. Creating more keys does not add capacity.
  • The per-second rate limit is a sliding one-second window. Concurrency is the number of your requests in flight at once.
  • The monthly quota runs over your subscription’s billing period, not the calendar month.
  • A batch of N calls counts as N requests.
  • A key can carry its own rate limit of 1–10,000 requests per second. It can only lower the organization’s limit for that key, never raise it.

On plans with overage enabled, requests past the included allowance keep being served and are billed per 1,000 requests, up to the plan’s overage cap for the period. After the cap, requests get -32007. Owners and admins get an email when overage starts and when the cap is reached.

Plan limits enforced by the gateway
PlanRequests / secondConcurrentIncluded / periodOverage
Free RPC25103,000,000—
Developer RPC25010025,000,000Overage $0.005 per 1,000 requests, capped at $150 per billing period
Professional RPC50050080,000,000Overage $0.003 per 1,000 requests, capped at $350 per billing period
Dedicated RPCCustomCustomUnlimitedNone — unlimited requests

Prices and limits read from the control plane on 27 October 2026. Plans priced per contract have their limits set in the contract. Compare plans

06

Errors and retries

Limit errors are HTTP 429 with a JSON-RPC envelope ({"jsonrpc":"2.0","id":null,"error":{"code":…,"message":…,"data":{…}}}). 400 and 403 are not JSON-RPC envelopes: their body is {"statusCode":…,"message":…,"error":…}. A 200 can still carry the node’s own JSON-RPC error — that is the chain rejecting the call.

Gateway status codes and JSON-RPC error codes
HTTPCodeMeaningRetry?
200node’s ownThe chain rejected the call (revert, bad params). The node's own JSON-RPC error is passed through unchanged.No — fix the call.
400—Missing API key, a body that is not JSON-RPC, or an unknown network slug.No.
403—Invalid, revoked or expired key; IP not on the key's allowlist; network not allowed for this key; organization suspended; no active subscription, or the subscription is past due, canceled or unpaid.No.
429-32005Over the per-second rate limit (data.retryAfter seconds, data.allowed, data.cost) or over the concurrency limit (data.inFlight).Yes, after data.retryAfter seconds.
429-32006Monthly request quota used up. data.resetsAt is when it resets.No — not until resetsAt, or upgrade.
429-32007Overage spend cap reached (data.overageCapUsd).No — raise the cap or change plan.
503-32603Every node tried for the network failed.Yes, with backoff.
503—No nodes are available for the network at all.Yes, later.
A 429 response
HTTP/1.1 429 Too Many Requests

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32005,
    "message": "…",
    "data": { "retryAfter": 1, "allowed": 20, "cost": 1 }
  }
}
A 403 response
HTTP/1.1 403 Forbidden

{ "statusCode": 403, "message": "…", "error": "Forbidden" }

Retrying safely

Retry -32005 after error.data.retryAfter seconds, and 503 with backoff. Never retry -32006 or -32007: they cannot succeed until the quota resets, the cap is raised or the plan changes.

Be careful re-sending a transaction submission: the gateway never replays one, and a failed-looking attempt may still have reached the network. Check for the transaction by hash before sending it again.

Retry loop (JavaScript)
// Retry only what can succeed on a second attempt.
const RPC_URL = "https://api.iteradian.com/rpc/v1/eth-mainnet";

async function rpc(payload, attempts = 4) {
  for (let attempt = 1; ; attempt++) {
    const res = await fetch(RPC_URL, {
      method: "POST",
      headers: { "Content-Type": "application/json", "X-Api-Key": process.env.ITERADIAN_API_KEY },
      body: JSON.stringify(payload),
    });
    const body = await res.json().catch(() => null);
    if (res.ok) return body; // may still carry the node's own error: fix the call, do not retry

    const code = body?.error?.code;
    const retryable =
      (res.status === 429 && code === -32005) || // rate or concurrency limit
      res.status === 503;                        // nodes failed or unavailable
    // -32006 (monthly quota) and -32007 (overage cap) can never succeed on retry.
    if (!retryable || attempt >= attempts) {
      throw new Error(`HTTP ${res.status} ${code ?? ""} ${JSON.stringify(body)}`);
    }
    const waitSeconds = body?.error?.data?.retryAfter ?? Math.min(2 ** attempt, 30);
    await new Promise((r) => setTimeout(r, waitSeconds * 1000));
  }
}

console.log(await rpc({ jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] }));
07

Creating and managing API keys

Create keys in the dashboard (Organization → API Keys) or with the management API. Owners and admins can create, edit, rotate and revoke keys; developers and viewers can see them. Creating a key needs an active or trialing subscription.

A key is itrd_live_ or itrd_test_ followed by 64 hex characters. The full key is shown once — when it is created and when it is rotated. After that only a prefix is visible.

API key options
OptionWhat it does
NameRequired.
Environmentlive or test. A label for organizing keys — it does not limit which networks the key can call.
IP allowlistUp to 50 IP addresses or CIDR ranges. Requests from anywhere else get 403.
Allowed networksRestricts the key to the networks you pick. Empty means every network.
Rate limit1–10,000 requests per second. Only ever lowers the organization’s limit for this key.
ExpiryOptional. An expired key gets 403. The dashboard offers never, or 30 / 90 / 180 / 365 days.

Revoking a key is permanent: a revoked key cannot be edited or rotated.

Each key has its own analytics over the last 1d / 7d / 30d / 90d.

Keeping keys safe

  • Keep keys on servers. Never ship one in a browser bundle or a mobile app, where anyone can read it out.
  • Set an IP allowlist on keys used from servers with fixed addresses.
  • Restrict each key to the networks it actually needs.
  • Use one key per service, so usage stays separate and one key can be revoked without touching the others.
  • Give keys for short-lived jobs an expiry.
08

Official SDKs

The SDKs cover the management API and RPC calls. Each takes two base URLs — the management API (https://api.iteradian.com/api/v1) and the gateway (https://api.iteradian.com) — and defaults to both. RPC calls go through an rpc group: call, batch and networks.

They retry -32005 and 5xx errors, honouring retryAfter, never retry -32006 or -32007, and never retry transaction submissions.

Published SDK packages
LanguagePackageInstall
TypeScript / JavaScriptnpm · @iteradian-rpc/sdknpm install @iteradian-rpc/sdk
PythonPyPI · iteradianpip install iteradian
C# / .NETNuGet · Iteradiandotnet add package Iteradian

First call

TypeScript / JavaScript
import { IteradianClient } from "@iteradian-rpc/sdk";

const client = new IteradianClient({ apiKey: process.env.ITERADIAN_API_KEY });

const res = await client.rpc.call("eth-mainnet", {
  jsonrpc: "2.0",
  id: 1,
  method: "eth_blockNumber",
  params: [],
});
console.log(res.result);
Python
import os
from iteradian import IteradianClient

# Synchronous client (built on httpx).
client = IteradianClient(api_key=os.environ["ITERADIAN_API_KEY"])

res = client.rpc.call("eth-mainnet", {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_blockNumber",
    "params": [],
})
print(res["result"])
C# / .NET
using Iteradian;

// .NET 6 and 8.
var client = new IteradianClient(
    "https://api.iteradian.com/api/v1",
    "https://api.iteradian.com");
client.SetApiKey(Environment.GetEnvironmentVariable("ITERADIAN_API_KEY"));

var res = await client.Rpc.CallAsync("eth-mainnet", new
{
    jsonrpc = "2.0",
    id = 1,
    method = "eth_blockNumber",
    @params = Array.Empty<object>(),
});
Console.WriteLine(res?["result"]);
09

Managing your account over HTTP

The management API at https://api.iteradian.com/api/v1 covers what the dashboard does: accounts, organizations, members, API keys, usage, logs, alerts, billing and support. It authenticates with an access token in Authorization: Bearer <accessToken> — not with an API key.

Signing in returns an access token that lasts 15 minutes and a refresh token that lasts 7 days. Refresh tokens are single-use: each refresh returns a new one, so store it every time.

Sign in, call, refresh
# Sign in — returns accessToken (15 min) and refreshToken (7 days)
curl -sS https://api.iteradian.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"…"}'
# With 2FA on, the first response is {"requires2FA":true}; repeat with "twoFactorCode":"123456".

curl -sS https://api.iteradian.com/api/v1/orgs -H "Authorization: Bearer $ACCESS_TOKEN"

# On 401: refresh (single-use — store the new refreshToken)
curl -sS https://api.iteradian.com/api/v1/auth/refresh \
  -H "Content-Type: application/json" -d "{\"refreshToken\":\"$REFRESH_TOKEN\"}"

Creating a key

The create body is below. allowedNetworks takes network IDs from GET /networks, not slugs, and unknown fields are rejected.

Create body
{ name, environment: "live"|"test", ipAllowlist?: string[],
  allowedNetworks?: string[],  // network IDs from GET /networks
  rateLimit?: number, expiresAt?: ISO date }
Create a key
curl -sS https://api.iteradian.com/api/v1/orgs/$ORG_ID/keys \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"backend-prod","environment":"live","ipAllowlist":["203.0.113.0/24"],"rateLimit":50}'
# The full key is in this response and is never shown again. Unknown fields are rejected.

Route reference

Every route is under https://api.iteradian.com/api/v1. There is no public OpenAPI or Swagger page, so this table is the reference.

Management API routes
GroupRoutes
Public (no sign-in)GET /plans, GET /plans/{planId}, GET /health
AuthPOST /auth/register, /auth/login, /auth/refresh, /auth/logout, /auth/verify-email, /auth/resend-verification, /auth/forgot-password, /auth/reset-password, /auth/magic-link, /auth/magic-login, /auth/2fa/enable, /auth/2fa/verify, /auth/2fa/disable, /auth/2fa/backup-codes; GET /auth/oauth/{google|github}
UserGET/PUT /users/me, PUT /users/me/password, GET /users/me/memberships, DELETE /users/me
OrganizationsGET/POST /orgs, GET/PUT/DELETE /orgs/{orgId}, GET/POST /orgs/{orgId}/members, PUT/DELETE /orgs/{orgId}/members/{memberId}, POST /orgs/{orgId}/leave, GET /orgs/{orgId}/permissions
API keysGET/POST /orgs/{orgId}/keys, GET/PUT/DELETE /orgs/{orgId}/keys/{keyId} (DELETE = revoke), POST /orgs/{orgId}/keys/{keyId}/rotate, GET /orgs/{orgId}/keys/{keyId}/analytics?timeRange=1d|7d|30d|90d
Networks (signed in)GET /networks, GET /networks/{networkId}
Usage and analyticsGET /orgs/{orgId}/usage?from&to, GET /orgs/{orgId}/usage/summary, GET /orgs/{orgId}/dashboard (+ /health, /quick-stats, /request-rate, /error-rate, /latency, /performance)
LogsGET /orgs/{orgId}/logs, /logs/stats, /logs/filters, /logs/{logId}
AlertsGET /orgs/{orgId}/alerts; rules GET/POST /orgs/{orgId}/alerts/rules, GET/PUT/DELETE …/rules/{ruleId}, POST …/rules/{ruleId}/toggle, POST …/rules/seed-defaults; channels GET/POST …/channels, GET/PUT/DELETE …/channels/{channelId}, POST …/channels/{channelId}/test; POST …/alerts/{alertId}/acknowledge, …/resolve
Subscription and billingGET /orgs/{orgId}/subscription, GET …/subscription/preview-change/{planId}, PUT …/subscription/plan (body must include "acceptedTerms": true), POST …/subscription/cancel, POST …/subscription/reactivate, GET …/subscription/invoices; GET /orgs/{orgId}/billing/status, POST …/billing/checkout-session, POST …/billing/portal-session
SupportGET/POST /orgs/{orgId}/support/tickets, GET …/tickets/stats, GET …/tickets/{ticketId}, POST …/tickets/{ticketId}/messages, PUT …/tickets/{ticketId}/status
10

What the dashboard does

Dashboard areas
AreaWhat you get
OverviewTotal requests, error rate, average and P95 latency, active keys, health, recent alerts, a request-rate chart and root-cause hints.
UsageRequests over time, by API key, by network and by region, with a daily table.
Request logsEvery request, filterable by network, method, status, key and more, with details and stats. Kept for 30 days.
AlertsRules for high error rate, high latency, rate limit exceeded, quota warning, service down, key expiring and unusual traffic, with severities from info to critical. Delivered by email, webhook or Slack. Rules are evaluated every 5 minutes.
EndpointsMonitoring for the nodes behind your networks. It does not change how requests are routed — routing is automatic.
StatusA private health view of your organization’s networks and endpoints.
SupportTickets with a category (general, billing, technical, API keys, endpoints, performance, security, feature request, bug report) and a priority from low to urgent.
BillingStripe checkout, the Stripe customer portal for payment methods and invoices, plan changes with a proration preview, cancel and reactivate.
AccountProfile, avatar (with an optional separate dark-theme avatar), password, two-factor authentication and linked Google or GitHub accounts.
SDKs and API guideAn SDKs page and an in-app “Use the API directly” guide. Light, dark and system themes.

Verifying alert webhooks

Webhook deliveries are signed with an X-Signature-256 header of the form sha256=<HMAC>. Compute the HMAC over the raw request body with the channel’s secret and compare before trusting the payload.

Verify a signature (Node.js)
// Node.js — verify an alert webhook before trusting it.
import { createHmac, timingSafeEqual } from "node:crypto";

export function isFromIteradian(rawBody, signatureHeader, secret) {
  // Header: X-Signature-256: sha256=<hex HMAC-SHA256 of the raw request body>
  const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(signatureHeader ?? "");
  const b = Buffer.from(expected);
  return a.length === b.length && timingSafeEqual(a, b);
}

Team and roles

Members are added by email and must already have an Iteradian account; they get access immediately. There are no invitation emails or pending invites. Admins can add developers and viewers; only owners can change roles. Anyone can leave an organization other than their personal one, except its last owner.

Organization roles
RoleCan
OwnerEverything, including cancelling the subscription and deleting the organization.
AdminManage members (except owners and admins), API keys, alerts, endpoints and billing — checkout, plan changes, invoices. Cannot cancel, reactivate or delete the organization.
DeveloperRead keys, usage, analytics, logs, alerts and endpoints; open support tickets.
ViewerRead-only.

Accounts and sign-in

  • Sign up with an email and a password of 8 to 128 characters that includes upper and lower case letters, a digit and a symbol.
  • Sign in with a password, a magic link (emailed, valid for 15 minutes), Google or GitHub. A Google or GitHub sign-in whose email already has an account is linked to that account.
  • Password reset links are valid for one hour.
  • Two-factor authentication works with any TOTP authenticator app and comes with 10 one-time backup codes. It applies to password sign-in.
  • You can delete your account yourself (password required). Deletion is blocked while you are the only owner of an organization that has other members.
11

Plans and billing

Plans, prices and limits are read from the live plan API (GET https://api.iteradian.com/api/v1/plans), so this table matches what the gateway enforces. The list can grow as plans are added.

Plans and prices
PlanPrice / monthIncludes
Free RPC$0/moWebSocket Subscriptions · Every Network · Community Support
Developer RPC$39/moWebSocket Subscriptions · Shared Infrastructure · Automatic Failover · Email Support
Professional RPC$169/moWebSocket Subscriptions · Shared + Priority Infrastructure · Priority Failover · Priority Support · Advanced Analytics
Dedicated RPCCustom Contact salesDedicated or isolated infrastructure · Automatic failover where provisioned · Priority Support

Prices and limits read from the control plane on 27 October 2026.

  • New accounts start on a 7-day trial of Developer RPC.
  • Dedicated RPC cannot be bought online: checkout and self-service plan changes point you to sales, and the limits are set per contract.
  • Plan changes are prorated and the difference is invoiced immediately through Stripe. The dashboard shows a preview first.
  • Cancelling takes effect at the end of the current period, and the subscription can be reactivated until then. Only owners can cancel or reactivate.
  • Payment methods and invoices are managed in the Stripe customer portal, opened from Billing.
  • Overage, where a plan has it, is described under Limits, quotas and overage.

See the pricing page · Talk to sales

12

Questions and limitations

Do you support WebSockets?
Yes. Open wss://rpc.iteradian.com/ws/v1/{network} with the same API key, in an X-Api-Key or Authorization: Bearer header, or as ?apiKey= where a browser cannot set headers. eth_subscribe, Solana *Subscribe and other subscription methods work. Every message you send counts as a request, like an HTTP call (a batch of N counts as N); notifications the node pushes are not charged. An organization can hold max(5, a quarter of its concurrency limit) streams open at once.
Can I use trace_*, debug_* or archive queries?
They are forwarded like any other method, but whether they work depends on the node that serves the request. They are not guaranteed, so test them before you depend on them.
Are test keys limited to testnets?
No. Live and test are labels for organizing keys. Either kind can call any network the key is allowed to use.
Is there a daily limit or a burst allowance per key?
No. The limits are your organization’s per-second rate, concurrency and monthly quota. A key can only have a lower per-second limit of its own.
Can I choose which node, region or priority my requests use?
No. Routing is automatic: requests go to a healthy node for the network and fail over when one does not answer. The dashboard’s Endpoints section is for monitoring, not routing.
Can I invite someone who has no account yet?
Not yet. They need an Iteradian account first; then an owner or admin adds them by email and they get access immediately. No invitation email is sent.
Is there a public status page?
No. The dashboard’s Status view shows the health of your own organization’s networks and endpoints.
Is there an OpenAPI or Swagger reference?
Not a public one. Use the route reference in the Management API section, or the SDKs.
Can I buy a contract-priced plan online?
No. Plans priced per contract are arranged with sales, and their limits are set in the contract.
Does two-factor authentication apply to magic-link, Google or GitHub sign-in?
No. Two-factor authentication applies to password sign-in.
Can I call the gateway straight from a browser?
You can, but you should not: a key shipped to a browser or an app can be read by anyone. Send the calls through your own backend.
13

Articles and guides

Querying Bittensor without running your own nodeA Bittensor subnet miner or validator needs a reliable chain endpoint long before it needs its own archive node. This walks through what a managed endpoint gives you, which Substrate methods matter, and the failure modes that actually cost you a weight-set window.Why eth_getLogs is the call that breaks your RPC budgetOne method accounts for a disproportionate share of most teams RPC spend and most of their timeouts. This explains what the node is actually doing during an eth_getLogs call, why block range is the variable that matters, and the query patterns that keep it cheap.Migrating off a self-hosted node without a flag dayMoving from your own node to a managed endpoint does not need a cutover window. This is the incremental path: shadow traffic first, move reads, keep a fallback, and the specific things that break if you skip a step.JSON-RPC 2.0 error codes, and the ones a gateway addsA reference for the error codes you will actually see from an RPC endpoint: the standard JSON-RPC 2.0 set, the node-level codes layered on top, and the gateway codes that tell you a limit was enforced before your request ever reached a node.Compute units, credits or requests: how RPC providers actually bill youRPC providers meter in three incompatible units — compute units, credits and plain requests. The unit decides whether a trace-heavy workload costs the same as a read-heavy one. This post explains each model and how to compare quotes that are not denominated the same way.How to handle RPC rate limits without dropping user transactionsEvery managed RPC provider throttles you eventually. The difference between a brief slowdown and a failed transaction is what your client does with an HTTP 429. This post covers Retry-After, exponential backoff with jitter, request batching and the idempotency trap around sending raw transactions.Public RPC endpoints are free. Here is what they cost you.Every chain publishes a free public RPC endpoint, and they are genuinely useful for local development. In production they introduce aggressive shared rate limits, no archive depth, no analytics and no accountability when they go down. This post covers when the free endpoint is fine and when it stops being fine.

Ready to send a request?

Create an account and a key — the 7-day trial starts immediately.

Get an API key