GET /apiv2/balances/
读取任意 TRON 地址的余额:当前、过去某一时刻、随时间变化的趋势,或某个时间段内的汇总。共六个端点,均为同步接口——结果直接在响应中返回,无需排队,也无需轮询。
端点基础 URL
https://netts.io/apiv2/balances/{address}{address} 是 base58 格式的 TRON 地址,长度正好为 34 个字符。
请求头
| 请求头 | 必填 | 说明 |
|---|---|---|
X-API-KEY | 是 | 来自控制台的 API 密钥 |
X-Real-IP | 是 | 密钥白名单中的地址 |
您的账户余额必须至少为 4 TRX。如果账户欠费,在请求接触到数据之前就会返回 402。
六个端点
| 端点 | 响应内容 |
|---|---|
GET /apiv2/balances/{address} | 当前持有的所有代币 |
GET /apiv2/balances/{address}/at?on=YYYY-MM-DD | 该日期结束时的余额(UTC 时间) |
GET /apiv2/balances/{address}/at-block?block=N | 某一精确区块或 ts=YYYY-MM-DD HH:MM:SS 时的余额 |
GET /apiv2/balances/{address}/history?token_id=TRX&days=90 | 某一单项代币逐日的变动情况 |
GET /apiv2/balances/{address}/summary?date_from=&date_to= | 每种代币的期初、流入、流出、手续费以及期末余额 |
GET /apiv2/balances/{address}/statement?date_from=&date_to= | 包含逐笔操作的对账单预览 |
示例
curl -s 'https://netts.io/apiv2/balances/TXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' \
-H 'X-API-KEY: your-api-key' \
-H 'X-Real-IP: 203.0.113.10'{
"status": "success",
"code": 0,
"msg": "",
"data": {
"address": "TXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"as_of_block": 86012345,
"live": false,
"hide_spam": false,
"total_value_usd": "385.25",
"balances": [
{
"token_id": "TRX",
"symbol": "TRON",
"token_type": "TRX",
"decimals": 6,
"balance": "1141.899000",
"price_usd": "0.334968",
"value_usd": "382.50",
"is_verified": true,
"is_spam": false,
"balance_source": "events",
"node_balance": "1141.899000"
}
]
}
}集成前须知
金额为字符串,而非数值。 "1141.899000" 是序列化为文本的高精度小数,以此避免浮点数转换过程中的精度损失。请使用高精度小数类型(Decimal)进行解析,不要使用浮点型(Float)。
在查询历史的响应中,balance 是正确答案,而 node_balance 不是。 balance 是您所查询时间点的金额。而在每一次回复中,node_balance 都代表链上当前持有的数量——因此在针对上个月的查询结果中,它仍然显示今天的数值。切勿将其作为历史金额展示。对于查询当前的情况,两者的角色刚好互换;这将在下一节中说明。
日期代表该天的结束。 ?on=2026-09-01 返回的是 2026-09-01 23:59:59Z 的数据。如果您需要某一天的期初数据,请请求前一天的期末数据,或者使用带有显式 ts 的 /at-block。
两种余额,以及为什么“当前”最为棘手
响应中包含两个不同的数值,对于活跃地址,它们并不一致:
| 字段 | 含义 | 何时完全准确 |
|---|---|---|
balance | 账本数值,由索引的链上事件重建至 as_of_block 中报告的区块 | 在该区块高度完全准确——但该区块并非最新区块 |
node_balance | TRON 节点当前持有的数值 | 始终为最新值,绝非历史值 |
balance 并不是“当前链上的实时余额”。 它是截至 as_of_block 时的余额。当您需要链上的当前数值时,请读取 node_balance——它是在请求时从 TRON 节点获取的,对于 TRX,它采用完整公式计算:可用流动余额加上质押的 frozenV2 再加上委托出去的部分。在一个持有 4170 万质押 TRX 的地址上,它返回了 42035672.226020,这正好是 237799.226020 + 41760434 + 36816 + 623。如果仅读取节点普通的 balance 字段,将只显示 23.7 万,与实际相差两个数量级。
但并非每一行都会填充 node_balance。 TRX 和所有 TRC10 可以在单次 getaccount 调用中一并返回,因此它们始终包含该字段。TRC20 则无法做到:节点无法直接列出某个地址持有的所有 TRC20 代币,因此仅对主流代币调用 balanceOf 进行查询。在对一个包含 504 行 TRC20 数据的钱包进行测试时,其中 494 行返回了 null。该 null 属于策略限制而非系统故障,若节点出现短暂不可达,也会出现同样的 null。因此,对于 TRX 和 TRC10,您始终可以获取链上的当前数值;而对于长尾 TRC20 代币,您能依赖的只有 balance 及其所在的区块。
只有在所有索引写入程序都确认了某个区块后,账本才会推进至该区块,并且其水位线是所有写入程序中的最小值。由于最慢的写入程序是以批量形式发布标记的,因此延迟差距会逐渐拉大然后迅速收回——呈现锯齿状,而非恒定不变。
2026 年 9 月 6 日在 20 分钟窗口内的抽样数据:
| 落后最新区块数 | 落后时间 | |
|---|---|---|
| 最佳 | 22 | 约 1 分钟 |
| 中位数 | 44 | 约 2 分钟 |
| 90 分位数 | 86 | 约 4 分钟 |
| 观测到的最差情况 | 121 | 约 6 分钟 |
请按账本比区块链落后数分钟(而非数秒)来进行系统设计。
由此可得出以下结论:
- 对于非活跃地址,即便查询“当前”也是完全准确的。 一旦没有变动的时间超过了当前延迟,账本就会追赶上来,此时
balance等于node_balance。 - 对于刚刚发生交易的地址,
balance可能在任一方向上出现偏差——当入账转账尚未被索引时数值偏低,而出账转账尚未被索引时数值偏高。 live=true可以缩小差距,但无法完全消除。 它会在 30–80 毫秒内动态应用as_of_block与链头之间的尾部转账事件。它不会改变as_of_block,不计入手续费,并且会特意跳过由独立索引跟踪的 TRC10 代币。一个实测示例:一个账本报告为157.317444TRX 的地址,在使用live=true时返回了766.194807,而此时节点实际持有1698.995472。虽然有所改善,但node_balance仍然是唯一能代表链上当前数值的字段。- 历史数据绝对完全准确。
/at、/at-block、/history、/summary和/statement描述的是账本很久以前就已经处理过的点。不存在需要考虑的延迟问题。
对于记账、对账和账单生成,请使用历史端点并完全信任它们。对于实时钱包界面,在存在 node_balance 的情况下(涵盖 TRX 和所有 TRC10)展示该字段;若为 null,则退回展示 balance 并在旁边标注 as_of_block,以便用户了解该数值基于哪个区块。
/history 仅返回产生活动的日期。 对一个仅在其中三天发生过变动的地址请求 days=7,将返回三个数据点,而非七个。每个数据点都包含当天的期末 balance 以及相对于前一个数据点的 delta。
/summary 自行完成对账。 对于每种代币,均满足 opening_balance + period_in − period_out − period_fees = closing_balance,引擎会在 control_formula 中直接返回写好的运算式,例如 76493.940406 + 141490.950160 - 216763.731366 - 79.260200 = 1141.899000。费用会拆分为 period_fees_energy 和 period_fees_bandwidth。请注意,/summary 可能会对某种代币报告一个微小的负余额,而当前余额端点可能会将其完全忽略。
/statement 受 ops_limit 限制。 它接受 10 到 5000 笔操作;超出该范围将返回 422。operations_total 是该时间段内的真实总数,operations_truncated 表示列表是否已被截断。省略时,token_id 默认为 TRX。如需获取超过 5000 笔操作的完整对账单,请改为订购文件——参见对账单文件。
代币排序经过精心设计。 TRX 和主流稳定币排在最前,其次是有报价的已认证代币,最后是其他所有代币。切勿按金额重新排序:空投垃圾代币通常带有巨大的名义余额,重排会使其浮动到顶部。
垃圾代币仅作标记,不会被移除。 is_spam 会对归类为欺诈性的代币进行标记。传递 hide_spam=true 可将其从响应中排除;TRX 和 USDT 绝不会被隐藏。
速率限制
每个端点接受 10 次请求/秒,由该端点的所有客户端共享。该限制针对各个端点分别计算,因此 /history 和 /summary 之间互不影响。
超出限制将返回 429 以及 Retry-After: 1,同时附带 RateLimit-Limit、RateLimit-Remaining 和 RateLimit-Reset。请在指定的延迟时间后重试。
针对整个 API,还存在另一项更为宽松的限制:每个源 IP 每秒 100 次请求。两者可通过错误消息进行区分:端点限制会提示 Endpoint rate limit exceeded (10 req/s shared),而全账户限制会提示 API rate limit exceeded。
错误响应
| HTTP | 含义 |
|---|---|
400 | 地址长度为 34 个字符,但未通过 base58 校验和验证 |
401 | 密钥缺失或无效,或者源 IP 不在白名单中 |
402 | 账户余额低于 4 TRX 最低要求 |
403 | API 密钥已被封禁;请联系技术支持 |
422 | 参数缺失或超出范围——错误的地址长度,或 ops_limit 超出 10–5000 的范围 |
429 | 超出速率限制 |
503 | 余额引擎未响应;该请求未计费,请重试 |
根据拒绝请求的层级不同,错误响应体分为三种形式。请根据 HTTP 状态码进行匹配,不要依赖响应体。
// 401, 402, 403 — 网关层,请求接触到服务之前
{"detail": {"code": 1004, "msg": "Insufficient funds. Minimum balance is 4 TRX. Please top up your account."}}
// 400, 422 — 服务层,参数解析完成之后
{"status": "error", "code": -4, "msg": "address must be base58 (T...)", "data": {"code": -4, "msg": "address must be base58 (T...)"}}
// 429 — 限流器
{"message": "Endpoint rate limit exceeded (10 req/s shared), retry shortly", "request_id": "e5dbf25437d2eb215c764617d50b8d3b"}相关内容
- 对账单文件 — CSV 或 PDF 格式的完整对账单
- 报表 Webhook — 在文件生成完毕时接收通知