Pular para o conteúdo

Every transaction, outgoing or incoming, moves through a series of statuses until it's confirmed on the blockchain, rejected, or failed. The console lists every transaction for a wallet, and for all wallets across your organization, with its current status. Open a transaction to see its full stage timeline and details. You can also follow a transaction's progress through the API, or with webhooks that notify you when a transaction changes status. For what each status means, see How transactions work.

To get real-time notifications instead of polling, see Webhooks.

Transaction actions

ActionConsole roleConsole procedureAPI procedure
List transactionsAll rolesView the transaction listList transactions
Search and filter transactionsAll rolesSearch and filter transactionsList transactions
Filter by origin or destinationAll rolesSearch and filter transactionsFilter transactions by origin or destination
View a transactionAll rolesView a transactionGet a transaction
Read the recipient and quantity of a contract-token transfer--Read contract-token transfers
Track a transaction to confirmationAll rolesView a transactionTrack the transaction lifecycle

Permissions: In the console, every role can view transactions. See User roles and permissions. The API procedures need an API credential of type TRANSACTIONS. See Prerequisites.

Prerequisites

To use the API procedures on this page, you need:

  • An API credential of type TRANSACTIONS. It grants access to creating and managing transactions. Create credentials in the console. See Manage API credentials and Credential types.
  • An access token. Exchange your credential's clientId and clientSecret for an access token. See Authenticate.

For the base URLs, token lifetime, pagination, filtering, and error format that every endpoint shares, see API conventions.

View the transaction list via the console

To view transactions in the console:

  1. Open the transaction list:
    • To view one wallet's transactions, open the wallet and select its Transactions tab.
    • To view transactions for all wallets across your organization, select Transactions in the main menu.

The list shows each transaction's Type, Details, Status, and Date. A wallet's list includes deposits into the wallet as well as transactions it sent. To sort the list, click the Status or Date column heading. Frozen transactions carry a Frozen label in the transaction list.

A wallet's Transactions tab with a confirmed payment showing the Success status

Search and filter transactions via the console

To find specific transactions in the console:

  1. Open the transaction list. See View the transaction list.
  2. To find a transaction by its hash or ID, enter the value in the Search by hash or ID box.
  3. To filter the list, click Filters and choose a category:
    • Amount — Enter a From and To range and click Apply, or choose one of the Quick filters.
    • Asset — Select one or more assets.
    • Date — Choose a preset (Today, Last 48 hours, Last 7 days, Last 30 days, or This month) or Custom to set your own range.
    • Destination — Select from Wallets or the Address book, or paste a Custom address to include or exclude.
    • Source — Select from Wallets or the Address book, or paste a Custom address to include or exclude.
    • Status — Select one or more statuses, such as Pending, Success, or Failed.

Each active filter appears as a chip, and the Filters button shows how many categories are active. A transaction must match every filter you set. To remove all filters, click Clear filters.

View a transaction via the console

To view a transaction in the console:

  1. In a wallet's Transactions tab, click a transaction to display a summary of the transaction details and current status.
  2. Click View transaction to open the full transaction page, which shows the status timeline and the Details, JSON, Encoded, and Advanced tabs.

The transaction page for a confirmed payment, showing the status timeline and the Details tab

To freeze or unfreeze an incoming transaction from its transaction page, see Configure transaction freeze controls.

Get a transaction via the API

Retrieve a single transaction with GET /v2/vaults/{vaultId}/wallets/{walletId}/transactions/{transactionId} to check its current state. For the full schema, see Get a transaction in the API reference.

curl "https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/transactions/$TRANSACTION_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

The response is the same transaction object, updated. If the transaction belongs to a different wallet, the request returns HTTP 404 with the message transaction not found and the reason PAL010.004. When the transfer completes, status is CONFIRMED, hash holds the blockchain transaction hash, feeQty holds the network fee actually paid, confirmedAssetChanges records the balance movements observed on chain, and reasons holds the blockchain result, such as Blockchain status: tesSUCCESS on the XRP Ledger.

