NOXYDocs
GitHub
Docs/Developers/RPC reference

RPC reference

The NOXY public /v0 HTTP API: submit transactions, read accounts and activity, fetch transaction proofs, and talk to the EVM lane over eth JSON-RPC.

Updated 2026-08-03Status ReferenceSource content/wiki/developers/rpc.mdx

RPC reference

The public API is a JSON-over-HTTP facade in front of the node. On the testnet it is served at https://test.noxycore.io. A self-hosted noxy-public-api binds to 0.0.0.0:8080 by default and talks to the node's local read (:9360) and submit (:9350) RPC ports.

Every response is JSON. Native account and asset IDs are 64-character lowercase hex; uppercase native IDs are rejected with a 400. EVM addresses (0x + 40 hex) are accepted case-insensitively and echoed lowercase.

Errors

All non-EVM endpoints share one error envelope:

{ "error": "account not found", "variant": "not_found" }

variant is a stable machine-readable string. The ones you will meet most: bad_request, hash, limit, cursor, asset, level, not_found, rate_limit, upstream_busy, unavailable, upstream, internal, preverify, auth, insufficient, nonce_mismatch.

Rate limiting is per client IP: a token bucket refilling at 20 requests/second with a burst of 50, plus a global in-flight cap. Over budget returns 429 with variant: rate_limit; no Retry-After header is sent. A 429 with variant: upstream_busy is different: the node itself is applying backpressure.

Health and identity

curl https://test.noxycore.io/v0/health
# { "status": "ok" }

curl https://test.noxycore.io/v0/node/identity
{
  "chain_id": "veylith-testnet-10",
  "genesis_hash_hex": "…",
  "native_asset_id_hex": "…",
  "protocol_version": 4,
  "release_version": "0.1.x",
  "commit_sha": "…",
  "node_role": "…"
}

/v0/health always answers 200 and never touches the node, so it only tells you the facade is up. /v0/economics/summary currently returns just { "native_asset_id_hex": "…" }.

Network stats

curl https://test.noxycore.io/v0/network/stats
{
  "chain_id": "veylith-testnet-10",
  "genesis_hash_hex": "…",
  "protocol_version": 4,
  "node_role": "…",
  "release_version": "0.1.x",
  "checkpoint": {
    "height": 84,
    "ordered_sequence_end": 12040,
    "state_root_hex": "…",
    "ordered_log_root_hex": "…"
  },
  "validators": { "count": 4, "fault_bound": 1, "quorum": 3 },
  "evm": {
    "chain_id_numeric": 20057,
    "window_gas_ceiling": 30000000,
    "base_fee_wei": "1000000000",
    "time_anchor_unix_secs": 1785173149,
    "millis_per_round": 250
  }
}

checkpoint is null until the first durable checkpoint. evm is null on a chain without the EVM lane; on the testnet it carries chain_id_numeric, window_gas_ceiling, base_fee_wei (decimal string), time_anchor_unix_secs, and millis_per_round. An indexed object with activity_rows appears when the node has a read-model attached.

Accounts

# Account record — "account" is null if the account does not exist (never 404)
curl https://test.noxycore.io/v0/account/{id_hex}
# { "account": { "account_id_hex": "…", "account_type": "User",
#                "status": "Active", "sequence_nonce": 7,
#                "primary_key_id_hex": "…" } }

# Next nonce to use — 404 if the account is unknown
curl https://test.noxycore.io/v0/account/{id_hex}/nonce
# { "nonce": 7 }

# Balance of one asset — "0" if the account holds none
curl https://test.noxycore.io/v0/account/{id_hex}/balance/{asset_id_hex}
# { "amount_decimal": "100000000000" }

Balance is a decimal string of base units. The chain is single-asset today: passing any asset ID other than the native one returns 400 with variant: asset.

The same /v0/account/{id} route also serves the EVM side of account duality. Pass a 0x + 40-hex address and the response becomes:

{
  "account": {
    "domain": "evm",
    "address_hex": "0x…",
    "balance_wei": "0",
    "nonce": 0,
    "is_contract": false,
    "code_hash_hex": "…"
  }
}

A never-seen EVM address returns the zero account rather than 404. The /nonce and /balance sub-routes accept native IDs only.

