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:write permission

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 submit
HttpRequest 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.