Public API

Networks

Networks routes describe what you can build on: which networks and environments exist, what a webhook or a block costs in credits, which RPC methods a network serves and what each costs, how the networks are doing right now, and which tokens a network accepts for payments. A network is named by its slug (for example ethereum, tron) and an environment by its own slug (mainnet, sepolia, nile). All routes require signed headers (see Authentication). Base URL: see Overview. Success responses use ok: true plus the fields below. A field without a value is not written (it is never null): read a missing field as "no value". Numeric ids are not exposed.

networkscreditsmethodsstatustokensNetworks

← Public API

GET /v1/networks

Active networks, ordered by sort, with the slugs of their environments.

Response fields

NameTypeDescription
okbooleantrue on success.
networks[]arrayNetworks, ordered by sort.
networks[].uuidstringNetwork uuid.
networks[].namestringDisplay name.
networks[].slugstringNetwork slug (use it in paths and in network_slug).
networks[].sortnumberSort order in the catalog.
networks[].environment_kindsstring[]Slugs of the active environments (mainnet, testnets).
networks[].scan_environment_kindsstring[]Environments where events and payments are available. Empty array when none.
  • Takes no query parameters or body. Only active networks and environments are listed.
  • environment_kinds are the slugs of the active environments of the network (mainnet, sepolia, ...). The same slugs are used as env_slug when you create an RPC endpoint and as the environments in GET /v1/networks/{slug}/credits.
  • scan_environment_kinds is the subset of environment_kinds where on-chain events (Address Watch, Tx Watch, Payments, block webhooks) are available. It is an empty array when none.
  • A network is addressed by slug in the other routes; uuid is a stable public identifier.

Request example

import { createHash, createHmac } from 'node:crypto'

const API_KEY = process.env.PUBLIC_API_KEY! // cabinet UUID
const SECRET = process.env.PUBLIC_API_SECRET! // sk_live_…
const BASE = 'https://api.rpcnode.dev'

// path: as the server receives it, with the query; body: the exact string that is sent
async function call(method: string, path: string, body = '') {
  const timestamp = Math.floor(Date.now() / 1000)
  const bodyHash = createHash('sha256').update(body).digest('hex')
  const signature = createHmac('sha256', SECRET)
    .update([timestamp, method, path, bodyHash].join('\n'))
    .digest('hex')
  const res = await fetch(BASE + path, {
    method,
    headers: {
      'X-Api-Key': API_KEY,
      'X-Timestamp': String(timestamp),
      'X-Signature': signature,
      ...(body ? { 'Content-Type': 'application/json' } : {}),
    },
    body: body || undefined,
  })
  return res.json()
}

console.log(await call('GET', '/api/public/v1/networks'))

The request is signed in the snippet itself — see Authentication for the signing rules.

Response example

{
  "ok": true,
  "networks": [
    {
      "uuid": "6f1c2a52-8c0e-4f43-9a55-3c5b6a7d9e10",
      "name": "Ethereum",
      "slug": "ethereum",
      "sort": 10,
      "environment_kinds": ["mainnet", "sepolia", "hoodi"],
      "scan_environment_kinds": ["mainnet", "sepolia"]
    },
    {
      "uuid": "0c7d1e24-5d3b-4a37-b0a1-7a2e9c4f8d21",
      "name": "TRON",
      "slug": "tron",
      "sort": 110,
      "environment_kinds": ["mainnet", "nile"],
      "scan_environment_kinds": ["mainnet"]
    }
  ]
}

GET /v1/networks/{slug}/credits

What an Address Watch event, a payment, a Tx Watch delivery and a block webhook cost in credits, per environment of the network.

Response fields