Activity

curl 'https://test.noxycore.io/v0/account/{id_hex}/activity?limit=25'
{
  "account_id_hex": "…",
  "limit": 25,
  "next_cursor": "…",
  "activities": [
    {
      "cursor": "…",
      "tx_hash_hex": "…",
      "block_height": 84,
      "tx_index": 0,
      "tx_type": "Transfer",
      "account_role": "sender",
      "accepted": true,
      "fee_charged_decimal": "1200",
      "state_version": 12040,
      "events_count": 2,
      "transfers": [
        {
          "direction": "sent",
          "counterparty_account_id_hex": "…",
          "asset_id_hex": "…",
          "amount_decimal": "1000000000"
        }
      ]
    }
  ]
}

limit is 1 to 100 (default 25). Pass next_cursor back as ?cursor= to page; next_cursor is null on the last page. A node without a read-model attached answers 200 with an empty activities array rather than an error.

Submit a transaction

curl -X POST https://test.noxycore.io/v0/tx/submit \
  -H 'content-type: application/json' \
  -d '{"envelope_bytes_base64":"<base64 canonical TransactionEnvelope>"}'

Success returns 202:

{ "tx_hash_hex": "9f2c…", "relay_status": "queued" }

Failures and their codes:

| Code | variant | Cause | |---|---|---| | 400 | preverify | invalid base64, oversized envelope, or an envelope the node rejects as malformed | | 401 | auth | signature check failed | | 402 | insufficient | balance below fee or transfer amount | | 409 | nonce_mismatch | envelope nonce ≠ account sequence nonce | | 429 | upstream_busy | node is applying backpressure | | 413 | — | body over the 256 KiB route cap |

Transaction status

curl https://test.noxycore.io/v0/tx/{hash_hex}
{
  "status": "done",
  "receipt": {
    "tx_hash_hex": "9f2c…",
    "stage": "…",
    "outcome": "…",
    "finality": "…",
    "display": {
      "display_label": "…",
      "help_line": "…",
      "progress_step": "…",
      "is_terminal": true,
      "can_user_act": false,
      "funds_effect": "…"
    },
    "dictionary_version": 2
  }
}

status is one of sending, processing, done, failed, unknown. An unknown hash answers 200 with { "status": "unknown", "receipt": null }, not 404. The display object is a ready-to-render status line for wallets; failure_reason_class and user_next_action appear only when relevant.

Transaction proofs

Any committed transaction can be proven against the chain with one GET:

curl 'https://test.noxycore.io/v0/tx/{hash_hex}/proof?level=finality'

level is inclusion, finality (default), or checkpoint. The response carries the transaction digest and index, the batch and window Merkle paths (tx_proof_hex, list_proof_hex), and the ordered reference (ordered_ref_hex). At finality and above it adds the checkpoint and its certificate (checkpoint_hex, checkpoint_cert_hex), so the proof chains up to a validator-signed checkpoint.

A transaction with no durable proof yet returns 404 not_found; one that predates the node's bootstrap base returns 404 post_base_only.

EVM lane: eth JSON-RPC

POST /v0/evm speaks standard eth JSON-RPC 2.0 and is live on the testnet (EVM chain id 20057), so EVM wallets and tooling can point at it directly. Supported methods:

eth_chainId, net_version, eth_blockNumber, eth_gasPrice, eth_maxPriorityFeePerGas, eth_getBlockByNumber, eth_getBlockByHash, eth_getBalance, eth_getTransactionCount, eth_getCode, eth_getStorageAt, eth_call, eth_estimateGas, eth_feeHistory, eth_sendRawTransaction, eth_getTransactionByHash, eth_getTransactionReceipt, eth_getLogs

Batches are supported up to 20 requests. eth_getLogs ranges are capped at 100 blocks. Errors always come back as JSON-RPC error objects over HTTP 200 (-32601 for unsupported methods, -32005 for exceeded limits, 3 for execution reverts).

Account names

Name records live on-chain in StateNamespace::AccountNameRecord. Resolution works from state: normalize the labels, derive the name hash, and read the record — the TypeScript SDK and the wallet do this for you. A dedicated public HTTP resolve endpoint is planned but not exposed yet; see Accounts for the record layout and lease semantics.