Read contract-token transfers via the API

For an outgoing contract-token transfer, such as an ERC-20 or TRC-20 transfer, the recipient wallet address and token quantity don't appear at the top level of the transaction. Read them from the transaction's asset changes instead.

To read the recipient and quantity of a contract-token transfer:

  1. Get the transaction. See Get a transaction.
  2. Iterate the entries in proposedAssetChanges (before confirmation) or confirmedAssetChanges (after confirmation).
  3. Skip entries with purpose: FEE.
  4. For each TRANSFER entry, read destination.address for the recipient wallet and qty for the token quantity sent to that wallet.

The same lookup works for native transfers: the TRANSFER entry mirrors the top-level fields, so a single code path handles both transfer types.

Why the top-level fields differ. Native asset transfers (ETH, BTC, TRX, XRP, SOL) move value directly from the origin wallet to the recipient wallet. The top-level destinationAddress names the recipient, and the top-level qty is the amount the recipient receives.

Contract-token transfers (ERC-20, TRC-20, BEP-20, ERC-721, and the other token-standard transfers in Supported token standards) work differently. The blockchain runs a call against the token contract, and the contract's internal ledger credits the recipient wallet.

Outgoing transfers: top-level destination names the execution target. For an outgoing transfer — one your organization sends — the top-level destination (and its deprecated equivalent destinationAddress) is the blockchain execution target: the address Ripple Custody (Wallet) submits to the blockchain after it compiles the transaction. For an outgoing contract-token transfer, compilation also sets the top-level qty to "0" and the top-level asset to the blockchain's native asset.

Outgoing transfer typeTop-level destination.addressTop-level qtyTop-level asset
Native asset (for example, ETH, TRX, SOL, BTC, XRP)The recipient wallet addressThe amount the recipient receivesThe transferred asset
Contract token (for example, ERC-20, TRC-20, BEP-20)The token contract addressTypically "0" — no native asset moves to the contractThe blockchain's native asset (for example, TRX for a TRC-20 transfer)

Incoming transfers keep the recipient at the top level. This normalization applies only to outgoing transfers. See Contract-token deposits.

Field naming

Use the structured destination object instead of the deprecated destinationAddress. destination.address holds the same address, and destination also carries wallet, vault, and counterparty context when Ripple Custody (Wallet) can resolve them. For new integrations, read destination.address.

Asset-change arrays. Every transaction exposes two arrays of AssetChange entries that describe how balances move:

  • proposedAssetChanges — Asset changes that Ripple Custody (Wallet) predicts before confirmation. Ripple Custody (Wallet) populates this array as soon as it compiles the transaction, so you can read it while the transaction is still pending. These values are indicative and can change if the on-chain execution differs from the prediction.
  • confirmedAssetChanges — Asset changes that Ripple Custody (Wallet) records after confirmation, once the transaction reaches CONFIRMED. These values reflect what happened on chain.

Each entry contains these fields:

  • purpose — either TRANSFER (asset movement) or FEE (network fees).
  • asset — the asset that moves.
  • qty — the amount that moves.
  • source — the wallet the asset moves from. On FEE entries, source identifies the fee payer, which can differ from the transfer source when a dedicated fee wallet pays the network fee.
  • destination — the wallet the asset moves to. Populated on TRANSFER entries; not populated on FEE entries.

Both source and destination hold the on-chain address, the wallet ID and vault ID when the wallet belongs to your organization, and any subaccount address the chain requires.

Example: TRC-20 / ERC-20 transfer. The following response shows an outgoing USDT transfer on Tron (TRC-20). USDT on Ethereum, USDC on any EVM chain, and any other ERC-20, TRC-20, or BEP-20 transfer follow the same shape — only the contract, wallet, and asset symbol change.

