Skip to main content
This guide covers three methods to send payments:
  1. Same-currency transfer to an external account
  2. Cross-currency transfer with a quote
  3. Sending to a 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

1

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.
2

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
  }'
Success (201 Created)
{
  "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.
3

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 to EUR, MXN, BRL, or other supported currencies
  • Sending international payments with automatic currency conversion
  • Need to lock in a specific exchange rate for the transfer

Create and execute a quote

1

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": { "accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965" },
    "destination": { "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123", "currency": "EUR" },
    "lockedCurrencySide": "SENDING",
    "lockedCurrencyAmount": 10000,
    "description": "Payment for services - Invoice #1234"
  }'
Success (201 Created)
{
  "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)
2

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.
3

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"
Success (200 OK)
{
  "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.
4

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"
}

Sending to a UMA Address

Send to a 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

Success (200 OK)
{
  "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 senderUserInfo (applies to either tab).

Create a quote

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",
    "sendingCurrencyCode": "USD",
    "receivingCurrencyCode": "EUR",
    "lockedCurrencySide": "SENDING",
    "lockedCurrencyAmount": 10000,
    "description": "Invoice #1234 payment",
    "senderUserInfo": { "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"
I