funod RPC Developer Guide¶
Scope and source baseline¶
This catalog targets FullOn Core v0.9.2 and the plugins that can be built
into funod. It covers:
- every HTTP route registered by plugins linked into
funod; - conditions that make a route available or unavailable;
- request fields, response purpose, and mutability;
- the State History WebSocket protocol, which is not a
/v1/*JSON endpoint.
Reviewed on 2026-11-02 against release tag v0.9.2, commit
2188e4f94a1e9fe564a31c33e497b464556f3650: route registration, request structures, and build switches,
not Swagger alone. This replaces the previous RPC baseline and does not
assert that every public node runs this release.
Build boundary: default core excludes History, Trace, and State History;
history includes them by default. Local signing is off by default and test
control depends on build switches. Runtime configuration cannot add omitted
plugins. See release and migration guidance.
fuwal wallet RPC belongs to a different executable and is intentionally not
included here.
Discover the actual routes on a node¶
A route exists only when its API plugin is enabled and its API category is exposed by the listener being called. Ask the node instead of assuming:
get_supported_apis returns the routes visible on that specific TCP or Unix
socket listener. It does not list routes assigned to a different category
listener. A missing route normally means one of these conditions is true:
- its plugin is not enabled;
- its category is not exposed on this listener;
- an additional feature flag is disabled;
- it is restricted to a Unix socket;
- the running node is older than this guide.
Calling conventions¶
The base form is:
Send {} to no-parameter methods. String-only Net API methods expect a JSON
string such as "peer.example.org:9876", not an object. Unless a method says
otherwise, successful read calls return HTTP 200; transaction submission
returns 202; Net and most Producer APIs currently return 201.
Minimal helper:
rpc=http://127.0.0.1:8888
curl --fail --silent --show-error \
-X POST "$rpc/v1/chain/get_info" \
-H 'Content-Type: application/json' \
--data '{}' | jq
The HTTP dispatcher currently resolves a registered path without enforcing a
verb, but clients should use POST for stable compatibility. OPTIONS is
handled for CORS preflight. Treat CORS headers as node configuration, not a
protocol guarantee.
Plugin and category matrix¶
| API group | Required API plugin | Category | Exposure guidance |
|---|---|---|---|
| Node discovery | eosio::http_plugin |
node |
Public or internal |
| Chain read | eosio::chain_api_plugin |
chain_ro |
Public with rate limits |
| Chain write | eosio::chain_api_plugin |
chain_rw |
Public transaction gateway or protected |
| Network read/write | eosio::net_api_plugin |
net_ro, net_rw |
Internal only; keep writes private |
| Producer read/write | eosio::producer_api_plugin |
producer_ro, producer_rw |
Internal only |
| Snapshot control | eosio::producer_api_plugin |
snapshot |
Internal only |
| Chain database size | eosio::db_size_api_plugin |
db_size |
Monitoring network only |
| Trace API | eosio::trace_api_plugin |
trace_api |
Indexed/read node; rate limit |
| Transaction history | eosio::transaction_history_api_plugin |
history_ro |
Indexed/read node; rate limit |
| Prometheus | eosio::prometheus_plugin |
prometheus |
Monitoring network only |
| Local signing gateway | eosio::sign_transaction_api_plugin |
sign_transaction |
Unix socket only |
| Test control | eosio::test_control_api_plugin |
test_control |
Test nodes only |
With a normal http-server-address, the listener exposes all enabled
categories. For production, category listeners allow read and privileged APIs
to be separated:
plugin = eosio::http_plugin
plugin = eosio::chain_api_plugin
plugin = eosio::net_api_plugin
plugin = eosio::producer_api_plugin
http-server-address = http-category-address
http-category-address = chain_ro,0.0.0.0:8888
http-category-address = chain_rw,0.0.0.0:8888
http-category-address = net_ro,127.0.0.1:8890
http-category-address = net_rw,./net-rw.sock
http-category-address = producer_ro,127.0.0.1:8891
http-category-address = producer_rw,./producer-rw.sock
http-category-address = snapshot,./snapshot.sock
In v0.9.2, plugin initialization rejects non-loopback/non-Unix listeners for
net_rw, producer_rw, snapshot, test_control, and the separate wallet
API by default. http-allow-insecure-management-api = true is an explicit
compatibility override, not authentication or encryption, and is only for
already protected gateway topologies. Signing remains Unix-only even with
that override. Disabling protection is not a routine troubleshooting step.
Linked plugins without standalone JSON routes¶
chain_plugin, net_plugin, producer_plugin, signature_provider_plugin,
transaction_history_plugin, and sign_transaction_plugin provide node
functionality consumed by their matching API plugins; they do not independently
register /v1/* routes. resource_monitor_plugin monitors disk use and also
has no client RPC. state_history_plugin is the separate WebSocket service
documented below.
Node discovery API¶
| Path | Body | Result |
|---|---|---|
/v1/node/get_supported_apis |
none | Sorted paths visible on the listener |
This route is provided directly by http_plugin; it is not inserted into its
own returned apis array.
Chain API¶
Enable:
Chain status, blocks, and finality¶
| Path | Request fields | Purpose and availability |
|---|---|---|
/v1/chain/get_info |
{} |
Node version, chain ID, head, LIB, resource limits, gas rates, and earliest available block |
/v1/chain/get_block |
block_num_or_id |
ABI-decoded signed block |
/v1/chain/get_raw_block |
block_num_or_id |
Raw signed-block representation |
/v1/chain/get_block_info |
block_num |
Compact block metadata by number |
/v1/chain/get_block_header |
block_num_or_id, optional include_extensions |
Signed header and optional extensions |
/v1/chain/get_block_header_state |
block_num_or_id |
Legacy block-header state; may be unavailable for retained ranges |
/v1/chain/get_transaction_status |
id |
Tracked transaction state and finality context; only registered when transaction finality status storage is enabled |
/v1/chain/get_finalizer_info |
{} |
Active/pending finalizer policies and last tracked votes |
/v1/chain/get_consensus_parameters |
{} |
Chain configuration and optional WASM configuration |
Although get_info is implemented by chain_api_plugin, it is tagged with the
universal node category and is visible on every configured HTTP listener.
Examples:
curl -sS -X POST "$rpc/v1/chain/get_block" \
-H 'Content-Type: application/json' \
--data '{"block_num_or_id":"14415393"}' | jq
curl -sS -X POST "$rpc/v1/chain/get_transaction_status" \
-H 'Content-Type: application/json' \
--data '{"id":"TRANSACTION_ID"}' | jq
Enable the conditional transaction-status route with a nonzero storage limit:
Its result is a bounded finality-tracking view, not permanent transaction history.
Accounts, code, and ABI¶
| Path | Request fields | Purpose |
|---|---|---|
/v1/chain/get_account |
account_name |
Account metadata, permissions, balances, gas and resource state |
/v1/chain/get_code |
account_name, optional code_as_wasm |
Deployed code hash, WASM/WAST, and ABI |
/v1/chain/get_code_hash |
account_name |
Deployed code hash only |
/v1/chain/get_abi |
account_name |
Decoded ABI definition |
/v1/chain/get_raw_code_and_abi |
account_name |
Raw WASM and ABI blobs |
/v1/chain/get_raw_abi |
account_name, optional abi_hash |
ABI hash and ABI blob; hash supports cache validation |
/v1/chain/get_accounts_by_authorizers |
accounts, keys |
Permissions satisfiable by specified permission levels or public keys; only registered with account queries enabled |
Account example:
curl -sS -X POST "$rpc/v1/chain/get_account" \
-H 'Content-Type: application/json' \
--data '{"account_name":"numguessgame"}' | jq
get_accounts_by_authorizers input example:
Enable this conditional route with:
Contract tables and token data¶
| Path | Request fields | Purpose |
|---|---|---|
/v1/chain/get_table_rows |
code, scope, table, plus options below |
Read rows from one primary or secondary table index |
/v1/chain/get_table_by_scope |
code, optional table, bounds/options |
Enumerate scopes that contain a table |
/v1/chain/get_currency_balance |
code, account, optional symbol |
Token balance rows for an account |
/v1/chain/get_currency_stats |
code, symbol |
Token supply, max supply, and issuer |
Complete get_table_rows request fields:
| Field | Required | Default / meaning |
|---|---|---|
code |
yes | Contract account |
scope |
yes | Table scope, encoded as a string |
table |
yes | Table name |
json |
no | false; use true for ABI-decoded rows |
table_key |
no | Legacy table-key hint |
lower_bound, upper_bound |
no | Index bounds |
limit |
no | 10 |
key_type |
no | Index type such as i64, i128, i256, float64, float128, sha256, or ripemd160 |
index_position |
no | 1/primary, 2/secondary, and so on |
encode_type |
no | dec; may be hex where supported |
reverse |
no | Reverse index traversal |
show_payer |
no | Include each row's RAM payer |
time_limit_ms |
no | Per-query time limit, bounded by node configuration |
Pagination uses more and next_key; pass next_key as the next
lower_bound. Do not infer completion from rows.length < limit alone.
curl -sS -X POST "$rpc/v1/chain/get_table_rows" \
-H 'Content-Type: application/json' \
--data '{
"json": true,
"code": "flon.token",
"scope": "numguessgame",
"table": "accounts",
"limit": 100
}' | jq
Producers, protocol features, and deferred transactions¶
| Path | Request fields | Purpose |
|---|---|---|
/v1/chain/get_producers |
optional json, lower_bound, limit, time_limit_ms |
Producer rows and total vote weight |
/v1/chain/get_producer_schedule |
{} |
Active, pending, and proposed producer schedules |
/v1/chain/get_activated_protocol_features |
optional lower_bound, upper_bound, limit, search_by_block_num, reverse, time_limit_ms |
Activated protocol-feature history |
/v1/chain/get_scheduled_transactions |
optional json, lower_bound, limit, time_limit_ms |
Deferred transaction queue |
For get_activated_protocol_features, bounds represent activation ordinals by
default and block numbers when search_by_block_num is true.
ABI conversion and authorization preparation¶
| Path | Request fields | Purpose |
|---|---|---|
/v1/chain/abi_json_to_bin |
code, action, args |
Serialize JSON action data with the current ABI |
/v1/chain/abi_bin_to_json |
code, action, binargs |
Decode binary action data with the current ABI |
/v1/chain/get_required_keys |
transaction, available_keys |
Determine which available public keys satisfy transaction authorization |
/v1/chain/get_transaction_id |
unpacked transaction object | Calculate the transaction ID without submitting it |
ABI conversion is tied to the ABI currently visible to the node. A client must rebuild and re-sign a transaction if the serialized action data changes.
Transaction simulation and submission¶
| Path | Request shape | Behavior |
|---|---|---|
/v1/chain/compute_transaction |
{ "transaction": <packed-or-unpacked-transaction> } |
Execute for computation/result inspection without normal submission |
/v1/chain/send_read_only_transaction |
{ "transaction": <packed-or-unpacked-transaction> } |
Execute a read-only transaction; registered on all Chain API nodes |
/v1/chain/push_transaction |
packed transaction object | Legacy single transaction submission |
/v1/chain/push_transactions |
array of packed transaction objects | Legacy batch submission |
/v1/chain/send_transaction |
packed transaction object | Submit one transaction |
/v1/chain/send_transaction2 |
wrapper described below | Submit with retry/failure-trace controls; preferred advanced endpoint |
/v1/chain/push_block |
signed block object | Inject a block; privileged operational use only |
send_transaction2 body:
{
"return_failure_trace": true,
"retry_trx": false,
"transaction": {
"signatures": ["SIG_K1_..."],
"compression": 0,
"packed_context_free_data": "",
"packed_trx": "..."
}
}
retry_trx_num_blocks is meaningful when retry_trx is true. Transaction
acceptance also requires api-accept-transactions = true. An HTTP 202
response means the node accepted processing of the request; applications must
still confirm inclusion and then compare the block number with LIB.
Do not use push_transactions as an atomic batch: entries are processed as
individual transactions.
Although send_read_only_transaction is registered whenever Chain API is
enabled, execution requires read-only-threads > 0; otherwise it returns an
unsupported-feature error.
Transaction History API¶
Enable both plugins:
Every registered operation has two equivalent route prefixes:
Use /v1/history/* when clients must also work with older deployed nodes.
The complete registered path set is:
/v1/history/get_transaction
/v1/history/get_actions
/v1/history/get_transaction_count
/v1/history/get_key_accounts
/v1/history/get_controlled_accounts
/v1/history/get_database_stats
/v1/history/get_performance_metrics
/v1/history/get_optimization_suggestions
/v1/history/get_cache_analysis
/v1/history/get_maintenance_needs
/v1/transaction_history/get_transaction
/v1/transaction_history/get_actions
/v1/transaction_history/get_transaction_count
/v1/transaction_history/get_key_accounts
/v1/transaction_history/get_controlled_accounts
/v1/transaction_history/get_database_stats
/v1/transaction_history/get_performance_metrics
/v1/transaction_history/get_optimization_suggestions
/v1/transaction_history/get_cache_analysis
/v1/transaction_history/get_maintenance_needs
| Method | Request fields | Purpose |
|---|---|---|
get_transaction |
id, optional block_num_hint |
Indexed transaction, traces, resources, gas data, block and LIB |
get_actions |
account_name, optional pos, offset |
Indexed account action sequence |
get_transaction_count |
optional start_block, end_block |
Count indexed transactions in a block range |
get_key_accounts |
public_key |
Accounts referenced by an indexed public key |
get_controlled_accounts |
controlling_account |
Accounts controlled by an indexed account authority |
get_database_stats |
{} |
History database statistics |
get_performance_metrics |
{} |
History database/cache performance metrics |
get_optimization_suggestions |
{} |
success, suggestions, optional error |
get_cache_analysis |
{} |
success, analysis, optional error |
get_maintenance_needs |
{} |
success, maintenance_needs, optional error |
v0.9.2 registers the first three diagnostic methods as read-only HTTP RPC
under both prefixes. They do not perform automatic optimization.
trigger_auto_optimize is still not a registered HTTP route. See the history
guide for history_status and index completeness.
See funod Transaction History RPC for pagination, irreversibility, and examples verified through the Flonscan integration.
Trace API¶
Enable:
Alternatively configure trace-no-abis when decoded ABI data is not required.
| Path | Request fields | Result |
|---|---|---|
/v1/trace_api/get_block |
block_num |
Retired action traces and related metadata for a retained block |
/v1/trace_api/get_transaction_trace |
id |
Trace for a transaction ID found in retained trace logs |
Missing retained data returns 404; malformed input returns 400. Trace
retention is local-node policy and can differ from block-log or history-plugin
retention.
Net API¶
Enable:
| Path | JSON body | Mutability |
|---|---|---|
/v1/net/connections |
{} |
Read all peer connection states |
/v1/net/status |
"host:port" |
Read one peer connection state |
/v1/net/connect |
"host:port" |
Open a P2P connection |
/v1/net/disconnect |
"host:port" |
Close a P2P connection |
Example:
curl -sS -X POST "$rpc/v1/net/connect" \
-H 'Content-Type: application/json' \
--data '"peer.example.org:9876"' | jq
connect and disconnect are node-control operations. Restrict net_rw to a
Unix socket or a protected management network.
Producer and Snapshot API¶
Enable:
The node also needs producer configuration appropriate to its role. Enabling the API plugin does not by itself make the node an elected producer.
Read operations¶
| Path | Request fields | Purpose |
|---|---|---|
/v1/producer/paused |
{} |
Whether local production is paused |
/v1/producer/get_runtime_options |
{} |
Current subjective runtime options |
/v1/producer/get_whitelist_blacklist |
{} |
Actor, contract, action, and key allow/deny configuration |
/v1/producer/get_scheduled_protocol_feature_activations |
{} |
Feature digests scheduled for activation |
/v1/producer/get_supported_protocol_features |
optional exclude_disabled, exclude_unactivatable |
Protocol features supported by this binary/configuration |
/v1/producer/get_account_ram_corrections |
optional lower_bound, upper_bound, limit, reverse |
Accounts with RAM correction records |
/v1/producer/get_unapplied_transactions |
optional lower_bound, limit, time_limit_ms |
Transactions waiting in local unapplied queues |
/v1/producer/get_snapshot_requests |
{} |
Scheduled and pending snapshot requests |
Write and control operations¶
| Path | Request fields | Effect |
|---|---|---|
/v1/producer/pause |
{} |
Pause local block production |
/v1/producer/resume |
{} |
Resume local block production |
/v1/producer/update_runtime_options |
optional max_transaction_time, max_irreversible_block_age, produce_block_offset_ms, subjective_cpu_leeway_us |
Change subjective producer runtime limits |
/v1/producer/set_whitelist_blacklist |
optional actor/contract/action/key allow/deny arrays | Replace supplied subjective allow/deny settings |
/v1/producer/create_snapshot |
{} |
Create a snapshot asynchronously |
/v1/producer/schedule_snapshot |
optional block_spacing, start_block_num, end_block_num, snapshot_description |
Schedule snapshots |
/v1/producer/unschedule_snapshot |
snapshot_request_id |
Delete a scheduled snapshot request |
/v1/producer/get_integrity_hash |
{} |
Calculate integrity hash at the current head; operationally expensive/control category |
/v1/producer/schedule_protocol_feature_activations |
protocol_features_to_activate array |
Schedule protocol-feature digests for activation |
Snapshot scheduling example:
{
"block_spacing": 1200,
"start_block_num": 15000000,
"end_block_num": 16000000,
"snapshot_description": "scheduled operational snapshot"
}
Protocol-feature activation changes chain behavior once the feature is included in a produced block. Coordinate binary readiness across producers before using that endpoint.
Compile-time greylist routes¶
These routes exist only when the binary is compiled with
ENABLE_GREYLIST_LIMIT; the standard checked build does not define it:
| Path | Request fields | Purpose |
|---|---|---|
/v1/producer/get_greylist |
{} |
Get greylisted accounts |
/v1/producer/add_greylist_accounts |
accounts array |
Add accounts |
/v1/producer/remove_greylist_accounts |
accounts array |
Remove accounts |
Feature-detect them with get_supported_apis.
DB Size API¶
Enable:
| Path | Body | Result |
|---|---|---|
/v1/db_size/get |
{} |
free_bytes, used_bytes, total size, reclaimable_bytes, and row count per index |
This exposes internal database sizing and schema/index names. Keep it on the monitoring network rather than a public application endpoint.
Prometheus API¶
Enable:
| Path | Body | Content type |
|---|---|---|
/v1/prometheus/metrics |
{} |
text/plain Prometheus exposition format |
Example:
curl --fail --silent --show-error \
-X POST "$rpc/v1/prometheus/metrics" \
-H 'Content-Type: application/json' \
--data '{}'
Sign Transaction API¶
Enable both plugins and configure signature providers:
The following four paths have the same request/response shapes as their Chain API counterparts:
| Path | Body |
|---|---|
/v1/sign_transaction/push_transaction |
packed transaction object |
/v1/sign_transaction/push_transactions |
array of packed transaction objects |
/v1/sign_transaction/send_transaction |
packed transaction object |
/v1/sign_transaction/send_transaction2 |
send_transaction2 wrapper |
All four are marked Unix-socket-only in code. They are unavailable over TCP
even if the TCP listener exposes the sign_transaction category. Configure a
Unix category listener and protect its filesystem permissions:
http-server-address = http-category-address
http-category-address = chain_ro,127.0.0.1:8888
http-category-address = sign_transaction,./sign-transaction.sock
This is a node-integrated signature-provider path, not fuwal wallet RPC.
Test Control API¶
Enable only on disposable test nodes:
| Path | Request fields | Effect |
|---|---|---|
/v1/test_control/kill_node_on_producer |
producer, where_in_sequence, based_on_lib |
Terminate the node at a selected producer sequence for tests |
The actual current route is kill_node_on_producer. An older Swagger file
calls it kill_node_or_producer; do not use that stale path.
Never expose this category on a production node.
State History WebSocket API¶
State History is a binary WebSocket streaming protocol, not HTTP JSON RPC and
does not appear under /v1/node/get_supported_apis.
Enable it separately:
plugin = eosio::state_history_plugin
state-history-endpoint = 127.0.0.1:8080
trace-history = true
chain-state-history = true
finality-data-history = true
On connection the server first sends its ABI as text, then switches to binary messages serialized with that ABI. The current request variants are:
| Request | Important fields / behavior |
|---|---|
get_status_request_v0 |
Get head, LIB, trace/state ranges, and chain ID |
get_status_request_v1 |
Also reports finality-data range |
get_blocks_request_v0 |
start_block_num, end_block_num, max_messages_in_flight, have_positions, irreversible_only, and fetch flags for block/traces/deltas |
get_blocks_request_v1 |
v0 fields plus fetch_finality_data |
get_blocks_ack_request_v0 |
Return num_messages flow-control credits |
The corresponding results are get_status_result_v0/v1 and
get_blocks_result_v0/v1. end_block_num is exclusive. Consumers must honor
max_messages_in_flight, send acknowledgements, preserve block positions for
fork recovery, and decode binary payloads with the ABI supplied by the server.
Keep the endpoint on an internal network; source configuration explicitly warns against public exposure.
Error model and client behavior¶
Standard JSON errors have this general form:
{
"code": 400,
"message": "Invalid Request",
"error": {
"code": 0,
"name": "exception_name",
"what": "error summary",
"details": []
}
}
Important statuses:
| HTTP status | Typical meaning |
|---|---|
200 |
Read or simulation completed |
201 |
Net/Producer operation completed |
202 |
Transaction, block, or test-control request accepted for processing |
400 |
Bad JSON, missing field, unknown block, authorization failure, or invalid request |
404 |
Route/category absent or retained trace/history item unavailable |
500 |
Chain/plugin exception |
503 |
HTTP bytes, requests, connections, or history admission limit exceeded |
Client rules:
- Discover optional routes at startup and cache the capability set briefly.
- Set request timeouts and bounded concurrency.
- Retry only transport failures,
429if introduced by a proxy, and transient503responses with backoff; do not blindly retry deterministic400s. - Treat transaction submission as provisional until inclusion is observed.
- Treat a block as final only when
block_num <= last_irreversible_block_num. - Cache immutable blocks and irreversible transaction details.
- Never send private keys to Chain, History, Trace, or Flonscan endpoints.
Coverage summary¶
A v0.9.2 build with all optional features compiled/enabled can expose up to 76 logical HTTP operations without the compile-time greylist feature. This is a source maximum, not the default core/history package capability set:
- 1 Node discovery operation;
- 35 Chain operations, including two conditionally registered routes and one always-registered read-only transaction route whose execution requires read threads;
- 17 standard Producer/Snapshot operations;
- 10 Transaction History operations, each exposed under two prefixes;
- 4 Net operations;
- 4 Unix-only Sign Transaction operations;
- 2 Trace operations;
- 1 DB Size operation;
- 1 Prometheus operation;
- 1 Test Control operation.
The three greylist operations raise the logical maximum to 79 in a custom
ENABLE_GREYLIST_LIMIT build. History aliases bring the route-path maximum
to 86, or 89 with greylist. Actual availability requires compilation, plugin
enabling, and listener exposure.
Verification basis¶
This guide was rechecked against v0.9.2 / 2188e4f94a1e9fe564a31c33e497b464556f3650.
The audit manifest records source hashes
and registered paths. The review covers:
programs/node/CMakeLists.txtfor plugins linked intofunod;- each API plugin's route-registration implementation;
- reflected request structures in Chain, Producer, History, State History, and Test Control headers;
- HTTP category routing and Unix-socket enforcement;
- the repository Swagger files as a secondary, non-authoritative cross-check.