curl --request POST \
--url https://api.privy.io/v1/wallets/{wallet_id}/transfer \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'privy-app-id: <privy-app-id>' \
--data '
{
"amount_type": "exact_input",
"source": {
"asset": "usdc",
"amount": "10.5",
"chain": "tempo"
},
"destination": {
"asset": "ousd",
"chain": "tempo",
"address": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2"
},
"slippage_bps": 100
}
'HttpResponse<String> response = Unirest.post("https://api.privy.io/v1/wallets/{wallet_id}/transfer")
.header("privy-app-id", "<privy-app-id>")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"amount_type\": \"exact_input\",\n \"source\": {\n \"asset\": \"usdc\",\n \"amount\": \"10.5\",\n \"chain\": \"tempo\"\n },\n \"destination\": {\n \"asset\": \"ousd\",\n \"chain\": \"tempo\",\n \"address\": \"0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2\"\n },\n \"slippage_bps\": 100\n}")
.asString();const options = {
method: 'POST',
headers: {
'privy-app-id': '<privy-app-id>',
Authorization: 'Basic <encoded-value>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount_type: 'exact_input',
source: {asset: 'usdc', amount: '10.5', chain: 'tempo'},
destination: {
asset: 'ousd',
chain: 'tempo',
address: '0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2'
},
slippage_bps: 100
})
};
fetch('https://api.privy.io/v1/wallets/{wallet_id}/transfer', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.privy.io/v1/wallets/{wallet_id}/transfer",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'amount_type' => 'exact_input',
'source' => [
'asset' => 'usdc',
'amount' => '10.5',
'chain' => 'tempo'
],
'destination' => [
'asset' => 'ousd',
'chain' => 'tempo',
'address' => '0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2'
],
'slippage_bps' => 100
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"Content-Type: application/json",
"privy-app-id: <privy-app-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.privy.io/v1/wallets/{wallet_id}/transfer"
payload := strings.NewReader("{\n \"amount_type\": \"exact_input\",\n \"source\": {\n \"asset\": \"usdc\",\n \"amount\": \"10.5\",\n \"chain\": \"tempo\"\n },\n \"destination\": {\n \"asset\": \"ousd\",\n \"chain\": \"tempo\",\n \"address\": \"0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2\"\n },\n \"slippage_bps\": 100\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("privy-app-id", "<privy-app-id>")
req.Header.Add("Authorization", "Basic <encoded-value>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"wallet_id": "fmfdj6yqly31huorjqzq38zc",
"type": "transfer",
"source_asset": "ousd",
"source_amount": "10.5",
"source_chain": "tempo",
"destination_address": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2"
}Transfer
Transfer tokens from a wallet to a destination address.
curl --request POST \
--url https://api.privy.io/v1/wallets/{wallet_id}/transfer \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'privy-app-id: <privy-app-id>' \
--data '
{
"amount_type": "exact_input",
"source": {
"asset": "usdc",
"amount": "10.5",
"chain": "tempo"
},
"destination": {
"asset": "ousd",
"chain": "tempo",
"address": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2"
},
"slippage_bps": 100
}
'HttpResponse<String> response = Unirest.post("https://api.privy.io/v1/wallets/{wallet_id}/transfer")
.header("privy-app-id", "<privy-app-id>")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"amount_type\": \"exact_input\",\n \"source\": {\n \"asset\": \"usdc\",\n \"amount\": \"10.5\",\n \"chain\": \"tempo\"\n },\n \"destination\": {\n \"asset\": \"ousd\",\n \"chain\": \"tempo\",\n \"address\": \"0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2\"\n },\n \"slippage_bps\": 100\n}")
.asString();const options = {
method: 'POST',
headers: {
'privy-app-id': '<privy-app-id>',
Authorization: 'Basic <encoded-value>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount_type: 'exact_input',
source: {asset: 'usdc', amount: '10.5', chain: 'tempo'},
destination: {
asset: 'ousd',
chain: 'tempo',
address: '0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2'
},
slippage_bps: 100
})
};
fetch('https://api.privy.io/v1/wallets/{wallet_id}/transfer', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.privy.io/v1/wallets/{wallet_id}/transfer",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'amount_type' => 'exact_input',
'source' => [
'asset' => 'usdc',
'amount' => '10.5',
'chain' => 'tempo'
],
'destination' => [
'asset' => 'ousd',
'chain' => 'tempo',
'address' => '0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2'
],
'slippage_bps' => 100
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"Content-Type: application/json",
"privy-app-id: <privy-app-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.privy.io/v1/wallets/{wallet_id}/transfer"
payload := strings.NewReader("{\n \"amount_type\": \"exact_input\",\n \"source\": {\n \"asset\": \"usdc\",\n \"amount\": \"10.5\",\n \"chain\": \"tempo\"\n },\n \"destination\": {\n \"asset\": \"ousd\",\n \"chain\": \"tempo\",\n \"address\": \"0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2\"\n },\n \"slippage_bps\": 100\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("privy-app-id", "<privy-app-id>")
req.Header.Add("Authorization", "Basic <encoded-value>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"wallet_id": "fmfdj6yqly31huorjqzq38zc",
"type": "transfer",
"source_asset": "ousd",
"source_amount": "10.5",
"source_chain": "tempo",
"destination_address": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2"
}/transfer endpoint will be
gas-sponsored by default. There is no need to specify
additional parameters for sponsorship.fee_configuration parameter to control
fee distribution between Privy and your app. Use the quote
endpoint to preview fees before executing a transfer.pending immediately. Replaying the same key
returns the cached response. On a synchronous 5xx, Privy deletes the record so the same key
retries fresh. Action outcomes (rejected, failed, succeeded) arrive via
webhooks and polling. Policy violations
always allow fresh retries.Authorizations
Basic Auth header with your app ID as the username and your app secret as the password.
Headers
ID of your Privy app.
Request authorization signature. If multiple signatures are required, they should be comma separated.
Request expiry. Value is a Unix timestamp in milliseconds representing the deadline by which the request must be processed.
Idempotency keys ensure API requests are executed only once within a 24-hour window.
Path Parameters
ID of the wallet.
Body
Request body for initiating a sponsored token transfer from an embedded wallet.
Source for a transfer identified by a named asset (e.g. "usdc", "eth"). Use this variant for first-class assets maintained by Privy.
- NamedTokenTransferSource
- CustomTokenTransferSource
Show child attributes
Show child attributes
{
"asset": "ousd",
"amount": "10.5",
"chain": "tempo"
}
The destination address for a token transfer. Optionally specify a different asset or chain for cross-asset or cross-chain transfers.
Show child attributes
Show child attributes
{
"address": "0xB00F0759DbeeF5E543Cc3E3B07A6442F5f3928a2"
}
Amount as a decimal string in the token's standard unit (e.g. "1.5" for 1.5 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.
100Whether the amount refers to the input token or output token.
exact_input, exact_output Maximum allowed slippage in basis points (1 bps = 0.01%). Only applicable for cross-chain or cross-asset transfers; omit to use the provider default.
0 <= x <= 10000Optional fee configuration for the transfer. If omitted, cross-chain transfers will not charge additional fees.
Show child attributes
Show child attributes
{ "type": "total_fee_bps", "value": 50 }
Unique caller-generated nonce used to prevent replaying a signed wallet action request. Must be at least 24 characters (e.g. a cuid2 or UUID).
24 - 255Developer-provided identifier for this request. Must be unique per app.
1 - 64Response
Transfer initiated successfully.
Response for a transfer action.
The ID of the wallet action.
The current status of the wallet action.
pending, succeeded, rejected, failed The ID of the wallet involved in the action.
ISO 8601 timestamp of when the wallet action was created.
transfer Chain name (e.g. "tempo", "base").
Recipient address.
Amount received on the destination chain. For exact_output cross-chain transfers, set at creation (the guaranteed exact amount). For exact_input cross-chain transfers, null until fill confirmation.
Developer-provided reference ID, if one was included in the request.
Top-level failure context for the wallet action. Present on rejected or failed actions when available.
Show child attributes
Show child attributes
The steps of the wallet action. Only returned if ?include=steps is provided.
A wallet action step consisting of an EVM transaction.
- EVMTransactionWalletActionStep
- EVMUserOperationWalletActionStep
- SVMTransactionWalletActionStep
- TVMTransactionWalletActionStep
- ExternalTransactionWalletActionStep
- CustodianTransactionWalletActionStep
Show child attributes
Show child attributes
Whether the amount refers to the input token or output token.
exact_input, exact_output Asset identifier (e.g. "usdc", "eth"). Present when the transfer was initiated with a named asset; omitted for custom-token transfers.
Token contract address (EVM) or mint address (Solana). Present when the transfer was initiated with asset_address.
Number of decimals for the transferred token. Present when the transfer was initiated with asset_address and the decimals were resolved on-chain.
Decimal amount sent on the source chain (e.g. "1.5"). For exact_output cross-chain transfers, null until fill confirmation.
Destination asset for cross-asset transfers. Omitted for same-asset transfers.
Destination chain for cross-chain transfers. Omitted for same-chain transfers.
Estimated fee breakdown from the provider quote. Only present for cross-chain or cross-asset transfers. Populated after on-chain confirmation.
Estimated fee paid to the relayer.
- RelayerFee
- PrivyFee
- DeveloperFee
Show child attributes
Show child attributes
{
"type": "privy",
"recipient": "0x1234567890abcdef1234567890abcdef12345678",
"amount": "0.20"
}
Estimated source-chain gas cost from the provider quote. Only present for cross-chain or cross-asset transfers. Populated after on-chain confirmation.
Show child attributes
Show child attributes
{
"base_amount": "100000000000000",
"amount": "0.0001",
"gas_asset": "ETH"
}
Actual fees paid for the transfer. Populated after on-chain confirmation. Only present for cross-chain transfers.
Estimated fee paid to the relayer.
- RelayerFee
- PrivyFee
- DeveloperFee
Show child attributes
Show child attributes
{
"type": "privy",
"recipient": "0x1234567890abcdef1234567890abcdef12345678",
"amount": "0.20"
}
Actual source-chain gas cost. Populated after on-chain confirmation. Only present for cross-chain transfers.
Show child attributes
Show child attributes
{
"base_amount": "100000000000000",
"amount": "0.0001",
"gas_asset": "ETH"
}
Was this page helpful?

