Skip to main content
Every Activity record is one event: a token movement (token_transfer) or a Soroban contract event (contract_event). This page lists the fields, shows a real record of each kind and explains IDs, amounts and coverage. Activity and webhooks share the same event body. Activity adds paging_token to every record and rpc_event_id to contract events; webhook bodies have neither. Set these once in your terminal. The sample values are real Testnet data, so the read examples return real results.

Fetch the events of a transaction

The transaction has a fee event and a transfer event. The fee record:
A contract_event record, from GET /accounts/$ACCOUNT/contract-events:

Fields

A custom contract event named transfer is not a verified token movement; check kind. Token classification lists the shapes that become token_transfer.

Event IDs

Treat id as an opaque string and deduplicate on (network, id). Its segments are separated by colons: op in a contract event ID is zero-based while the operation_index field is one-based, so operation_index equals op + 1. The event segment can skip numbers, because events that became token_transfer records keep their positions. Activity and webhooks use the same decoder, so the same on-chain event has the same id in both, for the same decoder release (a decoder change that renumbers events would be announced). When you store both:
  • Key on (network, id). Do not include generation: it is product-specific (the Activity index generation and the webhook chain generation differ).
  • Ignore the Activity-only paging_token and rpc_event_id when you compare bodies. balance.changed and webhook.test exist only in webhooks.
  • Ledger numbers and IDs repeat after a Testnet reset: start a new store, or add the reset date to the key.

Paging tokens and RPC event IDs

paging_token has the form {toid}-{index}: a 19-digit TOID and a 10-digit index. The TOID packs the ledger, the one-based transaction index and the one-based operation index (0 for fee events). The index is the zero-based position among the decoded events of that operation, with token-transfer events numbered before contract events. Use it only as a cursor. rpc_event_id uses the same layout, but both parts can differ: RPC counts operations from 0, and its index is the event’s position in the operation’s full event list (the event segment of id). For example, event testnet:5330800:ce:8:0:2 has paging_token 0022895611661549569-0000000004 and rpc_event_id 0022895611661549568-0000000002. Always join with RPC on rpc_event_id; never derive it from paging_token.

Amounts

amount_raw is the exact integer. amount is a decimal rendering; Classic assets and Stellar Asset Contracts use seven decimal places. Keep raw values and use integer or decimal libraries; do not reconcile balances with Number or floating-point columns. For a custom contract token, asset is absent (not null) and contract_address identifies the token. Its amount equals amount_raw: Lumeus does not know the contract’s decimals and applies no scaling. A token’s symbol is not globally unique. A Soroban transaction can have a second fee event with a negative amount: the refund. Sum the fee events of a transaction to get the final fee.

Participants and memos

from and to are the decoded movement roles. issuer marks an issuer action; the issuer is not a participant in holder-to-holder transfers. Muxed destinations can include to_muxed_id, to_muxed_address, to_muxed_text or to_muxed_hash. The transaction memo fields are repeated on each event so you can route deposits without a second request. Validate the routing convention of the application you integrate with.

Contract values

JSON cannot represent every ScVal type losslessly. Use topics_xdr and data_xdr when typed map keys, integer widths or exact bytes matter.

Coverage

Decoded movements include account creation and merge, payments and path payments, executed trades, claimable-balance movements, liquidity-pool reserve movements, inflation payouts, clawbacks, fees and SAC movements. Operations that move nothing (SetOptions, ChangeTrust, ManageData, sequence bumps, sponsorship-only changes, TTL and footprint maintenance) produce no event. Only successful contract events enter the contract-event stream; diagnostic and system events are excluded. A failed transaction keeps its header and fee events. A muxed source is normalized to its base G address. This is decoded event coverage, not every Horizon operation. An unknown future protocol construct stops indexing rather than publishing incomplete history, so a new protocol can need a decoder update first. See service readiness when fresh data stops appearing.