{
  "id": "019c94f1-cc8c-79b4-9c0f-bc7edaabc267",
  "walletId": "019c8a3b-5678-7def-1234-567890abcdef",
  "vaultId": "019c8a2f-1234-7abc-9def-abcdef123456",
  "status": "CONFIRMED",
  "action": "PALISADE_TRANSFER",
  "blockchain": "TRON",
  "asset": { "symbol": "TRX", "standard": "NATIVE" },
  "originAddress": "TSourceWallet0000000000000000000000",
  "origin": {
    "address": "TSourceWallet0000000000000000000000",
    "walletId": "019c8a3b-5678-7def-1234-567890abcdef"
  },
  "destinationAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "destination": {
    "address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
    "type": "EXTERNAL"
  },
  "qty": "0",
  "proposedAssetChanges": [
    {
      "purpose": "TRANSFER",
      "asset": {
        "symbol": "USDT",
        "standard": "ERC20",
        "contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
      },
      "qty": "125.500000",
      "source": {
        "address": "TSourceWallet0000000000000000000000",
        "walletId": "019c8a3b-5678-7def-1234-567890abcdef",
        "vaultId": "019c8a2f-1234-7abc-9def-abcdef123456"
      },
      "destination": {
        "address": "TRecipientWallet00000000000000000000"
      }
    },
    {
      "purpose": "FEE",
      "asset": { "symbol": "TRX", "standard": "NATIVE" },
      "qty": "13.451000",
      "source": {
        "address": "TSourceWallet0000000000000000000000",
        "walletId": "019c8a3b-5678-7def-1234-567890abcdef"
      }
    }
  ],
  "confirmedAssetChanges": [
    {
      "purpose": "TRANSFER",
      "asset": {
        "symbol": "USDT",
        "standard": "ERC20",
        "contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
      },
      "qty": "125.500000",
      "source": {
        "address": "TSourceWallet0000000000000000000000",
        "walletId": "019c8a3b-5678-7def-1234-567890abcdef",
        "vaultId": "019c8a2f-1234-7abc-9def-abcdef123456"
      },
      "destination": {
        "address": "TRecipientWallet00000000000000000000"
      }
    },
    {
      "purpose": "FEE",
      "asset": { "symbol": "TRX", "standard": "NATIVE" },
      "qty": "13.451000",
      "source": {
        "address": "TSourceWallet0000000000000000000000",
        "walletId": "019c8a3b-5678-7def-1234-567890abcdef"
      }
    }
  ]
}

Read this response as follows:

  • destinationAddress and destination.address both hold TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t — the on-chain USDT contract that Tron runs the transfer against, not the recipient.
  • Top-level qty is "0" because no native TRX moves to the contract. The TRX in the FEE entry is the network fee.
  • Top-level asset is TRX, the blockchain's native asset — compilation normalizes it along with destination and qty. USDT appears only in the TRANSFER asset-change entries.
  • The recipient wallet TRecipientWallet00000000000000000000 and the token quantity 125.500000 appear in the TRANSFER entry of confirmedAssetChanges (or proposedAssetChanges while the transaction is still pending).

The same pattern applies to ERC-20 transfers on Ethereum, Arbitrum, Base, Polygon, Avalanche, and BNB Smart Chain: destination.address names the ERC-20 contract (for example, the USDC contract 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 on Ethereum), and the TRANSFER asset-change entry holds the recipient wallet.

List transactions via the API

