> ## Documentation Index
> Fetch the complete documentation index at: https://docs.privy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Usage

To execute a transfer, make a `POST` request to `/v1/wallets/{wallet_id}/transfer`.

### Body

In the body of the request, pass the following parameters.

<ParamField body="source" type="object" required>
  The source asset, amount, and chain for the transfer. Specify either `asset` (for named assets) or
  `asset_address` (for custom assets), not both.

  <Expandable title="properties" defaultOpen>
    <ParamField body="source.asset" type="string">
      The named asset to transfer. Must be one of the listed [well-known
      assets](/wallets/actions/transfer/overview#well-known-assets). Provide either `asset` or
      `asset_address`.
    </ParamField>

    <ParamField body="source.asset_address" type="string">
      The token contract address (EVM) or mint address (Solana) of the asset to transfer. Use this
      field for tokens that are not first-class named assets. Provide either `asset` or
      `asset_address`.
    </ParamField>

    <ParamField body="source.amount" type="string" required>
      The amount of tokens to transfer, as a decimal string in standard units (e.g. `"10.0"` for 10
      USDC). The API handles decimal precision based on the asset — most stablecoins like USDC use 6
      decimal places, while native tokens like ETH use 18 and SOL uses 9. There is no need to
      convert to the smallest unit (e.g. wei, lamports, or micro-units) before sending the request.
    </ParamField>

    <ParamField body="source.chain" type="string" required>
      The chain to transfer from. Must be one of the listed [supported
      chains](/wallets/actions/transfer/overview#supported-chains).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="destination" type="object" required>
  The destination for the transfer.

  <Expandable title="properties" defaultOpen>
    <ParamField body="destination.address" type="string" required>
      The recipient wallet address. Use a hex address for EVM chains and a base58 address for
      Solana.
    </ParamField>

    <ParamField body="destination.asset" type="string">
      The destination asset. Must be one of the listed [well-known
      assets](/wallets/actions/transfer/overview#well-known-assets). Required for cross-asset
      transfers (e.g. transferring `usdt` on the source and receiving `usdc` on the destination).
    </ParamField>

    <ParamField body="destination.chain" type="string">
      The destination chain. Must be one of the listed [supported
      chains](/wallets/actions/transfer/overview#supported-chains). Required for cross-chain
      transfers (e.g. transferring from `tempo` and receiving on `arbitrum`).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="amount" type="string">
  Amount as a decimal string in standard units (e.g. `"10.0"` for 10 USDC). For `exact_input`, the
  amount to send. For `exact_output`, the exact amount to receive. Takes precedence over
  `source.amount` when both are provided.
</ParamField>

<ParamField body="amount_type" type="'exact_input' | 'exact_output'">
  Whether the amount refers to the input token (`exact_input`) or the output token
  (`exact_output`). Defaults to `exact_input`.

  * **`exact_input`** — the specified amount is deducted from the source wallet; the destination
    amount varies based on fees and bridge pricing.
  * **`exact_output`** — the recipient receives exactly the specified amount; the source amount is
    determined by the bridge provider and may be higher due to fees.

  Exact output is only supported for cross-chain or cross-asset (DADC) transfers on EVM source
  chains. Solana is not supported as a source chain for exact output.
</ParamField>

<ParamField body="slippage_bps" type="integer">
  The maximum allowed slippage in basis points (1 bps = 0.01%). Must be between `0` and `10000`.
  Only applies to cross-chain and cross-asset transfers. If omitted, an appropriate slippage
  tolerance is automatically determined based on current market conditions. See
  [slippage](/wallets/actions/swap/overview#slippage) for details.
</ParamField>

<ParamField body="fee_configuration" type="object">
  Optional fee configuration for cross-chain transfers.

  <Expandable title="properties">
    <ParamField body="fee_configuration.type" type="'total_fee_bps'" required>
      The fee model to apply. Currently only `total_fee_bps` is supported.
    </ParamField>

    <ParamField body="fee_configuration.value" type="number" required>
      Total fee cap in basis points (0–10000). Relayer and developer fees must fit within this cap.
      For example, `80` represents 0.8%.
    </ParamField>
  </Expandable>
</ParamField>

### Response

The endpoint returns a `200` response with a pending [wallet action](/wallets/actions/overview) resource.

<Info>
  The transfer action is processed asynchronously. The response contains a pending [wallet
  action](/wallets/actions/overview) resource with `status: "pending"` that Privy processes in the
  background.
</Info>

<ResponseField name="id" type="string">
  The unique identifier for the wallet action.
</ResponseField>

<ResponseField name="status" type="'pending' | 'succeeded' | 'rejected' | 'failed'">
  The current status of the action.
</ResponseField>

<ResponseField name="wallet_id" type="string">
  The ID of the wallet initiating the transfer.
</ResponseField>

<ResponseField name="created_at" type="string">
  The ISO 8601 timestamp for when the action was created.
</ResponseField>

<ResponseField name="type" type="'transfer'">
  The type of action. For transfers, this is always `transfer`.
</ResponseField>

<ResponseField name="amount_type" type="'exact_input' | 'exact_output'">
  The amount type used for this transfer. Omitted when the default `exact_input` was used.
</ResponseField>

<ResponseField name="source_asset" type="string">
  The named asset being transferred (e.g. `"usdc"`, `"eth"`). Present when the transfer was
  initiated with a named `asset`; omitted for custom-token transfers.
</ResponseField>

<ResponseField name="source_asset_address" type="string">
  The token contract address (EVM) or mint address (Solana) of the transferred asset. Present when
  the transfer was initiated with `asset_address`.
</ResponseField>

<ResponseField name="source_asset_decimals" type="integer">
  The number of decimals for the transferred token. Present when the transfer was initiated with
  `asset_address` and the decimals were resolved on-chain.
</ResponseField>

<ResponseField name="source_amount" type="string">
  The amount sent on the source chain as a decimal string (e.g. `"1.5"`). Omitted for `exact_output`
  cross-chain transfers until the source amount is determined.
</ResponseField>

<ResponseField name="source_chain" type="string">
  The chain the transfer is sent from (e.g. `"tempo"`, `"ethereum"`).
</ResponseField>

<ResponseField name="destination_address" type="string">
  The recipient wallet address.
</ResponseField>

<ResponseField name="destination_asset" type="string">
  The destination asset for cross-asset transfers. Omitted for same-asset transfers.
</ResponseField>

<ResponseField name="destination_chain" type="string">
  The destination chain for cross-chain transfers. Omitted for same-chain transfers.
</ResponseField>

<ResponseField name="destination_amount" type="string">
  The amount received on the destination chain. Populated immediately for `exact_output` transfers,
  or after fill confirmation for `exact_input` cross-chain transfers.
</ResponseField>

<ResponseField name="fees" type="FeeLineItem[]">
  Fees paid for the transfer. Each item has a `type` (`relayer` or `developer`) and an `amount` in
  USD. Items of type `developer` include a `recipient` address.
</ResponseField>

<ResponseField name="failure_reason" type="object">
  Present on `rejected` or `failed` actions when available. Contains a `message` string with a
  human-readable description of the failure, and an optional `details` field with additional
  context.
</ResponseField>

To track the status of a transfer, see [wallet action lifecycle](/wallets/actions/overview#wallet-action-lifecycle).

## Examples

<Accordion title="Exact input example">
  <View title="NodeJS" icon="node-js">
    Use the `transfer` convenience method on the wallets service to transfer tokens from a wallet.

    ```typescript {skip-check} theme={"system"}
    const response = await privy.wallets().transfer('insert-wallet-id', {
      source: {
        asset: 'usdc',
        amount: '10.0',
        chain: 'tempo'
      },
      destination: {
        address: '0xRecipientAddress'
      },
      fee_configuration: {
        type: 'total_fee_bps',
        value: 80
      },
      authorization_context: {
        authorization_private_keys: ['<authorization-private-key>']
      }
    });
    ```

    The method returns a `TransferActionResponse` with the pending wallet action. See [wallet action lifecycle](/wallets/actions/overview#wallet-action-lifecycle) to track the status.
  </View>

  <View title="REST API" icon="terminal">
    ```bash theme={"system"}
    curl -X POST https://api.privy.io/v1/wallets/{wallet_id}/transfer \
      -u "<your-privy-app-id>:<your-privy-app-secret>" \
      -H "privy-app-id: <your-privy-app-id>" \
      -H "Content-Type: application/json" \
      -d '{
        "source": {
          "asset": "usdc",
          "amount": "10.0",
          "chain": "tempo"
        },
        "destination": {
          "address": "0xRecipientAddress"
        },
        "fee_configuration": {
          "type": "total_fee_bps",
          "value": 80
        }
      }'
    ```

    ```json Example response theme={"system"}
    {
      "id": "action-id",
      "status": "pending",
      "wallet_id": "wallet-id",
      "created_at": "2026-04-14T20:09:11.929Z",
      "type": "transfer",
      "source_asset": "usdc",
      "source_amount": "10.0",
      "source_chain": "tempo",
      "destination_address": "0xRecipientAddress",
      "fees": [
        {
          "type": "relayer",
          "amount": "0.02"
        },
        {
          "type": "developer",
          "recipient": "0x1234567890abcdef1234567890abcdef12345678",
          "amount": "0.04"
        }
      ]
    }
    ```
  </View>
</Accordion>

<Accordion title="Exact output example">
  To send exactly 100 USDC to a recipient on Arbitrum from a Tempo wallet:

  <View title="NodeJS" icon="node-js">
    ```typescript {skip-check} theme={"system"}
    const response = await privy.wallets().transfer('insert-wallet-id', {
      amount: '100.0',
      amount_type: 'exact_output',
      source: {
        asset: 'usdc',
        chain: 'tempo'
      },
      destination: {
        address: '0xRecipientAddress',
        chain: 'arbitrum'
      },
      authorization_context: {
        authorization_private_keys: ['<authorization-private-key>']
      }
    });
    ```
  </View>

  <View title="REST API" icon="terminal">
    ```bash theme={"system"}
    curl -X POST https://api.privy.io/v1/wallets/{wallet_id}/transfer \
      -u "<your-privy-app-id>:<your-privy-app-secret>" \
      -H "privy-app-id: <your-privy-app-id>" \
      -H "Content-Type: application/json" \
      -d '{
        "amount": "100.0",
        "amount_type": "exact_output",
        "source": {
          "asset": "usdc",
          "chain": "tempo"
        },
        "destination": {
          "address": "0xRecipientAddress",
          "chain": "arbitrum"
        }
      }'
    ```

    ```json Example response theme={"system"}
    {
      "id": "action-id",
      "status": "pending",
      "wallet_id": "wallet-id",
      "created_at": "2026-04-14T20:09:11.929Z",
      "type": "transfer",
      "amount_type": "exact_output",
      "source_asset": "usdc",
      "source_amount": null,
      "source_chain": "tempo",
      "destination_address": "0xRecipientAddress",
      "destination_chain": "arbitrum",
      "destination_amount": "100.0"
    }
    ```
  </View>

  <Info>
    For `exact_output` cross-chain transfers, `source_amount` is `null` at creation because the exact
    source amount is determined by the bridge provider at execution time. It is populated once the
    transfer is confirmed on-chain.
  </Info>
</Accordion>

## API reference

See the [API reference](/api-reference/wallets/transfer) for more details.
