Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ledger.so/llms.txt

Use this file to discover all available pages before exploring further.

Create a transfer

Every transfer requires a walletId — the wallet you’re sending funds from. This can be a crypto wallet or a virtual account’s wallet.

From a crypto wallet

curl -X POST https://api.ledger.so/v1/transfers \
  -H "Authorization: Bearer $LEDGER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: transfer-1" \
  -d '{
    "customerId": "cus_...",
    "walletId": "wal_...",
    "amount": "10.00",
    "destinationCurrency": "usdc",
    "destinationPaymentRail": "solana",
    "destinationAddress": "7nwiVgP8..."
  }'
Response:
{
  "ok": true,
  "data": {
    "id": "txn_...",
    "customerId": "cus_...",
    "type": "transfer",
    "status": "in_review",
    "amount": "10.00",
    "fee": "0.03",
    "netAmount": "9.97",
    "sourceCurrency": "usdc",
    "destinationCurrency": "usdc",
    "destinationAddress": "7nwiVgP8...",
    "finalAmount": null,
    "destinationTxHash": null,
    "gasFee": null,
    "exchangeFee": null,
    "createdAt": 1710000000000,
    "updatedAt": 1710000000000
  }
}

From a virtual account wallet

When you create a virtual account, the response includes a walletId. Fiat deposited into the virtual account converts to stablecoins in that wallet. Use that walletId to transfer funds out.
curl -X POST https://api.ledger.so/v1/transfers \
  -H "Authorization: Bearer $LEDGER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: transfer-2" \
  -d '{
    "customerId": "cus_...",
    "walletId": "wal_...",
    "amount": "5.00",
    "destinationCurrency": "gbp",
    "destinationPaymentRail": "faster_payments",
    "destinationAddress": "pa_..."
  }'
Response:
{
  "ok": true,
  "data": {
    "id": "txn_...",
    "customerId": "cus_...",
    "type": "transfer",
    "status": "funds_received",
    "amount": "5.00",
    "fee": "0.15",
    "netAmount": "4.85",
    "sourceCurrency": "usdc",
    "destinationCurrency": "gbp",
    "payoutAccountId": "pa_...",
    "finalAmount": null,
    "exchangeFee": null,
    "createdAt": 1710000000000,
    "updatedAt": 1710000000000
  }
}
Virtual account wallets support both crypto and fiat destinations.

Request fields

FieldTypeRequiredDescription
customerIdstringYesLedger customer ID (cus_...)
walletIdstringYesWallet to transfer from (wal_...)
amountstring or numberYesAmount to send
destinationCurrencystringYesCurrency to deliver (e.g. usdc, gbp, eur, usd)
destinationPaymentRailstringYesDelivery rail (e.g. solana, ach, faster_payments, sepa)
destinationAddressstringYesOnchain address or payout account ID (pa_...)
referencestringNoPayment reference included with the fiat transfer (see limits below)
clientReferenceIdstringNoYour own reference ID (not sent to the recipient)

Reference limits by rail

The reference field is sent to the recipient’s bank. Character limits vary by rail:
RailMax LengthAllowed Characters
ach10A-Z, a-z, 0-9, spaces
wire140
sepa140
faster_payments
spei
pix

Response fields

Every transfer response includes:
FieldDescription
amountOriginal amount requested
feeLedger fee deducted
netAmountAmount sent to destination after fee
Additional fields vary by transfer type:
FieldCryptoFiatDescription
destinationAddressYesNoOnchain recipient address
payoutAccountIdNoYesPayout account receiving funds
destinationTxHashYesNoOnchain settlement transaction hash
gasFeeYesNoNetwork gas fee
finalAmountYesYesFinal amount delivered after fees/conversion
exchangeFeeYesYesExchange or conversion fee

Fees

Ledger charges a flat fee on all transfers, deducted from the source amount before sending:
Transfer typeFee
FX transfers (e.g. USDC → GBP, USDC → EUR)3%
Stablecoin / same-currency (e.g. USDC → USD, USDC → USDC)0.3%

Onchain vs fiat transfers

Destination RailTypeKYC Required
solana, ethereum, polygon, arbitrum, base, optimism, tronOnchain transferNo
ach, wire, sepa, faster_payments, spei, pixFiat transferYes
For fiat transfers, the customer must have completed KYC verification and have a payout account created first.

Tracking transfers

After creating a transfer, track its progress via:
  • GET /v1/transactions/{id} to poll the status
  • Subscribe to transaction.updated webhooks for real-time updates
For crypto transfers, the destinationTxHash field populates once settled onchain.