Skip to content
Last updated

Events & monitoring

Choose which transaction activity your application reacts to and when it receives notifications. This guide explains typed events and subscription triggers, including the difference between transaction detection and confirmation.

4 kinds shared by EVM and Tron 4 Tron staking kinds 1 Bitcoin kind 1 trigger per subscription

Anatomy of an event

A transaction is a container: it can move value, grant permissions and call a contract. Its network fee can be zero; a Bitcoin coinbase transaction pays no fee. Vilna decodes the value moves, permission grants and contract calls into typed events; the fee stays on the transaction itself, not inside any event.

Transaction0x1234…cdef3 a contract interaction
0interaction

contract called

1approval

spending approved

2transfer

value moves

Every event carries two fields common to every kind, plus fields specific to that kind:

  • event_index - a zero-based position within the transaction, so you always know the order events happened in.
  • kind - the event's type: transfer, approval, interaction, contract_creation, one of Tron's four staking kinds, or Bitcoin's utxo_transfer.

The kind-specific fields sit directly on the event object - there is no data wrapper. A transfer event, for example, carries event_index, kind, asset_gid, amount, operation, from_address and to_address all at the same level. See the illustration below.

The network fee is not one of these events - it is a sibling field on the transaction, details.fee.

Event kinds by chain family

Which kinds a transaction can carry depends on its chain family. EVM and Tron share four kinds; Tron adds four staking-specific kinds on top of those; Bitcoin has exactly one.

For complete event variant schemas, see the Get transaction response. The examples below illustrate what each kind means.

transferEVMTRON

Assets moved from one address to another.

{
  "event_index": 0,
  "kind": "transfer",
  "asset_gid": "eip155:1/erc20:0xdAC17F958D2ee523a2206206994597C13D831ec7",
  "amount": { "base": "1000000", "formatted": "1.0" },
  "operation": "transfer",
  "from_address": "0x742d35cc6634c0532925a3b8d1e1d78d8E15e5c4",
  "to_address": "0x95212290dd7278aa3ddd389cc1e1d165cc4bafe5"
}
Scenario

A user sends 1 USDT to a merchant wallet. The transfer event carries the sender, the recipient, the asset and the exact amount - your deposit detection matches the recipient to a customer.

approvalEVMTRON

A token spending allowance was granted or changed.

{
  "event_index": 0,
  "kind": "approval",
  "asset_gid": "eip155:1/erc20:0xdAC17F958D2ee523a2206206994597C13D831ec7",
  "owner_address": "0x742d35cc6634c0532925a3b8d1e1d78d8E15e5c4",
  "spender_address": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
  "allowance": { "base": "1000000000", "formatted": "1000.0" }
}
Scenario

Someone gets approved to move tokens from a monitored address. A transfer-only view stays silent until the tokens actually move; the approval event is the early warning - flag unlimited or unusually large allowances for review.

interactionEVMTRON

A smart-contract call was made, with its outcome.

{
  "event_index": 0,
  "kind": "interaction",
  "target_address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
  "caller_address": "0x742d35cc6634c0532925a3b8d1e1d78d8E15e5c4",
  "outcome": "succeeded"
}
Scenario

A monitored address interacts with a contract, even when no tokens move directly. The interaction event records the call and its outcome - useful for phishing detection and audit trails. A reverted outcome means the call rolled back; nothing it attempted took effect.

contract_creationEVMTRON

A new smart contract was deployed.

{
  "event_index": 0,
  "kind": "contract_creation",
  "creator_address": "0x742d35cc6634c0532925a3b8d1e1d78d8E15e5c4",
  "created_address": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
}
Scenario

A monitored address deploys a contract. The event records who deployed it and where it now lives - useful for compliance logging.

stakeTRON

TRX was locked for a network resource.

{
  "event_index": 0,
  "kind": "stake",
  "owner_address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "amount": { "base": "1000000000", "formatted": "1000.0" },
  "resource": "energy"
}
Scenario

An account locks TRX to gain a network resource. The stake event names the resource - bandwidth, energy or voting power - and the amount locked.

unstakeTRON

A stake was released back toward the owner.

{
  "event_index": 0,
  "kind": "unstake",
  "owner_address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "amount": { "base": "1000000000", "formatted": "1000.0" },
  "resource": "energy"
}
Scenario

An account requests its staked TRX back. The unstake event records the resource and amount being released; the funds themselves return later, when a separate stake_withdrawal event fires.

stake_withdrawalTRON

TRX from a matured unstake became spendable again.

{
  "event_index": 0,
  "kind": "stake_withdrawal",
  "owner_address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "amount": { "base": "1000000000", "formatted": "1000.0" }
}
Scenario

TRX from a matured unstake becomes spendable again. The stake_withdrawal event marks the moment the funds actually return to the owner.

unstake_cancellationTRON

A pending unstake was cancelled.

{
  "event_index": 0,
  "kind": "unstake_cancellation",
  "owner_address": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "amount": { "base": "1000000000", "formatted": "1000.0" },
  "resource": "energy"
}
Scenario

A pending unstake is cancelled before it matures, and the amount returns to the active stake. The unstake_cancellation event records the resource and amount involved.

utxo_transferBitcoin

A UTXO transfer with full input/output visibility - used on Bitcoin instead of transfer.

{
  "event_index": 0,
  "kind": "utxo_transfer",
  "asset_gid": "bip122:000000000019d6689c085ae165831e93/slip44:0",
  "is_coinbase": false,
  "inputs": [{
    "input_index": 0,
    "previous_txid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
    "previous_output_index": 1,
    "amount": { "base": "150000", "formatted": "0.0015" }
  }],
  "outputs": [
    { "output_index": 0, "amount": { "base": "100000", "formatted": "0.001" } },
    { "output_index": 1, "amount": { "base": "45000", "formatted": "0.00045" } }
  ]
}
Scenario

