> ## Documentation Index
> Fetch the complete documentation index at: https://ramps-sync-country-coverage-2026-09-21.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Sending Payments

Every payment goes through `POST /quotes`. What changes is where you are sending:

1. To an account — internal or external, with or without currency conversion
2. To an UMA address

## Choosing the right method

* **Account**: Pay an internal or external account. Grid converts when the currencies differ and settles over local payment rails (e.g., ACH, RTP, SEPA Instant, PIX, FPS) when they match. Also covers sending to a crypto wallet address when configured.
* **UMA**: Send using a Universal Money Address. Ideal for global counterparties on networks.

## Checking limits before you quote

Every corridor accepts amounts only within a range. You can read that range before you
create a quote, so an out-of-range amount surfaces in your own UI rather than as a
`400 AMOUNT_OUT_OF_RANGE` on `POST /quotes`.

Which endpoint you use depends on what you know:

| You know             | Use                                                                           | Bounds you get                                                                                             |
| -------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| A currency corridor  | `GET /exchange-rates`                                                         | `minSendingAmount` / `maxSendingAmount`, in the sending currency                                           |
| A specific recipient | `GET /receiver/external-account/{accountId}` or `GET /receiver/uma/{address}` | Per-currency `min` / `max` in the receiving currency, plus sending-side bounds where Grid can resolve them |

<Warning>
  These bounds are approximate. They are priced off a cached rate that refreshes about every
  five minutes, and only `POST /quotes` locks a rate and a final amount. Treat what you read
  here as a pre-flight check for your UI, not a guarantee that the quote will succeed.
</Warning>

### Across a corridor

Use the exchange rates endpoint when you know the currencies but not yet the recipient —
populating a currency picker, or validating an amount as the sender types it.

```bash theme={null}
curl -X GET 'https://api.lightspark.com/grid/2025-10-13/exchange-rates?sourceCurrency=USD&destinationCurrency=INR' \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

```json Success (200 OK) theme={null}
{
  "data": [
    {
      "sourceCurrency": { "code": "USD", "name": "US Dollar", "symbol": "$", "decimals": 2 },
      "sendingAmount": 10000,
      "minSendingAmount": 100,
      "maxSendingAmount": 10000000,
      "destinationCurrency": { "code": "INR", "name": "Indian Rupee", "symbol": "₹", "decimals": 2 },
      "destinationPaymentRail": "UPI",
      "receivingAmount": 825000,
      "exchangeRate": 0.012121,
      "fees": { "fixed": 100, "total": 150 },
      "updatedAt": "2025-02-05T12:00:00Z"
    }
  ]
}
```

`minSendingAmount` and `maxSendingAmount` are in the smallest unit of `sourceCurrency` — on
this corridor, \$1.00 to \$100,000.00.

Omit `destinationCurrency` to get every corridor available from a source currency, each with
its own bounds and rail. Repeat the parameter to compare a few:
`?sourceCurrency=USD&destinationCurrency=INR&destinationCurrency=GBP`.

<Tip>
  Pass `sendingAmount` to price a specific amount. `fees.total` varies with the amount sent,
  so the default (`10000`) is only representative.
</Tip>

### For a specific recipient

Once you have a destination, look it up. The lookup prices the corridor against that
particular recipient and returns a `lookupId` you can carry into the quote.

```bash theme={null}
curl -X GET 'https://api.lightspark.com/grid/2025-10-13/receiver/external-account/ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965?customerId=Customer:019542f5-b3e7-1d02-0000-000000000001&sendingCurrency=USD' \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

```json Success (200 OK) theme={null}
{
  "accountId": "ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
  "lookupId": "Lookup:019542f5-b3e7-1d02-0000-000000000009",
  "sendingCurrency": { "code": "USD", "name": "United States Dollar", "symbol": "$", "decimals": 2 },
  "supportedCurrencies": [
    {
      "currency": { "code": "MXN", "name": "Mexican Peso", "symbol": "$", "decimals": 2 },
      "estimatedExchangeRate": 18.5,
      "min": 2000,
      "max": 185000000,
      "minSendingAmount": 109,
      "maxSendingAmount": 10000000
    }
  ],
  "requiredPayerDataFields": [
    { "name": "FULL_NAME", "mandatory": true }
  ]
}
```

