Skip to main content
A transaction that transfers HBAR and tokens between Hedera accounts. You can enter multiple transfers in a single transaction. The net value of HBAR between the sending accounts and receiving accounts must equal zero. For a CryptoTransferTransactionBody:
  • Max of 10 balance adjustments in its HBAR transfer list.
  • Max of 10 fungible token balance adjustments across all its token transfer list.
  • Max of 10 NFT ownership changes across all its token transfer list.
  • Max of 20 balance adjustments or NFT ownership changes implied by a transaction (including custom fees).
  • If you are transferring a token with custom fees, only two levels of nesting fees are allowed.
  • The sending account is responsible to pay for the custom token fees.
Transaction Fees
  • Please see the transaction and query fees table for the base transaction fee
  • Please use the Hedera fee estimator to estimate your transaction fee cost
Spender Account Allowances An account can have another account spend tokens on its behalf. If the delegated spender account is transacting tokens from the owner account that authorized the allowance, the owner account needs to be specified in the transfer transaction by calling one of the following:
  • addApprovedHbarTransfer()
  • addApprovedTokenTransfer()
  • addApprovedNftTransfer()
  • addApprovedTokenTransferWithDecimals()
The debiting account is the owner’s account when using this feature.
Note: The allowance spender must pay the fee for the transaction.
Account Allowance Hooks (HIP-1195) An account can have Hiero Hooks that act as programmable allowances. Instead of using traditional ERC-style allowances, a TransferTransaction can reference a hook on the sending or receiving account. The hook’s EVM bytecode runs and must return true for the transfer to proceed. This enables custom validation logic like one-time passcodes, compliance rules, or conditional transfer approvals. To invoke a hook, use the WithHook variants of the transfer methods:
  • addHbarTransferWithHook() — HBAR transfers with a FungibleHookCall
  • addTokenTransferWithHook() — Fungible token transfers with a FungibleHookCall
  • addNftTransferWithHook() — NFT transfers with optional sender and receiver NftHookCall
The counterpart transfer entry (the other side of the zero-sum) is added separately with the standard addHbarTransfer(), addTokenTransfer(), or addNftTransfer() methods.
Hook Invocation LimitsChild records generated by hook calls are capped at 50 per transaction (consensus.handle.maxFollowingRecords=50). Hook executions are not supported in batch or scheduled transactions.
Transaction Signing Requirements
  • The accounts the tokens are being debited from are required to sign the transaction
    • If an authorized spender account is spending on behalf of the account that owns the tokens then the spending account is required to sign
  • The transaction fee-paying account is required to sign the transaction

Methods


Transfer with account allowance hooks

The following examples demonstrate how to invoke Hiero Hooks during a transfer. Each WithHook method attaches a hook call to a specific transfer entry. The hook’s EVM bytecode executes and must return true for the transfer to succeed.

Hook call types

Hooks use typed call objects that extend a base HookCall: Each hook call requires a hookId (the 64-bit ID of the hook on the owning account) and an EvmHookCall containing data (extra bytes passed to the hook) and gasLimit (maximum gas the payer will pay for this hook).

Example: HBAR transfer with a pre-hook

Example: NFT transfer with sender and receiver hooks

Example: Fungible token transfer with pre/post hook

Hook execution order

When a TransferTransaction invokes multiple hooks, the network executes them in a strict order:
  1. Pre-hooks: All PRE_HOOK_SENDER / PRE_HOOK_RECEIVER hooks execute in the order their transfers appear (HBAR first, then each token transfer list). For NFT transfers with both sender and receiver hooks, the sender hook executes first.
  2. Pre/Post hooks (pre-transfer call): All PRE_POST_HOOK variants execute their allowPre(...) function, in the same transfer order.
  3. Main transfer logic executes.
  4. Pre/Post hooks (post-transfer call): The same hooks execute their allowPost(...) function, in the same order as step 2.

Get transaction values