AML screening needs every funding source, not just one sender. A single utxo_transfer event lists every input and output, so compliance sees the complete picture. A coinbase transaction, the block's own subsidy, has no inputs at all - is_coinbase marks it.

Why track more than transfers

The approval, interaction and contract_creation events show permissions, calls and deployments alongside transfers, so you can relate actions within one transaction:

Example: a DeFi swap to 4 events

A single swap on a decentralized exchange can fan out into four events. A transfer-only view catches the two token movements but misses the interaction that triggered them and the approval that authorized the router to spend:

Transaction0x9c4e…71af4 events from one swap
0interaction

user calls the swap router

1approval

router granted an allowance

2transfer

input token moves to the pool

3transfer

output token moves to the user

What's tracked per chain family

Chain families differ in what they support. Here is what Vilna emits for each - the live, complete list is always available from GET /blockchains.

CapabilityEVMTRONBitcoin
transferNative + ERC-20Native + TRC-20N/A
approvalERC-20TRC-20N/A
interactionContract callsContract callsN/A
contract_creationDeploymentDeploymentN/A
stakeN/AResource stakeN/A
unstakeN/AResource unstakeN/A
stake_withdrawalN/AMatured funds returnN/A
unstake_cancellationN/APending unstake cancelledN/A
utxo_transferN/AN/AFull inputs/outputs

Bitcoin uses utxo_transfer instead of transfer to expose every input and output - it has no smart contracts, so approval, interaction and contract_creation do not apply. The four staking kinds are specific to Tron's resource model.

Solana registers addresses and resolves tokens, without transactions or events.

When a notification fires

A subscription notifies once, when its trigger condition is met - not automatically at two separate stages. The trigger you choose decides that moment.

Triggers

Block

A block trigger fires a fixed number of blocks after inclusion. after_blocks: 0 reports the transaction as seen, with no finality guarantee.

Network

A network trigger fires once the chain's own confirmation policy is satisfied - a threshold Vilna does not publish.

Mempool

A mempool trigger fires before inclusion, for Bitcoin only. See the repeat-notification exception below.

A subscription picks exactly one trigger kind at creation and keeps it for life; only a block trigger's after_blocks value can change later, through PATCH, and changing it re-evaluates every wait that has not fired yet. Want an early signal and a later confirmation signal? Create two subscriptions with different triggers, rather than expecting one subscription to deliver both.

Use Create subscription to select a channel, family and one trigger. Choose block with after_blocks: 0 to notify as soon as a transaction is included. See Update subscription for changing the supported threshold. Those operation pages provide schemas and request examples. Save a separate Idempotency-Key and the original inputs; reuse them after a lost response. See retry rules.

One notice per transaction

A subscription creates at most one notification per transaction; that notification may have multiple delivery attempts. Re-inclusion, a changed block hash or a later content revision never repeats or corrects a notice that already went out. The one exception is a mempool subscription: it can notify a second time if the transaction leaves the mempool for more than an hour and then reappears.

A block trigger describes inclusion depth; a network trigger describes the chain's confirmation policy. Successful webhook delivery proves only that a message arrived, not that an invoice completed. For invoices, re-read status, received_amount, confirmed_amount and transaction links.

There is no notice for a reorganization. If a transaction you were told about later drops out of the chain, you will not get a follow-up message - reconcile through the API if you need certainty.

The noise filter

Every subscription carries is_noise_filtered, on by default. With it on, a notice fires only when the selected address itself acted - as sender, caller, creator or owner - or when the native asset moved, or a token that is verified (is_verified) or trusted by your project (is_trusted) moved. An unrelated address moving an unfamiliar token through your address stays quiet. Which tokens count as verified or trusted, and how to add one, is in the tokens guide.

Turning is_noise_filtered off removes only that rule: every matching activity notifies, including unfamiliar tokens. It does not mark a token as trusted and does not start tracking its balance. Either way, a notification always carries the whole transaction, not just the part that qualified it.

Scope and edits

A subscription only catches transactions from the moment it is created onward - there is no replay of history. Changing filters, tags or trust status takes effect only for transactions evaluated after the change; nothing already queued or delivered is touched.

Disabling a subscription cancels its unfinished waits. Re-enabling it does not resume them - it only starts catching new transactions again.

Inside the webhook payload

With payload_version: v2, a notification contains WebhookV2Payload. Use item.details.events for decoded actions, item.activity for per-address changes and references for names and metadata. The Webhooks reference defines the envelope, schemas and signature verification. Choose the webhook payload version independently of the HTTP API version.

Consuming events

For the mechanics of a reliable handler - responding fast, verifying X-Webhook-Signature, deduplicating by event_id - see the Webhooks reference. Once a verified payload reaches your code, work the event model directly.

After signature verification, select events by kind: transfer describes an EVM/Tron transfer; utxo_transfer exposes Bitcoin inputs and outputs. Resolve metadata by the exact asset_gid in references.tokens, and keep base exact for calculations. Reconcile current facts through Get transaction and per-address changes through List activity.

Routing & delivery

See Notification channels for channel setup and relaying to other systems.

Notifications are dispatched in event order, but delivery is not strictly ordered - a slow endpoint can receive a later event before an earlier retry completes. Group transactions by chain_gid, then order events by details.block.block_height, details.transaction_index and event_index. When there is no block, as in a Bitcoin mempool notice, item.created_at gives only observation order, not chain order. Timing, retry schedule and channel auto-disable are covered in the Webhooks reference.