GET /api/nodes/:address
Every node a wallet holds, with what each has been credited and what it has already withdrawn. Public, because the same list is readable from the contract.
Request
GET /api/nodes/0x1234567890abcdef1234567890abcdef12345678| Parameter | In | Rules |
|---|---|---|
address | Path | A 20-byte hex address. Case insensitive; matched lower case. An invalid address is a 400, not an empty list. |
Response
[
{
"id": 12,
"chainNodeId": "12",
"createdAt": "2026-08-19T09:14:02.114Z",
"balanceWei": "418000000000000",
"cumulativeWei": "902000000000000",
"withdrawnWei": "484000000000000",
"mintTx": "0xab…",
"status": "active"
}
]| Field | Type | Meaning |
|---|---|---|
id | number | Ledger row id. Useful for linking, not for the contract. |
chainNodeId | string | The id the contract knows. This is the one to pass to withdraw or nodeInfo. A string because node ids are uint256. |
createdAt | string or null | ISO 8601 UTC, when the node was recorded |
balanceWei | string | Withdrawable now: cumulativeWei - withdrawnWei |
cumulativeWei | string | Ever credited to this node. Never decreases. |
withdrawnWei | string | Ever paid out. Moves only after a confirmed transaction, and mirrors totalWithdrawnByNode from nodeInfo(id) on chain. |
mintTx | string | Transaction hash the node was minted in |
status | string or null | active or retired. See Node states. |
Nodes are returned oldest first, ordered by chain node id, so ids read in the order they were bought. A wallet with no nodes returns [] with a 200. That is not an error, and neither is an address that has never touched the protocol.
Try it
Enter any address to plot what this endpoint returns for it. Filled bars are value still on the contract, outlined bars are value already withdrawn.
Verifying against the chain
The ids and every wei figure in this response exist on chain too, and should agree. Where they do not, the chain is right.
# the same list of ids, straight from the contract
cast call $FACTORY "nodesOf(address)(uint256[])" $ADDRESS
# owner, createdAt, balance, totalReceived, totalWithdrawnByNode for one of them
cast call $FACTORY \
"nodeInfo(uint256)(address,uint64,uint256,uint256,uint256)" $CHAIN_NODE_IDThe third, fourth and fifth values are the same numbers this endpoint calls balanceWei, cumulativeWei and withdrawnWei.
Caching and limits
| Property | Value |
|---|---|
| Cache-Control | public, max-age=0, s-maxage=5, stale-while-revalidate=15 |
| Rate limit | 60 requests per minute per IP |
Errors
| Status | Body | When |
|---|---|---|
| 400 | { "error": "That is not a valid wallet address." } | The path segment is not a 20-byte hex address |
| 429 | { "error": "Too many requests…" } | Over the per-IP limit |
| 503 | { "error": "This service is not available right now." } | The service is misconfigured |
Example
# total withdrawable across a wallet, in wei
curl -s https://sitowise.xyz/api/nodes/$ADDRESS \
| jq '[.[].balanceWei | tonumber] | add'
# just the chain ids, ready to pass to withdraw(id, to) one at a time
curl -s https://sitowise.xyz/api/nodes/$ADDRESS | jq -r '.[].chainNodeId'There is no batched withdrawal that takes a list of ids. To empty every node at once, call withdrawAll(to) from the owning wallet and pass no ids at all; the contract works out which nodes are yours. See Withdrawing.
Note that tonumber in the first example is fine for a rough total and wrong for accounting. Use a big-integer type when the figure matters; see the API overview.