NameTypeDescription
okbooleantrue on success.
network_slugstringNetwork slug.
network_namestringNetwork display name.
environments[]arrayActive environments of the network.
environments[].slugstringEnvironment slug (mainnet, sepolia, ...).
environments[].namestringEnvironment display name.
environments[].kindstringmainnet | testnet.
environments[].address_watch_creditsnumberCredits for an Address Watch event (charged with the first event).
environments[].payment_creditsnumberCredits for a payment (charged when the money is first seen).
environments[].block_creditsnumberCredits for a block webhook (price of the get-block call).
environments[].tx_watch_creditsnumberCredits for the final delivery of a Tx Watch hash. 0 means free.
  • Path parameter slug is the network slug (for example ethereum). An unknown or inactive network gives 404 with error_code network.not_found.
  • Prices are per environment: a testnet usually costs less than its mainnet. kind is "mainnet" or "testnet".
  • address_watch_credits is charged once, with the first event for a watched address; confirmations and the final state are free. payment_credits is charged once, when the money of a payment is first seen; the other payment events are free. tx_watch_credits is charged for the final delivery of a watched transaction (0 means free). block_credits is the price of one block webhook and equals the price of the network get-block call.
  • Test webhooks are not charged.

Request example

import { createHash, createHmac } from 'node:crypto'

const API_KEY = process.env.PUBLIC_API_KEY! // cabinet UUID
const SECRET = process.env.PUBLIC_API_SECRET! // sk_live_…
const BASE = 'https://api.rpcnode.dev'

// path: as the server receives it, with the query; body: the exact string that is sent
async function call(method: string, path: string, body = '') {
  const timestamp = Math.floor(Date.now() / 1000)
  const bodyHash = createHash('sha256').update(body).digest('hex')
  const signature = createHmac('sha256', SECRET)
    .update([timestamp, method, path, bodyHash].join('\n'))
    .digest('hex')
  const res = await fetch(BASE + path, {
    method,
    headers: {
      'X-Api-Key': API_KEY,
      'X-Timestamp': String(timestamp),
      'X-Signature': signature,
      ...(body ? { 'Content-Type': 'application/json' } : {}),
    },
    body: body || undefined,
  })
  return res.json()
}

console.log(await call('GET', '/api/public/v1/networks/SLUG/credits'))

The request is signed in the snippet itself — see Authentication for the signing rules.

Response example

{
  "ok": true,
  "network_slug": "ethereum",
  "network_name": "Ethereum",
  "environments": [
    {
      "slug": "mainnet",
      "name": "Mainnet",
      "kind": "mainnet",
      "address_watch_credits": 450,
      "payment_credits": 750,
      "block_credits": 40,
      "tx_watch_credits": 150
    },
    {
      "slug": "sepolia",
      "name": "Sepolia Testnet",
      "kind": "testnet",
      "address_watch_credits": 225,
      "payment_credits": 375,
      "block_credits": 40,
      "tx_watch_credits": 75
    }
  ]
}

GET /v1/networks/{slug}/methods

The RPC methods the network serves and what each costs in credits.

Response fields

NameTypeDescription
okbooleantrue on success.
network_slugstringNetwork slug.
network_namestringNetwork display name.
protocolstringRPC family of the network.
methods[]arrayActive methods, ordered by sort.
methods[].uuidstringMethod uuid.
methods[].methodstringRPC method name, or the path for REST-style networks.
methods[].variantstringPrice variant of the method (default, full, ...).
methods[].creditsnumberCredits per call.
methods[].http_methodsstring[]HTTP verbs the method is served with.
methods[].sortnumberSort order.
methods[].descriptionstringShort description. Absent when none. (optional)
  • Path parameter slug is the network slug. An unknown or inactive network gives 404 with error_code network.not_found (ok: false, error_code, error).
  • Only active methods are listed, ordered by sort. A method can appear several times with different variant values (for example "default" and "full", a cheaper and a heavier form of the same call); the price depends on the variant.
  • protocol is the RPC family of the network (for example evm, solana, bitcoin, aptos, cosmos, other). For REST-style families method is a path such as /v1/accounts/{address}.
  • http_methods tells which HTTP verbs the method is served with (POST for JSON-RPC, GET for REST).
  • description is absent when the method has none.

Request example

import { createHash, createHmac } from 'node:crypto'

