This guide covers three methods to send payments:
Same-currency transfer to an external account
Cross-currency transfer with a quote
Sending to an UMA address
Choosing the right method
Same-currency : Best for domestic payouts when sender and recipient use the same currency. Uses local payment rails (e.g., RTP, SEPA Instant, PIX, FPS) for low cost and fast settlement.
Cross-currency : Use when conversion is required or when paying globally across borders. Also supports sending to a crypto wallet address when configured.
UMA : Send using a Universal Money Address. Ideal for global counterparties on networks.
Same-Currency Transfers
Use the /transfer-out endpoint when sending funds in the same currency (no exchange rate needed). This is the simplest and fastest option for domestic transfers.
When to use same-currency transfers
Transferring USD from a USD internal account to a USD external account
Sending funds within the same country using the same payment rail
No currency conversion is required
Create a transfer
Get account IDs
Retrieve the internal account (source) and external account (destination) IDs: curl -X GET 'https://api.lightspark.com/grid/2025-10-13/customers/internal-accounts?customerId=Customer:019542f5-b3e7-1d02-0000-000000000001' \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET "
Note the id fields from both the internal and external accounts you want to use.
Initiate the transfer
Create the transfer by specifying the source and destination accounts: curl -X POST 'https://api.lightspark.com/grid/2025-10-13/transfer-out' \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET " \
-H 'Content-Type: application/json' \
-d '{
"source": { "accountId": "InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" },
"destination": { "accountId": "ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965" },
"amount": 12550
}'
{
"id" : "Transaction:019542f5-b3e7-1d02-0000-000000000015" ,
"status" : "PENDING" ,
"type" : "OUTGOING" ,
"source" : {
"accountId" : "InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" ,
"currency" : "USD"
},
"destination" : {
"accountId" : "ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965" ,
"currency" : "USD"
},
"sentAmount" : { "amount" : 12550 , "currency" : { "code" : "USD" , "decimals" : 2 } },
"receivedAmount" : { "amount" : 12550 , "currency" : { "code" : "USD" , "decimals" : 2 } },
"customerId" : "Customer:019542f5-b3e7-1d02-0000-000000000001" ,
"platformCustomerId" : "customer_12345" ,
"createdAt" : "2025-10-03T15:00:00Z" ,
"settledAt" : null
}
The amount is specified in the smallest unit of the currency (cents for USD, pence for GBP, etc.). For example, 12550 represents $125.50 USD.
Track transfer status
The transaction is created with a PENDING status. Monitor the status by: Option 1: Webhook notifications (recommended){
"type" : "OUTGOING_PAYMENT" ,
"transaction" : {
"id" : "Transaction:019542f5-b3e7-1d02-0000-000000000015" ,
"status" : "COMPLETED" ,
"settledAt" : "2025-10-03T15:02:30Z"
},
"timestamp" : "2025-10-03T15:03:00Z"
}
Option 2: Poll the transaction endpoint curl -X GET 'https://api.lightspark.com/grid/2025-10-13/transactions/Transaction:019542f5-b3e7-1d02-0000-000000000015' \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET "
When the transaction status changes to COMPLETED, the funds have been successfully transferred to the external account.
Cross-Currency Transfers
Use the quotes flow when sending funds with currency conversion. This locks in an exchange rate and provides all details needed to execute the transfer.
When to use cross-currency transfers
Converting USD, USDC, USDT to EUR, MXN, BRL, BTC, or other supported fiat and crypto currencies
Sending international payments with automatic currency conversion
Need to lock in a specific exchange rate for the transfer
Create and execute a quote
Create a quote
Request a quote to lock in the exchange rate and get transfer details: curl -X POST 'https://api.lightspark.com/grid/2025-10-13/quotes' \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET " \
-H 'Content-Type: application/json' \
-d '{
"source": { "sourceType": "ACCOUNT", "accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965" },
"destination": { "destinationType": "ACCOUNT", "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" },
"lockedCurrencySide": "SENDING",
"lockedCurrencyAmount": 10000,
"description": "Payment for services - Invoice #1234"
}'
{
"id" : "Quote:019542f5-b3e7-1d02-0000-000000000025" ,
"status" : "PENDING" ,
"source" : { "accountId" : "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965" , "currency" : "USD" },
"destination" : { "accountId" : "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" , "currency" : "EUR" },
"sendingAmount" : { "amount" : 10000 , "currency" : { "code" : "USD" , "decimals" : 2 } },
"receivingAmount" : { "amount" : 9200 , "currency" : { "code" : "EUR" , "decimals" : 2 } },
"exchangeRate" : 0.92 ,
"fee" : { "amount" : 50 , "currency" : { "code" : "USD" , "decimals" : 2 } },
"expiresAt" : "2025-10-03T15:15:00Z" ,
"createdAt" : "2025-10-03T15:00:00Z" ,
"description" : "Payment for services - Invoice #1234"
}
Locked currency side determines which amount is fixed:
SENDING: Lock the sending amount (receiving amount calculated based on exchange rate)
RECEIVING: Lock the receiving amount (sending amount calculated based on exchange rate)
Including purpose of payment
For external account or UMA destinations, some payment corridors require a purpose of payment. Include the purposeOfPayment field in the quote request: {
"source" : { "sourceType" : "ACCOUNT" , "accountId" : "InternalAccount:..." },
"destination" : { "destinationType" : "ACCOUNT" , "accountId" : "ExternalAccount:..." },
"lockedCurrencySide" : "SENDING" ,
"lockedCurrencyAmount" : 10000 ,
"purposeOfPayment" : "GOODS_OR_SERVICES"
}
Purpose of payment codes:
GIFT - Personal gift
SELF - Transfer to yourself
GOODS_OR_SERVICES - Payment for goods or services
EDUCATION - Education-related expenses
HEALTH_OR_MEDICAL - Medical or healthcare expenses
REAL_ESTATE_PURCHASE - Real estate transaction
TAX_PAYMENT - Tax payment
LOAN_PAYMENT - Loan repayment
UTILITY_BILL - Utility bill payment
DONATION - Charitable donation
TRAVEL - Travel-related expenses
OTHER - Other purpose (may require additional documentation)
Review quote details
Before executing, review the quote to ensure:
Exchange rate is acceptable
Fees are as expected
Receiving amount meets requirements
Quote hasn’t expired (check expiresAt)
Quotes typically expire after a short period. If expired, create a new quote to get an updated exchange rate.
Execute the quote
Confirm and execute the quote to initiate the transfer: curl -X POST 'https://api.lightspark.com/grid/2025-10-13/quotes/Quote:019542f5-b3e7-1d02-0000-000000000025/execute' \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET "
{
"id" : "Quote:019542f5-b3e7-1d02-0000-000000000025" ,
"status" : "PROCESSING" ,
"transactionId" : "Transaction:019542f5-b3e7-1d02-0000-000000000030" ,
"source" : { "accountId" : "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965" , "currency" : "USD" },
"destination" : { "accountId" : "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" , "currency" : "EUR" },
"sendingAmount" : { "amount" : 10000 , "currency" : { "code" : "USD" , "decimals" : 2 } },
"receivingAmount" : { "amount" : 9200 , "currency" : { "code" : "EUR" , "decimals" : 2 } },
"exchangeRate" : 0.92 ,
"executedAt" : "2025-10-03T15:05:00Z"
}
Once executed, the quote creates a transaction and the transfer begins processing. The transactionId can be used to track the payment.
Monitor completion
Track the transfer using webhooks or by polling the transaction: curl -X GET 'https://api.lightspark.com/grid/2025-10-13/transactions/Transaction:019542f5-b3e7-1d02-0000-000000000030' \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET "
You’ll receive a webhook when the transaction completes: {
"type" : "OUTGOING_PAYMENT" ,
"transaction" : {
"id" : "Transaction:019542f5-b3e7-1d02-0000-000000000030" ,
"status" : "COMPLETED" ,
"sentAmount" : { "amount" : 10000 , "currency" : { "code" : "USD" , "decimals" : 2 } },
"receivedAmount" : { "amount" : 9200 , "currency" : { "code" : "EUR" , "decimals" : 2 } },
"exchangeRate" : 0.92 ,
"settledAt" : "2025-10-03T15:30:00Z" ,
"quoteId" : "Quote:019542f5-b3e7-1d02-0000-000000000025"
},
"timestamp" : "2025-10-03T15:31:00Z"
}
Funding with cryptocurrencies
Cross-currency transfers support funding via USDC and BTC on popular blockchains including Solana, Base, Lightning and Spark. When you create a quote specifying the source currency as USDC or BTC, the response includes payment instructions for multiple funding options.
Supported blockchains
Blockchain Network Cryptocurrencies Solana USDC Base USDC Tron USDT Polygon USDC Lightning BTC Spark BTC
Create a quote for USDC-funded transfer
Request a quote that provides blockchain funding options:
curl -X POST 'https://api.lightspark.com/grid/2025-10-13/quotes' \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET " \
-H 'Content-Type: application/json' \
-d '{
"source": {
"sourceType": "REALTIME_FUNDING",
"customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
"currency": "USDC",
"cryptoNetwork": "SOLANA_MAINNET"
},
"destination": { "destinationType": "ACCOUNT", "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" },
"lockedCurrencySide": "SENDING",
"lockedCurrencyAmount": 10000,
"description": "Payment for services - Invoice #1234"
}'
The cryptoNetwork field is required when the source currency is a stablecoin (USDC, USDT). It specifies which blockchain network the customer will deposit on, so the correct deposit address can be generated. Example values: SOLANA_MAINNET, BASE_MAINNET, ETHEREUM_MAINNET.
The response includes an array of payment instructions, including blockchain wallet addresses for USDC and invoices for BTC:
{
"id" : "Quote:019542f5-b3e7-1d02-0000-000000000025" ,
"status" : "PENDING" ,
"source" : { "customerId" : "Customer:019542f5-b3e7-1d02-0000-000000000001" , "currency" : "USDC" , "cryptoNetwork" : "SOLANA_MAINNET" },
"destination" : { "accountId" : "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" , "currency" : "EUR" },
"sendingAmount" : { "amount" : 10000 , "currency" : { "code" : "USDC" , "decimals" : 2 } },
"receivingAmount" : { "amount" : 9200 , "currency" : { "code" : "EUR" , "decimals" : 2 } },
"exchangeRate" : 0.92 ,
"fee" : { "amount" : 50 , "currency" : { "code" : "USD" , "decimals" : 2 } },
"expiresAt" : "2025-10-03T15:15:00Z" ,
"createdAt" : "2025-10-03T15:00:00Z" ,
"paymentInstructions" : [
{
"accountOrWalletInfo" : {
"accountType" : "SOLANA_WALLET" ,
"assetType" : "USDC" ,
"address" : "4Nd1m6Qkq7RfKuE5vQ9qP9Tn6H94Ueqb4xXHzsAbd8Wg"
}
},
{
"accountOrWalletInfo" : {
"accountType" : "BASE_WALLET" ,
"assetType" : "USDC" ,
"address" : "0x1234567890abcdef1234567890abcdef12345678"
}
}
]
}
Transaction processing
Grid automatically detects blockchain deposits and processes the transfer once funds are received:
Send USDC to the provided address
Transfer the exact amount of USDC specified in sendingAmount to your chosen blockchain wallet address.
Grid detects the deposit
Grid monitors the blockchain for incoming deposits. You’ll receive an ACCOUNT_STATUS webhook when the deposit is confirmed: {
"type" : "ACCOUNT_STATUS" ,
"accountId" : "InternalAccount:019542f5-b3e7-1d02-0000-000000000025" ,
"oldBalance" : { "amount" : 0 , "currency" : { "code" : "USDC" , "decimals" : 2 } },
"newBalance" : { "amount" : 10000 , "currency" : { "code" : "USDC" , "decimals" : 2 } },
"timestamp" : "2025-10-03T15:05:00Z"
}
Transfer executes automatically
Once the deposit is confirmed, Grid executes the cross-currency transfer. You’ll receive OUTGOING_PAYMENT webhooks as the transfer progresses and completes: {
"type" : "OUTGOING_PAYMENT" ,
"transaction" : {
"id" : "Transaction:019542f5-b3e7-1d02-0000-000000000030" ,
"status" : "COMPLETED" ,
"sentAmount" : { "amount" : 10000 , "currency" : { "code" : "USD" , "decimals" : 2 } },
"receivedAmount" : { "amount" : 9200 , "currency" : { "code" : "EUR" , "decimals" : 2 } },
"exchangeRate" : 0.92 ,
"settledAt" : "2025-10-03T15:30:00Z" ,
"quoteId" : "Quote:019542f5-b3e7-1d02-0000-000000000025"
},
"timestamp" : "2025-10-03T15:31:00Z"
}
Sending to an UMA Address
Send to an UMA address when the receiver is identified by their UMA handle eg $alice@example.com . You’ll look up the receiver, create a quote, and then fund.
Look up the recipient
curl -X GET "https://api.lightspark.com/grid/2025-10-13/receiver/ \$ recipient@example.com?platformUserId=9f84e0c2a72c4fa" \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET "
Response
{
"id" : "Lookup:019542f5-b3e7-1d02-0000-000000000009" ,
"receiver" : {
"handle" : "$recipient@example.com" ,
"vaspName" : "ExampleBank" ,
"network" : "UMA"
},
"supportedCurrencies" : [
{ "code" : "EUR" , "decimals" : 2 },
{ "code" : "BRL" , "decimals" : 2 }
],
"requiredPayerFields" : [
"FULL_NAME" ,
"BIRTH_DATE"
],
"constraints" : {
"minAmount" : { "amount" : 100 , "currency" : { "code" : "USD" , "decimals" : 2 } },
"maxAmount" : { "amount" : 10000000 , "currency" : { "code" : "USD" , "decimals" : 2 } }
},
"createdAt" : "2025-10-03T15:00:00Z"
}
The response includes supported currencies and any required payer information fields.
If the receiver’s VASP requires payer data, include it in senderCustomerInfo (applies to either tab).
Create a quote
Just-in-time funding
Prefunded (use internal account as source)
curl -X POST "https://api.lightspark.com/grid/2025-10-13/quotes" \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET " \
-H "Content-Type: application/json" \
-d '{
"lookupId": "Lookup:019542f5-b3e7-1d02-0000-000000000009",
"source": {
"sourceType": "REALTIME_FUNDING",
"currency": "USD"
},
"destination": {
"destinationType": "UMA_ADDRESS",
"umaAddress": "$recipient@example.com"
},
"lockedCurrencySide": "SENDING",
"lockedCurrencyAmount": 10000,
"description": "Invoice #1234 payment",
"senderCustomerInfo": { "FULL_NAME": "John Sender", "BIRTH_DATE": "1985-06-15" }
}'
Execute payment (just-in-time)
Use the paymentInstructions from the quote to instruct your bank to push funds. Include the exact reference provided.
Execute payment (prefunded)
Existing internal account balances will be used to fund the payment. Use the lookup Id above to confirm the payment and execute the quote.
Execute the quote
curl -X POST "https://api.lightspark.com/grid/2025-10-13/quotes/Quote:019542f5-b3e7-1d02-0000-000000000025/execute" \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET "
Executing the quote creates a transaction that draws from your internal account and delivers to the recipient associated with the UMA address.
Track status
Listen for OUTGOING_PAYMENT webhooks until the transaction reaches COMPLETED or FAILED.
You can also query for the transaction with the following snippet:
curl -X GET "https://api.lightspark.com/grid/2025-10-13/transactions/Transaction:019542f5-b3e7-1d02-0000-000000000030" \
-u " $GRID_CLIENT_ID : $GRID_CLIENT_SECRET "