For historical information about an account (for example, a full list of past transactions), you need to use the HTTP API. The WebSocket only sends events that occur after you subscribe, so anything that happened before the subscription is not available through WebSocket.
Via WebSocket, you can receive account and transaction–related events in real time:
- When subscribed to
user_transaction events, the node will send a WebSocket message for every transaction where any of the subscribed addresses appears in the transaction.
- When subscribed to
accounts events, the node will send the updated account state whenever there is a change for one of the subscribed addresses.
To subscribe, send this JSON to the /subscribe WebSocket endpoint:
{
"addresses": [
"klv1rgceqsxh3m5jrh3vmdsu5e0dd09fpqn54gftjvll9eu6wdddq05s8ax4nr"
],
"subcribed_types": [
"accounts",
"user_transaction"
]
}
This subscribes you to the accounts and user_transaction events. That means whenever there is:
- A new transaction involving any of the provided
addresses, or
- A change in the account state for any of those
addresses
the node will send a WebSocket event with the corresponding data.
Example of a user_transaction event:
{
"type": "user_transaction",
"address": "klv1rgceqsxh3m5jrh3vmdsu5e0dd09fpqn54gftjvll9eu6wdddq05s8ax4nr",
"hash": "",
"data": "eyJoYXNoIjoiZjNlODU5YTg3OWE1YTMwM2M3NjZjMTRhMTI1MzBhNDY5ZGViYzYyOGFmYWZhYTA2Y2Q5NWU0YTMxN2UwNjQ4MCIsImJsb2NrTnVtIjoxMDgsInNlbmRlciI6ImtsdjFybXF6OXljNWE0eDR5c2w5a3Y0NTBqemZ1dTdzbmF0NXZxNGgwdzdtMGN3NDRldmprM2NzMGtjamN3Iiwibm9uY2UiOjEsInRpbWVzdGFtcCI6MTc2Mzc2NDM1OTAwMCwia0FwcEZlZSI6NTAwMDAwLCJiYW5kd2lkdGhGZWUiOjEwMDAwMDAsInN0YXR1cyI6InN1Y2Nlc3MiLCJyZXN1bHRDb2RlIjoiT2siLCJ2ZXJzaW9uIjoxLCJjaGFpbklEIjoiNDIwNDIwIiwic2lnbmF0dXJlIjpbIjEwODE3Y2NkNzg5ZTMwODAwZTA4ZDc1ZTZjMzU0NDhkYzczOGNkMjlkYzE0OWE0MjBkNmIyNmUwZjIxMDhlYzgzZDZiY2M3ODUxOTJlZDRjNDEzMjA4ZTliODY4Y2ZlYTk3OGZjMWI1ZTY5NGQ1NWZkNTQyNGMyODE4NjE5MDBmIl0sInNlYXJjaE9yZGVyIjowLCJyZWNlaXB0cyI6W3siY0lEIjoyNTUsInNpZ25lciI6ImtsdjFybXF6OXljNWE0eDR5c2w5a3Y0NTBqemZ1dTdzbmF0NXZxNGgwdzdtMGN3NDRldmprM2NzMGtjamN3IiwidHlwZSI6MTksInR5cGVTdHJpbmciOiJTaWduZWRCeSIsIndlaWdodCI6IjEifSx7ImFzc2V0SWQiOiJLTFYiLCJhc3NldFR5cGUiOiJGdW5naWJsZSIsImNJRCI6MCwiY29sbGVjdGlvbiI6IktMViIsImZyb20iOiJrbHYxcm1xejl5YzVhNHg0eXNsOWt2NDUwanpmdXU3c25hdDV2cTRoMHc3bTBjdzQ0ZXZqazNjczBrY2pjdyIsIm1hcmtldHBsYWNlSWQiOiIiLCJub25jZSI6IiIsIm9yZGVySWQiOiIiLCJ0byI6ImtsdjFyZ2NlcXN4aDNtNWpyaDN2bWRzdTVlMGRkMDlmcHFuNTRnZnRqdmxsOWV1NndkZGRxMDVzOGF4NG5yIiwidHlwZSI6MCwidHlwZVN0cmluZyI6IlRyYW5zZmVyIiwidmFsdWUiOjEwMDAwMDAwMH1dLCJjb250cmFjdCI6W3sidHlwZSI6MCwidHlwZVN0cmluZyI6IlRyYW5zZmVyQ29udHJhY3RUeXBlIiwicGFyYW1ldGVyIjp7ImFzc2V0SWQiOiJLTFYiLCJ0b0FkZHJlc3MiOiJrbHYxcmdjZXFzeGgzbTVqcmgzdm1kc3U1ZTBkZDA5ZnBxbjU0Z2Z0anZsbDlldTZ3ZGRkcTA1czhheDRuciIsImFtb3VudCI6MTAwMDAwMDAwfX1dfQ=="
}
Decoding the Base64 in the data field yields:
{
"hash": "f3e859a879a5a303c766c14a12530a469debc628afafaa06cd95e4a317e06480",
"blockNum": 108,
"sender": "klv1rmqz9yc5a4x4ysl9kv450jzfuu7snat5vq4h0w7m0cw44evjk3cs0kcjcw",
"nonce": 1,
"timestamp": 1763764359000,
"kAppFee": 500000,
"bandwidthFee": 1000000,
"status": "success",
"resultCode": "Ok",
"version": 1,
"chainID": "420420",
"signature": [
"10817ccd789e30800e08d75e6c35448dc738cd29dc149a420d6b26e0f2108ec83d6bcc785192ed4c413208e9b868cfea978fc1b5e694d55fd5424c281861900f"
],
"searchOrder": 0,
"receipts": [
{
"cID": 255,
"signer": "klv1rmqz9yc5a4x4ysl9kv450jzfuu7snat5vq4h0w7m0cw44evjk3cs0kcjcw",
"type": 19,
"typeString": "SignedBy",
"weight": "1"
},
{
"assetId": "KLV",
"assetType": "Fungible",
"cID": 0,
"collection": "KLV",
"from": "klv1rmqz9yc5a4x4ysl9kv450jzfuu7snat5vq4h0w7m0cw44evjk3cs0kcjcw",
"marketplaceId": "",
"nonce": "",
"orderId": "",
"to": "klv1rgceqsxh3m5jrh3vmdsu5e0dd09fpqn54gftjvll9eu6wdddq05s8ax4nr",
"type": 0,
"typeString": "Transfer",
"value": 100000000
}
],
"contract": [
{
"type": 0,
"typeString": "TransferContractType",
"parameter": {
"assetId": "KLV",
"toAddress": "klv1rgceqsxh3m5jrh3vmdsu5e0dd09fpqn54gftjvll9eu6wdddq05s8ax4nr",
"amount": 100000000
}
}
]
}
In this example, the address klv1rgceqsxh3m5jrh3vmdsu5e0dd09fpqn54gftjvll9eu6wdddq05s8ax4nr is the receiver of the transfer.
Because we also subscribed to the accounts event type, the node sends an additional event with the updated account state for that address:
{
"type": "accounts",
"address": "klv1rgceqsxh3m5jrh3vmdsu5e0dd09fpqn54gftjvll9eu6wdddq05s8ax4nr",
"hash": "",
"data": "eyJhZGRyZXNzIjoia2x2MXJnY2Vxc3hoM201anJoM3ZtZHN1NWUwZGQwOWZwcW41NGdmdGp2bGw5ZXU2d2RkZHEwNXM4YXg0bnIiLCJub25jZSI6MCwiYmFsYW5jZSI6MTAwMDAwMDAwLCJmcm96ZW5CYWxhbmNlIjowLCJ1bmZyb3plbkJhbGFuY2UiOjAsImFsbG93YW5jZSI6MCwicGVybWlzc2lvbnMiOltdLCJ0aW1lc3RhbXAiOjE3NjM3NjQzNTkwMDB9"
}
Decoding the Base64 data field:
{
"address": "klv1rgceqsxh3m5jrh3vmdsu5e0dd09fpqn54gftjvll9eu6wdddq05s8ax4nr",
"nonce": 0,
"balance": 100000000,
"frozenBalance": 0,
"unfrozenBalance": 0,
"allowance": 0,
"permissions": [],
"timestamp": 1763764359000
}
This represents the current account state after the transaction, where the address now has a balance of 100000000 (it previously had 0).
A few important points about account state and token balances:
- The
accounts event is emitted whenever the account changes, and this includes changes that come from token operations.
- However, the WebSocket
accounts payload does not currently show individual token balances. It only exposes fields like balance, frozenBalance, etc., as in the JSON above.
- This means that if you detect that an account has changed and you want to know which token balances changed and by how much, you still need to query that information via the HTTP API.
In a future node update, we plan to extend the WebSocket accounts events so that they also include token balance changes, but only for the specific tokens that were modified in that event. Until that feature is available, detailed per-token balances must be fetched through the API.