const API_KEY = process.env.PUBLIC_API_KEY! // cabinet UUID
const SECRET = process.env.PUBLIC_API_SECRET! // sk_live_…
const BASE = 'https://api.rpcnode.dev'

// path: as the server receives it, with the query; body: the exact string that is sent
async function call(method: string, path: string, body = '') {
  const timestamp = Math.floor(Date.now() / 1000)
  const bodyHash = createHash('sha256').update(body).digest('hex')
  const signature = createHmac('sha256', SECRET)
    .update([timestamp, method, path, bodyHash].join('\n'))
    .digest('hex')
  const res = await fetch(BASE + path, {
    method,
    headers: {
      'X-Api-Key': API_KEY,
      'X-Timestamp': String(timestamp),
      'X-Signature': signature,
      ...(body ? { 'Content-Type': 'application/json' } : {}),
    },
    body: body || undefined,
  })
  return res.json()
}

console.log(await call('GET', '/api/public/v1/networks/SLUG/methods'))

The request is signed in the snippet itself — see Authentication for the signing rules.

Response example

{
  "ok": true,
  "network_slug": "ethereum",
  "network_name": "Ethereum",
  "protocol": "evm",
  "methods": [
    {
      "uuid": "b3a6c1de-7f10-4d0b-9e2a-1f4d8c5e6a70",
      "method": "web3_clientVersion",
      "variant": "default",
      "credits": 5,
      "http_methods": ["POST"],
      "sort": 10,
      "description": "Returns the current client version"
    },
    {
      "uuid": "d41e9a02-3c58-4b6f-8a17-5e0c2b9f7d33",
      "method": "eth_getBlockByNumber",
      "variant": "full",
      "credits": 40,
      "http_methods": ["POST"],
      "sort": 120
    }
  ]
}

GET /v1/network-status

Live status of all active networks: status, chain tip height and node latency, as last measured.

Response fields

NameTypeDescription
okbooleantrue on success.
checked_atstringISO-8601 time of this response.
networks[]arrayAll active networks.
networks[].slugstringNetwork slug.
networks[].namestringNetwork display name.
networks[].statusstringok | degraded | unknown | unsupported.
networks[].latency_msnumberAnswer time of the network in milliseconds. Absent when there is no value. (optional)
networks[].block_heightnumberLast known chain tip. Absent when never measured. (optional)
networks[].environment_kindsstring[]Slugs of all active environments of the network.
networks[].environment_kindstringThe environment the figures are of. Absent when the network has no active environment. (optional)
networks[].checked_atstringISO-8601 time of the last check of this network.
  • Takes no query parameters or body. It is cheap to poll.
  • The figures are of one environment per network. environment_kind says which; environment_kinds lists all active environments.
  • status is ok | degraded | unknown | unsupported. unknown means there is no recent status for the network; unsupported means status is not available for it.
  • latency_ms, block_height and environment_kind are absent when there is no value (for example status unknown). checked_at on a network is the time of its last check; the top-level checked_at is the time of this response. Both are ISO-8601 UTC.

Request example

import { createHash, createHmac } from 'node:crypto'

const API_KEY = process.env.PUBLIC_API_KEY! // cabinet UUID
const SECRET = process.env.PUBLIC_API_SECRET! // sk_live_…
const BASE = 'https://api.rpcnode.dev'

// path: as the server receives it, with the query; body: the exact string that is sent
async function call(method: string, path: string, body = '') {
  const timestamp = Math.floor(Date.now() / 1000)
  const bodyHash = createHash('sha256').update(body).digest('hex')
  const signature = createHmac('sha256', SECRET)
    .update([timestamp, method, path, bodyHash].join('\n'))
    .digest('hex')
  const res = await fetch(BASE + path, {
    method,
    headers: {
      'X-Api-Key': API_KEY,
      'X-Timestamp': String(timestamp),
      'X-Signature': signature,
      ...(body ? { 'Content-Type': 'application/json' } : {}),
    },
    body: body || undefined,
  })
  return res.json()
}

console.log(await call('GET', '/api/public/v1/network-status'))

The request is signed in the snippet itself — see Authentication for the signing rules.

