Transfer Tokens
Send tokens between accounts using SDP's payment orchestration.
SDP handles token transfers through its payments API. Transfers move tokens from a source account to a destination address.
Transfers are available through the Payments dashboard and the API.
Prerequisites
- A deployed token with minted supply
- A wallet with signing configured
- The
payments:writepermission
Execute mode
curl -X POST https://api.solana.com/v1/payments/transfers \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: transfer-001" \
-d '{
"source": "3xYZa...2aBc",
"destination": "7xKXz...9fGh",
"token": "9aBCd...4eEf",
"amount": "500000",
"memo": "Payment for invoice #1234"
}'const response = await fetch(
"https://api.solana.com/v1/payments/transfers",
{
method: "POST",
headers: {
"Authorization": "Bearer sk_test_...",
"Content-Type": "application/json",
"Idempotency-Key": "transfer-001",
},
body: JSON.stringify({
source: "3xYZa...2aBc",
destination: "7xKXz...9fGh",
token: "9aBCd...4eEf",
amount: "500000",
memo: "Payment for invoice #1234",
}),
}
);
const { data } = await response.json();HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.solana.com/v1/payments/transfers"))
.header("Authorization", "Bearer sk_test_...")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "transfer-001")
.POST(HttpRequest.BodyPublishers.ofString("""
{
"source": "3xYZa...2aBc",
"destination": "7xKXz...9fGh",
"token": "9aBCd...4eEf",
"amount": "500000",
"memo": "Payment for invoice #1234"
}"""))
.build();Prepare mode
curl -X POST https://api.solana.com/v1/payments/transfers/prepare \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"source": "3xYZa...2aBc",
"destination": "7xKXz...9fGh",
"token": "9aBCd...4eEf",
"amount": "500000",
"memo": "Payment for invoice #1234",
"options": { "simulate": true }
}'const response = await fetch(
"https://api.solana.com/v1/payments/transfers/prepare",
{
method: "POST",
headers: {
"Authorization": "Bearer sk_test_...",
"Content-Type": "application/json",
},
body: JSON.stringify({
source: "3xYZa...2aBc",
destination: "7xKXz...9fGh",
token: "9aBCd...4eEf",
amount: "500000",
memo: "Payment for invoice #1234",
options: { simulate: true },
}),
}
);
const { data } = await response.json();
// data.preparedTransaction.serialized — sign and submitHttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.solana.com/v1/payments/transfers/prepare"))
.header("Authorization", "Bearer sk_test_...")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("""
{
"source": "3xYZa...2aBc",
"destination": "7xKXz...9fGh",
"token": "9aBCd...4eEf",
"amount": "500000",
"memo": "Payment for invoice #1234",
"options": { "simulate": true }
}"""))
.build();See Prepare vs Execute for guidance on which mode to use.
Idempotency
Always include an Idempotency-Key header on transfer requests. If a network error occurs, retrying with the same key ensures the transfer is only executed once.
Related guides
- Mint and Burn — create or destroy token supply
- Manage Allowlists — define approved destinations for allowlist-enabled issuance flows
- Freeze and Compliance — halt transfers for compliance