List a wallet's transactions with GET /v2/vaults/{vaultId}/wallets/{walletId}/transactions. To list transactions across your whole organization, use GET /v2/transactions. Both endpoints accept the same filter, search, sort, and pagination parameters:

  • Filters — filter.<field>.<operator> query parameters. Filterable fields include status, type (the transaction action, such as PALISADE_TRANSFER for transfers or PALISADE_MANAGED for XRP Ledger transaction types), blockchain, assetSymbol, qty, createdAt, updatedAt, origin, destination, transactionId, transactionHash, externalId, and correlationId. Operators depend on the field — for example eq, notEq, in, and notIn for enums; gt, gte, lt, and lte for qty; and before, after, between.start, between.end, and relativeDays for timestamps. A transaction must match every filter you set. For origin and destination matching rules, see Filter transactions by origin or destination. Use a negative relativeDays value, such as -7 for the last seven days. To find a transaction by its blockchain hash, use filter.transactionHash.contains or filter.transactionHash.startsWith, or pass the hash as search.
  • Search — search runs a case-insensitive free-text search over transaction ID, transaction hash, external ID, correlation ID, asset symbol, origin address, and destination address.
  • Sort — pagination.orderBy accepts created_at, updated_at, amount, or status. Set pagination.order to SORT_ORDER_ASC or SORT_ORDER_DESC.
  • Pagination — pagination.pageSize sets the page size (default 50, maximum 1000; a larger value returns HTTP 400). To get the next page, pass the previous response's filter.nextPageToken as pagination.pageToken. Use the pagination.* form: GET /v2/transactions doesn't accept a top-level pageSize.
curl "https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/transactions?filter.status.eq=CONFIRMED&pagination.pageSize=10" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
curl "https://api.sandbox.palisade.co/v2/transactions?filter.createdAt.relativeDays=-7&pagination.orderBy=created_at&pagination.order=SORT_ORDER_DESC" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Both endpoints return a transactions array of transaction objects and a filter object with pagination metadata: total, plus nextPageToken when there's a next page and previousPageToken when there's a previous one. A wallet's list includes deposits into the wallet as well as transactions it sent.

{
  "transactions": [
    { "id": "01a11af7-f22d-7474-ac46-86c7d4680c3d", "status": "REJECTED", "action": "PALISADE_TRANSFER", "...": "..." }
  ],
  "filter": {
    "previousPageToken": "eyJsaW1pdCI6Miwib2Zmc2V0IjowfQ==",
    "nextPageToken": "eyJsaW1pdCI6Miwib2Zmc2V0Ijo0fQ==",
    "total": 87
  }
}

For complex filters, send them as a JSON body to POST /v2/transactions:list or POST /v2/vaults/{vaultId}/wallets/{walletId}/transactions:list instead. The body takes filter and pagination objects with the same fields, and search as a string. For the full schemas, see List wallet transactions (with a request body) and List transactions (with a request body) in the API reference. For example:

curl -X POST "https://api.sandbox.palisade.co/v2/transactions:list" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": {
      "status": { "in": ["REJECTED", "FAILED"] },
      "createdAt": { "relativeDays": -7 }
    },
    "pagination": { "pageSize": 50, "orderBy": "created_at", "order": "SORT_ORDER_DESC" }
  }'
Deprecated list parameters

On the wallet-level endpoints, the top-level pageSize, pageToken, and correlationId parameters still work but are deprecated; use pagination.pageSize, pagination.pageToken, and filter.correlationId. The address-only filter.originAddress.* and filter.destinationAddress.* filters are also deprecated — see Filter transactions by origin or destination.

Filter transactions by origin or destination via the API

To list transactions by where they come from or go to, add filter.origin.* or filter.destination.* query parameters to GET /v2/transactions or GET /v2/vaults/{vaultId}/wallets/{walletId}/transactions. Each filter matches the origin or destination of a transaction by any of these identifiers:

  • The blockchain address
  • The wallet ID or address book entry ID
  • The counterparty ID
OperatorBehavior
eq, inMatches when any identifier equals a value you supply. Address matching is case-sensitive: supply the address in the form the transaction records, such as the checksummed form of an EVM address.
notEq, notInMatches only when no identifier equals a value you supply.
contains, startsWith, endsWithMatches the address only. Pattern matching is case-insensitive.
isNullChecks whether the origin or destination is empty.