Response example

{
  "ok": true,
  "checked_at": "2026-08-07T12:00:30.512Z",
  "networks": [
    {
      "slug": "ethereum",
      "name": "Ethereum",
      "status": "ok",
      "latency_ms": 84,
      "block_height": 23100456,
      "environment_kinds": ["mainnet", "sepolia", "hoodi"],
      "environment_kind": "mainnet",
      "checked_at": "2026-08-07T12:00:02Z"
    },
    {
      "slug": "tron",
      "name": "TRON",
      "status": "unknown",
      "environment_kinds": ["mainnet", "nile"],
      "environment_kind": "mainnet",
      "checked_at": "2026-08-07T12:00:30.512Z"
    }
  ]
}

GET /v1/network-tokens

Tokens of a network that can be used for payments, by contract, with symbol and number of decimals.

Query parameters

NameTypeDescription
network_slugstringNetwork slug (for example ethereum). Required; up to 255 characters; case-insensitive.

Response fields

NameTypeDescription
okbooleantrue on success.
items[]arrayTokens of the network. Empty array when none.
items[].network_slugstringNetwork slug.
items[].contractstringToken contract address (token_contract in POST /v1/payments).
items[].symbolstringToken symbol, for example USDT.
items[].decimalsnumberNumber of decimals of the token.
  • The coin of the network (ETH, TRX, BNB, ...) is not a token and is not in this list. A payment created without token_contract is made in the coin; a token payment names the token by its contract (see Payments).
  • network_slug missing or empty gives 400 common.validation_failed with errors: [{ "field": "network_slug", "error": "network_slug is required." }]. A slug that matches no network gives an empty items array, not 404.
  • Only tokens enabled for payments are listed, each once. A token that is switched off is not listed and a payment in it is rejected with network_token.disabled.
  • Order: USDT, USDC, DAI and WETH first, then by symbol.
  • decimals and symbol are fixed per token and cannot be set in a payment request. Use contract from this list as token_contract.

Request example

import { createHash, createHmac } from 'node:crypto'

const API_KEY = process.env.PUBLIC_API_KEY! // cabinet UUID
const SECRET = process.env.PUBLIC_API_SECRET! // sk_live_…
const BASE = 'https://api.rpcnode.dev'

// path: as the server receives it, with the query; body: the exact string that is sent
async function call(method: string, path: string, body = '') {
  const timestamp = Math.floor(Date.now() / 1000)
  const bodyHash = createHash('sha256').update(body).digest('hex')
  const signature = createHmac('sha256', SECRET)
    .update([timestamp, method, path, bodyHash].join('\n'))
    .digest('hex')
  const res = await fetch(BASE + path, {
    method,
    headers: {
      'X-Api-Key': API_KEY,
      'X-Timestamp': String(timestamp),
      'X-Signature': signature,
      ...(body ? { 'Content-Type': 'application/json' } : {}),
    },
    body: body || undefined,
  })
  return res.json()
}

console.log(await call('GET', '/api/public/v1/network-tokens?network_slug=example'))

The request is signed in the snippet itself — see Authentication for the signing rules.

Response example

{
  "ok": true,
  "items": [
    {
      "network_slug": "ethereum",
      "contract": "0xdac17f958d2ee523a2206206994597c13d831ec7",
      "symbol": "USDT",
      "decimals": 6
    },
    {
      "network_slug": "ethereum",
      "contract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "symbol": "USDC",
      "decimals": 6
    }
  ]
}

Tips

  • Sign every request with X-Api-Key, X-Timestamp and X-Signature (see Authentication). Query strings such as ?network_slug=ethereum are part of the signed path.
  • Errors use { ok: false, error_code, error } and, for a rejected request, an errors list naming each field. See Authentication for the auth errors.
  • Network slugs and environment slugs from GET /v1/networks are the values you pass as network_slug and env_slug when creating RPC endpoints, watches and payments.
  • Poll GET /v1/network-status for a status page or a pre-flight check instead of probing the nodes yourself. Remember the API limit of 100 requests per minute per account.