balance.changed event carries the absolute balance of one holder for one
asset after a ledger closes. Use it to keep a wallet or ledger view current
without summing transfers, and to keep an Assets API
snapshot up to date.
Balance events are opt-in. A subscription receives them only when its
event_types lists balance.changed or balance.changed.fees. Subscriptions
with an empty event_types list receive decoded events only.
Subscribe
hmac_secret, as in
Your first webhook. Selectors
apply to balance events as follows:
You can list balance and decoded event types in one subscription, for example
["transfer", "balance.changed"].
Payload
Payload (example values)
Amounts are strings. Parse them as exact integers or decimals, never as
floating-point numbers.
Semantics
- One event per holder, asset and ledger. Several changes inside one ledger are coalesced. The event carries the value after the ledger, not a running sum.
- Fees. An XLM change caused only by a transaction fee (or its refund) is
suppressed unless the subscription lists
balance.changed.fees. That option includes allbalance.changedevents as well. - Contract tokens. Custom SEP-41 tokens are included when the Assets registry recognizes their balance storage layout. Native XLM, classic assets, SAC balances and pool shares are always included. If the registry is temporarily unavailable, delivery continues for those and custom tokens resume once it is reachable again.
- Delivery. Balance events use the same signing, retries, ordering and
credits as other deliveries, and the same
(network, id)deduplication. They exist only in Webhooks; the Activity API has no balance events, so after a gap re-read holdings instead (below).
Stitch with an Assets snapshot
Because each event carries an absolute balance, you can start from any holdings snapshot without a replay:- Create the subscription and read its
activation_checkpointC. - Read holdings from the Assets API. Its
read_view.as_of_ledgeris N. Use a snapshot with N >= C. - Apply only events with
ledger > N, keyed by (holder,asset). Ignore events withledger <= N; the snapshot already contains them. - Keep the event with the highest
ledgerfor each (holder,asset). An older event must never overwrite a newer one, even if it arrives later.
last_ledger and continue from step 3.
Limits
One subscription can admit at most 4,096 events per ledger. Filter balance subscriptions byaccount or asset: a broad selector, such as native
without an account or a subscription with no account or asset at all, can
match thousands of holders in one busy ledger. When a ledger exceeds the
limit, that subscription records a coverage gap for the ledger with reason
payload_or_policy_limit. The subscription stays active and later ledgers are delivered
normally. Narrow the selector,
or repair the gap with a new snapshot.