Example: List a wallet's transactions sent to a specific counterparty.

curl -X GET "https://api.sandbox.palisade.co/v2/vaults/$VAULT_ID/wallets/$WALLET_ID/transactions?filter.destination.eq=$COUNTERPARTY_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Example: List transactions received from either of two addresses.

curl -X GET "https://api.sandbox.palisade.co/v2/transactions?filter.origin.in=0x55502b9d5a68b0F8a48384352295BeD968aD8AA4&filter.origin.in=0x8dCd82eC41C41627D987830128198aff4A392D89" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

A transaction must match every filter you set.

Deprecated address-only filters

Ripple Custody (Wallet) deprecates filter.originAddress.* and filter.destinationAddress.*. These filters match the blockchain address only. Their exact and list operators (eq, notEq, in, notIn) are case-sensitive, and their pattern operators are case-insensitive. For new integrations, use filter.origin.* and filter.destination.*.

Track the transaction lifecycle via the API

A transaction moves through a series of status values from creation to completion:

  1. REQUESTED — Ripple Custody (Wallet) accepted the transaction.
  2. POLICY_CHECK_PENDING → POLICY_CHECK_PASSED — Ripple Custody (Wallet) evaluates your policy rules and collects any required approvals. POLICY_CHECK_PASSED means the transaction passed both policy checks and approvals.
  3. COMPILATION_PENDING → COMPILED — Ripple Custody (Wallet) builds the transaction for the target blockchain.
  4. SIGNATURE_PENDING → SIGNED — Ripple Custody (Wallet) signs the transaction.
  5. PUBLISH_PENDING → PUBLISHED — Ripple Custody (Wallet) submits the transaction to the blockchain.
  6. CONFIRMATION_PENDING → CONFIRMED — the blockchain confirms the transaction.

Stages can complete faster than you poll, so you won't necessarily see every status. For example, an XRP Ledger transfer that needs no approvals can reach POLICY_CHECK_PASSED in under a second and CONFIRMED within about ten seconds, and a poll can go straight from POLICY_CHECK_PASSED to SIGNED or PUBLISHED. Don't build logic that waits for a particular intermediate status. Statuses only move forward, so compare a status's position in this list instead.

A transaction can end in REJECTED (a policy or approval check declined it) or FAILED (Ripple Custody (Wallet) couldn't complete it). A policy rejection can happen within moments of creation, so a transaction can go straight from REQUESTED to REJECTED. The problems array contains structured details, including a retryability value of RETRYABLE or NOT_RETRYABLE. For example, a transfer rejected because the wallet's transaction limits aren't active:

{
  "status": "REJECTED",
  "problems": [
    {
      "code": 9,
      "reason": "PAL006.005",
      "domain": "policy-service",
      "message": "Transaction limits for XRP exist but are not active. Check limit approval status.",
      "retryability": "NOT_RETRYABLE",
      "metadata": {}
    }
  ],
  "reasons": [
    "Transaction limits for XRP exist but are not active. Check limit approval status."
  ]
}

The older reasons array is deprecated, but check it when problems is empty: for some blockchain failures, problems is empty and reasons holds the blockchain result, such as Blockchain status: tecUNFUNDED_PAYMENT. For the format of errors that the API returns directly, see Error codes.

Two other fields help you follow a transaction:

  • history — a read-only list of business events for the transaction, such as status changes, policy decisions, approval votes, and freeze actions, each with an event, stage, and outcome. It can be empty, even for a confirmed transfer.
  • expiresAt — when set, the time after which Ripple Custody (Wallet) rejects the transaction if it isn't confirmed. It's null or absent when no expiry applies.

Poll GET /v2/vaults/{vaultId}/wallets/{walletId}/transactions/{transactionId} until the status reaches CONFIRMED, REJECTED, or FAILED, or subscribe to transaction events instead of polling — see Manage webhooks via the API. For a full description of each stage, see How transactions work.