Skip to main content
This guide shows how to fetch a transaction trace from the Ton Center API and how to interpret it.
A trace expands a single transaction into a tree of all triggered calls, including intermediate contract executions, fees, and message flows across accounts.
This recipe is useful for:
  • Exchanges validating deposits end-to-end
  • DApps debugging complex interactions (e.g., Jetton swaps, NFT mints)
  • Explorers building a visual graph of what happened in a transaction
  • Bridges indexing trace finality to confirm cross-chain settlement consistency
The examples use the public Ton Center endpoint:
For production, request your own API key and use a dedicated endpoint for higher rate limits and stability.

Understanding Traces

A trace represents the complete on-chain execution flow of a transaction. It shows every step that occurred as the message propagated through the network—covering all internal calls, fees, and resulting state changes. In other words, it provides:
  • the full call chain (incoming -> outgoing -> nested calls),
  • all intermediate transactions involved,
  • state updates and fees for each phase,
  • bounce behavior and exit codes indicating success or failure.
Traces are authoritative because they reflect the final, confirmed result on the blockchain.

Emulation vs. On-chain Trace

While traces show what actually happened, trace emulation predicts what would happen if a message were processed at the current network state. Emulation is typically used before sending a transaction to:
  • estimate whether it will succeed or fail,
  • preview gas consumption and expected actions,
  • simulate complex interactions like swaps or NFT mints.
Once the transaction is included on-chain, the on-chain trace becomes the factual record of the execution.
Workflow tip
  1. Before sending: emulate to check success, cost, and side effects.
  2. After confirmation: fetch the on-chain trace to verify final behavior and outcomes.

How to obtain the transaction hash

You need a transaction hash (or a normalized external-in hash) to fetch a trace.
  • From a block explorer like tonviewer.com or tonscan.org (copy the tx hash from the UI).
  • From Ton Center APIs that return transactions.
  • If you start from an external-in (e.g., sent through TON Connect), compute the normalized external-in hash per [TEP-467] and locate the resulting transaction. See the dedicated guide for message lookup.
That guide explains normalization (TEP-467) and provides working code to:
  • compute the normalized hash of the external-in,
  • page through the destination account’s history,
  • match the transaction by comparing the normalized input message.

Fetching and Analyzing Traces

1. Fetch a trace by transaction hash

If you start from an external-in, first follow Message lookup to resolve the transaction hash, then call /traces with that hash.

2. Understanding the response

A trace response has three layers:
  1. Trace envelope (per trace):
  • trace_id: identifier for this end-to-end trace.
  • external_hash (optional): normalized hash of the originating external-in (if any).
  • mc_seqno_start, mc_seqno_end: masterchain boundaries in which the trace executed.
  • start_lt / end_lt, start_utime / end_utime: logical times and timestamps for the trace window.
  • trace_info: summary object
    • trace_state: e.g. complete / incomplete
    • counters: messages, transactions, pending_messages
    • classification_state: internal/heuristic classification state (provider-specific)
  • is_incomplete: true when some sub-messages are still pending (e.g., delayed/IHR paths).
  1. Trace tree (trace):
  • A root node { tx_hash, in_msg_hash, children[] }.
  • Children recursively enumerate sub-transactions spawned by out-messages.
  1. Transactions map (transactions) and order (transactions_order):
  • transactions is a hash -> transaction dictionary giving full details for each tx in the tree.
  • transactions_order offers a deterministic ordering for UI rendering.
Inside each transaction:
  • account, hash, lt, now, mc_block_seqno
  • Phases under description:
    • storage_ph: storage fee collection and status change
    • credit_ph: inbound value credit (if any)
    • compute_ph: VM execution info (success, exit_code, gas_used, vm_steps, etc.)
    • action: actions taken, msgs_created, fwd fees, result_code
  • in_msg: the inbound message (fields like source, destination, value, opcode, bounce, message_content, etc.)
  • out_msgs: array of messages produced by this tx
  • account_state_before / account_state_after: balance, code/data hashes, status transitions
  • emulated: whether this record was emulated (for real on-chain traces this is false)
Output for transaction hash Vy11B+AiGGrDBcGx3UiUFUJozUQ3U2yHvaATSrS03og=:
Reading the example
  • External -> 0:9B14…27D1 : 0 — the trace starts from an external-in with 0 nanotons attached.
  • 0:9B14…27D1 -> 0:52D7…1C77 : 565,276,000 — value forwarded to a contract.
  • 0:52D7…1C77 -> 0:1C22…8E34 : 547,800,000 — the contract performs a sub-transfer.
  • 0:1C22…8E34 -> 0:8524…283A : 543,800,000 (100 Telegram Stars) — main action.
  • 0:52D7…1C77 -> 0:F9BC…94A1 : 4,350,400 (Fee) — processing fee path.
  • 0:52D7…1C77 -> 0:7D87…5E19 : 6,525,600 — small commission/auxiliary payout.
Look at:
  • compute_ph.success and exit_code to confirm execution success.
  • action.msgs_created and each message’s bounce/bounced flags.
  • total_fees, gas_used for cost analysis.
  • account_state_* to verify code/data and balance deltas.
Field legend

3. End-to-end flow

Below is a pragmatic end-to-end flow developers typically implement:
  1. Create an external-in (e.g., via TON Connect).
  2. Emulate (optional but recommended) to anticipate success and costs.
  3. Send.
  4. Wait for inclusion using Message lookup (normalized hash).
  5. Trace the final transaction with /traces and render the call tree.

Troubleshooting

  • is_incomplete: true: some sub-messages were still pending at query time—poll again.
  • No trace found: the transaction may not be finalized or you’re using the wrong hash. If starting from an external-in, verify normalization and use the Message lookup flow.
  • Bounced messages: look for bounce: true and bounced: true in message nodes; check exit_code and compute_ph for the failing hop.