> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lightspark.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sending Payments

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

<Steps>
  <Step title="Get account IDs">
    Retrieve the internal account (source) and external account (destination) IDs:

    ```bash theme={null}
    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.
  </Step>

  <Step title="Initiate the transfer">
    Create the transfer by specifying the source and destination accounts:

    ```bash theme={null}
    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", "paymentRail": "ACH" },
        "amount": 12550
      }'
    ```

    <Tip>
      The `paymentRail` field is optional. If omitted, Grid selects a default rail for the destination.
    </Tip>

    ```json Success (201 Created) theme={null}
    {
      "id": "Transaction:019542f5-b3e7-1d02-0000-000000000015",
      "status": "PENDING",
      "type": "OUTGOING",
      "source": {
        "sourceType": "ACCOUNT",
        "accountId": "InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123"
      },
      "destination": {
        "destinationType": "ACCOUNT",
        "accountId": "ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965"
      },
      "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
    }
    ```

    <Info>
      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.
    </Info>
  </Step>

  <Step title="Track transfer status">
    The transaction is created with a `PENDING` status and progresses through `PROCESSING` to `COMPLETED` or `FAILED`. You'll receive `OUTGOING_PAYMENT.<STATUS>` webhooks as the transaction progresses. The webhook body contains the full transaction resource:

    ```json theme={null}
    {
      "type": "OUTGOING_PAYMENT.COMPLETED",
      "data": {
        "id": "Transaction:019542f5-b3e7-1d02-0000-000000000015",
        "status": "COMPLETED",
        "type": "OUTGOING",
        "sentAmount": { "amount": 12550, "currency": { "code": "USD", "decimals": 2 } },
        "receivedAmount": { "amount": 12550, "currency": { "code": "USD", "decimals": 2 } },
        "settledAt": "2025-10-03T15:02:30Z"
      },
      "timestamp": "2025-10-03T15:03:00Z"
    }
    ```

    If a transaction fails, Grid initiates a refund automatically. You'll receive `OUTGOING_PAYMENT.REFUND_PENDING` followed by `OUTGOING_PAYMENT.REFUND_COMPLETED` or `OUTGOING_PAYMENT.REFUND_FAILED`. The transaction's `refund` object tracks the refund status and reference.

    <Info>
      For the full state diagram, refund object details, and all webhook scenarios (including bank returns and manual cancellations), see the [Transaction Lifecycle](/platform-overview/core-concepts/transaction-lifecycle) guide.
    </Info>
  </Step>
</Steps>

## 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

<Steps>
  <Step title="Create a quote">
    Request a quote to lock in the exchange rate and get transfer details:

    ```bash theme={null}
    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"
      }'
    ```

    ```json Success (201 Created) theme={null}
    {
      "id": "Quote:019542f5-b3e7-1d02-0000-000000000025",
      "status": "PENDING",
      "createdAt": "2025-10-03T15:00:00Z",
      "expiresAt": "2025-10-03T15:15:00Z",
      "source": { "sourceType": "ACCOUNT", "accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965" },
      "destination": { "destinationType": "ACCOUNT", "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" },
      "sendingCurrency": { "code": "USD", "name": "United States Dollar", "symbol": "$", "decimals": 2 },
      "receivingCurrency": { "code": "EUR", "name": "Euro", "symbol": "€", "decimals": 2 },
      "totalSendingAmount": 10000,
      "totalReceivingAmount": 9200,
      "exchangeRate": 0.92,
      "feesIncluded": 50,
      "transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000030",
      "description": "Payment for services - Invoice #1234"
    }
    ```

    <Info>
      **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)
    </Info>

    <Accordion title="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:

      ```json theme={null}
      {
        "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)
    </Accordion>
  </Step>

  <Step title="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`)

    <Warning>
      Quote expiration depends on the corridor but is typically \~5 minutes or greater. If expired, create a new quote to get an updated exchange rate.
    </Warning>

    <Note>
      Quoted fees may fluctuate between quotes. Some underlying fee components
      are denominated in the receiving currency, so their equivalent in the
      sending currency moves with the FX rate. The fee shown in the quote is
      locked only for the lifetime of that quote — a new quote for the same
      transfer may return a different total.
    </Note>
  </Step>

  <Step title="Execute the quote">
    Confirm and execute the quote to initiate the transfer:

    ```bash theme={null}
    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"
    ```

    ```json Success (200 OK) theme={null}
    {
      "id": "Quote:019542f5-b3e7-1d02-0000-000000000025",
      "status": "PROCESSING",
      "createdAt": "2025-10-03T15:00:00Z",
      "expiresAt": "2025-10-03T15:15:00Z",
      "source": { "sourceType": "ACCOUNT", "accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965" },
      "destination": { "destinationType": "ACCOUNT", "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" },
      "sendingCurrency": { "code": "USD", "name": "United States Dollar", "symbol": "$", "decimals": 2 },
      "receivingCurrency": { "code": "EUR", "name": "Euro", "symbol": "€", "decimals": 2 },
      "totalSendingAmount": 10000,
      "totalReceivingAmount": 9200,
      "exchangeRate": 0.92,
      "feesIncluded": 50,
      "transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000030"
    }
    ```

    <Check>
      Once executed, the quote creates a transaction and the transfer begins processing. The `transactionId` can be used to track the payment.
    </Check>

    <Info>
      **Real-time funding sources:** If your quote uses a real-time funding source (USDC, BTC, RTP, or FedNow), you don't call the execute endpoint. Instead, send a payment to the account specified in the quote's `paymentInstructions`. Grid detects the deposit and processes the transfer automatically.
    </Info>
  </Step>

  <Step title="Monitor completion">
    After execution, a transaction is created and progresses through `PENDING` → `PROCESSING` → `COMPLETED` or `FAILED`. You'll receive `OUTGOING_PAYMENT.<STATUS>` webhooks as the transaction progresses. The webhook body contains the full transaction resource:

    ```json theme={null}
    {
      "type": "OUTGOING_PAYMENT.COMPLETED",
      "data": {
        "id": "Transaction:019542f5-b3e7-1d02-0000-000000000030",
        "status": "COMPLETED",
        "type": "OUTGOING",
        "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"
    }
    ```

    If a transaction fails, Grid initiates a refund automatically. You'll receive `OUTGOING_PAYMENT.REFUND_PENDING` followed by `OUTGOING_PAYMENT.REFUND_COMPLETED` or `OUTGOING_PAYMENT.REFUND_FAILED`. The transaction's `refund` object tracks the refund status and reference.

    <Info>
      For the full state diagram, refund object details, and all webhook scenarios (including bank returns and manual cancellations), see the [Transaction Lifecycle](/platform-overview/core-concepts/transaction-lifecycle) guide.
    </Info>
  </Step>
</Steps>

### 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:

```bash theme={null}
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"
    },
    "destination": { "destinationType": "ACCOUNT", "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" },
    "lockedCurrencySide": "SENDING",
    "lockedCurrencyAmount": 10000,
    "description": "Payment for services - Invoice #1234"
  }'
```

The response includes an array of payment instructions, including blockchain wallet addresses for USDC and invoices for BTC:

```json Success (201 Created) theme={null}
{
  "id": "Quote:019542f5-b3e7-1d02-0000-000000000025",
  "status": "PENDING",
  "createdAt": "2025-10-03T15:00:00Z",
  "expiresAt": "2025-10-03T15:15:00Z",
  "source": { "sourceType": "REALTIME_FUNDING", "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001", "currency": "USDC" },
  "destination": { "destinationType": "ACCOUNT", "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" },
  "sendingCurrency": { "code": "USDC", "name": "USD Coin", "symbol": "USDC", "decimals": 2 },
  "receivingCurrency": { "code": "EUR", "name": "Euro", "symbol": "€", "decimals": 2 },
  "totalSendingAmount": 10000,
  "totalReceivingAmount": 9200,
  "exchangeRate": 0.92,
  "feesIncluded": 50,
  "transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000030",
  "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:

<Steps>
  <Step title="Send USDC to the provided address">
    Transfer the exact amount of USDC specified in `totalSendingAmount` to your chosen blockchain wallet address.
  </Step>

  <Step title="Grid detects the deposit">
    Grid monitors the blockchain for incoming deposits. You'll receive an `INTERNAL_ACCOUNT.BALANCE_UPDATED` webhook when the deposit is confirmed:

    ```json theme={null}
    {
      "id": "Webhook:019542f5-b3e7-1d02-0000-000000000040",
      "type": "INTERNAL_ACCOUNT.BALANCE_UPDATED",
      "timestamp": "2025-10-03T15:05:00Z",
      "data": {
        "id": "InternalAccount:019542f5-b3e7-1d02-0000-000000000025",
        "balance": { "amount": 10000, "currency": { "code": "USDC", "decimals": 2 } }
      }
    }
    ```
  </Step>

  <Step title="Transfer executes automatically">
    Once the deposit is confirmed, Grid executes the cross-currency transfer. You'll receive `OUTGOING_PAYMENT.<STATUS>` webhooks as the transfer progresses:

    ```json theme={null}
    {
      "id": "Webhook:019542f5-b3e7-1d02-0000-000000000041",
      "type": "OUTGOING_PAYMENT.COMPLETED",
      "timestamp": "2025-10-03T15:31:00Z",
      "data": {
        "id": "Transaction:019542f5-b3e7-1d02-0000-000000000030",
        "status": "COMPLETED",
        "type": "OUTGOING",
        "sentAmount": { "amount": 10000, "currency": { "code": "USDC", "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"
      }
    }
    ```

    See the [Transaction Lifecycle](/platform-overview/core-concepts/transaction-lifecycle) guide for all possible status transitions and refund handling.
  </Step>
</Steps>

## Sending to an UMA Address

Send to an UMA address when the receiver is identified by their UMA handle, e.g., \$[alice@example.com](mailto:alice@example.com). You'll look up the receiver, create a quote, and then fund.

### Look up the recipient

```bash theme={null}
curl -X GET "https://api.lightspark.com/grid/2025-10-13/receiver/uma/\$recipient@example.com?customerId=Customer:019542f5-b3e7-1d02-0000-000000000001" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

#### Response

```json Success (200 OK) theme={null}
{
  "receiverUmaAddress": "$recipient@example.com",
  "lookupId": "Lookup:019542f5-b3e7-1d02-0000-000000000009",
  "supportedCurrencies": [
    {
      "currency": { "code": "EUR", "name": "Euro", "symbol": "€", "decimals": 2 },
      "estimatedExchangeRate": 0.92,
      "min": 100,
      "max": 10000000
    },
    {
      "currency": { "code": "BRL", "name": "Brazilian Real", "symbol": "R$", "decimals": 2 },
      "estimatedExchangeRate": 5.15,
      "min": 100,
      "max": 10000000
    }
  ],
  "requiredPayerDataFields": [
    { "name": "FULL_NAME", "mandatory": true },
    { "name": "BIRTH_DATE", "mandatory": true }
  ]
}
```

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

<CodeGroup>
  ```bash Just-in-time funding theme={null}
  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" }
    }'
  ```

  ```bash Prefunded (use internal account as source) theme={null}
  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": "ACCOUNT",
        "accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965"
      },
      "destination": {
        "destinationType": "UMA_ADDRESS",
        "umaAddress": "$recipient@example.com"
      },
      "lockedCurrencySide": "SENDING",
      "lockedCurrencyAmount": 10000,
      "description": "UMA payment from prefunded balance"
    }'
  ```
</CodeGroup>

### 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

```bash theme={null}
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:

```bash theme={null}
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"
```