Each entry carries bounds on both sides of the conversion. `min` and `max` are in the
smallest unit of that entry's `currency` — here MX\$20.00 to MX\$1,850,000.00.
`minSendingAmount` and `maxSendingAmount` are in the smallest unit of the response's
`sendingCurrency` — \$1.09 to \$100,000.00 — which is the pair you want when your UI collects
an amount in the sender's currency.

Pass `sendingCurrency` when your customer holds more than one currency. Without it the
bounds are priced against the customer's default currency, which may not be the one they
intend to send from.

`GET /receiver/uma/{address}` returns the same shape for a UMA recipient, with
`receiverUmaAddress` in place of `accountId`. A UMA recipient commonly supports several
currencies, so expect more than one entry in `supportedCurrencies`, each with its own bounds.

<Info>
  `minSendingAmount` and `maxSendingAmount` are omitted when Grid cannot resolve a
  sending-side bound for that currency. Fall back to dividing `min` and `max` by
  `estimatedExchangeRate`, and treat the result as looser than the real limit — the sending
  leg can impose a bound of its own that the converted receiving bound doesn't reflect.
</Info>

Reuse the `lookupId` on `POST /quotes` to price against the same lookup. It is required for
UMA destinations.

<Note>
  Clearing these bounds doesn't guarantee the quote succeeds. Cumulative limits are enforced
  at quote time and surface separately as `DAILY_VOLUME_LIMIT_EXCEEDED` (HTTP 429), and a
  per-transaction ceiling can surface as `TRANSACTION_SIZE_LIMIT_EXCEEDED`. Handle both
  alongside `AMOUNT_OUT_OF_RANGE`.
</Note>

## Sending to an Account

Every payment to an internal or external account goes through `POST /quotes`, whether or not
the currencies differ. The quote prices the transfer — amounts, fees, and, when converting,
a locked exchange rate — and creates the transaction that carries the money.

What varies is when you execute it:

* **In one request.** Set `immediatelyExecute` and Grid creates and executes the quote
  together. Use this when you don't need to put rate or fee details in front of your user
  before the money moves.
* **In two steps.** Create the quote, show your user what the transfer will cost, then call
  execute before the quote expires. Use this whenever your UX surfaces rates or fees — which
  includes same-currency transfers, where there is no exchange rate but there can still be
  fees worth showing.

### 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", "paymentRail": "ACH" },
        "lockedCurrencySide": "SENDING",
        "lockedCurrencyAmount": 10000,
        "remittanceInformation": "INV-12345",
        "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,
      "platformFeesIncluded": 0,
      "transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000030",
      "description": "Payment for services - Invoice #1234"
    }
    ```

    <Info>
      **Same-currency transfers use this exact request.** The two currencies simply match, and
      the quote comes back with an `exchangeRate` of `1` — the fee fields are still populated.
      Add `"immediatelyExecute": true` to create and execute in this one request and skip the
      next two steps.
    </Info>

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

    <Tip>
      The `paymentRail` field is optional. If omitted, Grid selects a default rail for the destination. Specify a rail (e.g., `ACH`, `WIRE`, `RTP`, `FEDNOW`) when you need to control which payment network processes the transfer.
    </Tip>

    <Info>
      `remittanceInformation` is optional. Use it to send a reference that travels with the payment to the recipient (max 80 characters). This populates the ACH Addenda record, FedNow/RTP remittance information, or wire OBI field depending on the payment rail.
    </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
      * `FAMILY_SUPPORT` - Family support or remittance
      * `SALARY_PAYMENT` - Salary or wage payment
      * `OTHER` - Other purpose (may require additional documentation)
    </Accordion>
  </Step>

  <Step title="Review quote details">
    Skip this step and the next by setting `immediatelyExecute` on the quote. Otherwise,
    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,
      "platformFeesIncluded": 0,
      "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",
        "direction": "DEBIT",
        "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

Transfers can be funded 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             |
| Ethereum           | USDC, USDT       |
| Plasma             | USDT             |
| Arbitrum           | USDC, USDT       |
| 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,
  "platformFeesIncluded": 0,
  "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 } },
        "totalBalance": { "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",
        "direction": "DEBIT",
        "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"
```

## Strong Customer Authentication (EU customers)

Customers in SCA-regulated regions (in practice the EU: EUR / USDC) must confirm
payments with Strong Customer Authentication. When it applies, the quote comes
back `PENDING_AUTHORIZATION` carrying an `scaChallenge` that you authorize
before the transfer is released; for every other customer nothing changes. See
[Per-transaction authorization](/platform-overview/sca/per-transaction-authorization)
for the full walkthrough.
