> ## Documentation Index
> Fetch the complete documentation index at: https://ramps-04-30-docs-add-grid-tutorial-skill-interactive-zero-t.mintlify.site/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" },
        "amount": 12550
      }'
    ```

    ```json Success (201 Created) theme={null}
    {
      "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
    }
    ```

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

    <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>
  </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",
      "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"
    }
    ```

    <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",
  "source": { "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001", "currency": "USDC" },
  "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:

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

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

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

    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/\$recipient@example.com?platformUserId=9f84e0c2a72c4fa" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

#### Response

```json Success (200 OK) theme={null}
{
  "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

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