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

# Quickstart

> Complete walkthrough for buying Bitcoin and sending it as a reward to an external Spark wallet for self-custody

<img src="https://mintcdn.com/ramps/iSnT-NB4iMMUe72B/images/heroes/hero-quickstart-rewards-light.svg?fit=max&auto=format&n=iSnT-NB4iMMUe72B&q=85&s=d78507df3b766eb2d86b002435641255" alt="Rewards quickstart hero" className="page-hero block dark:hidden" width="928" height="400" data-path="images/heroes/hero-quickstart-rewards-light.svg" />

<img src="https://mintcdn.com/ramps/iSnT-NB4iMMUe72B/images/heroes/hero-quickstart-rewards-dark.svg?fit=max&auto=format&n=iSnT-NB4iMMUe72B&q=85&s=3895768e90e5df69724e47963fdf40a1" alt="Rewards quickstart hero" className="page-hero hidden dark:block" width="928" height="400" data-path="images/heroes/hero-quickstart-rewards-dark.svg" />

This guide walks you through the complete process of buying Bitcoin with USD and sending it to a self-custody Spark wallet, from customer onboarding through quote execution.

## Understanding Entity Mapping for Rewards

In this guide, the entities map as follows (platform-funded model):

| Entity Type          | Who They Are                             | In This Example                  |
| -------------------- | ---------------------------------------- | -------------------------------- |
| **Platform**         | Your rewards app paying rewards directly | Your cashback/rewards platform   |
| **Customer**         | (Not used in this model)                 | N/A                              |
| **External Account** | Users' crypto wallets receiving rewards  | User's self-custody Spark wallet |

**Flow**: Your platform funds its internal account → sends Bitcoin micro-payouts directly → to users' external crypto wallets at scale. This is common for cashback apps where you earn affiliate commissions and share them with users.

<Note>
  For white-label reward programs where brands like Nike or Starbucks fund their own reward campaigns, those brands would be created as **Customers** who manage their own reward budgets.
</Note>

## Prerequisites

Before starting this guide, ensure you have:

* A Grid API account with valid authentication credentials
* Access to the Grid API endpoints (production or sandbox)
* A webhook endpoint configured to receive notifications
* A Spark wallet address where the Bitcoin will be sent

## Overview

The process consists of the following steps:

1. **List platform internal accounts** to find your platform's USD funding instructions
2. **Fund your internal account** via ACH push and receive a webhook notification
3. **Generate a spark wallet** for your customer, or let them connect their own
4. **Register the destination wallet** as an external account
5. **Execute a quote** to complete the Bitcoin purchase and transfer a reward to the user's own Spark wallet.

## Step 1: List your platform's internal accounts

When your platform is first created, it is automatically assigned an internal account with a balance in your configured fiat currency.
List your platform's internal accounts to see the available balances and funding instructions for USD.

### Request

```bash theme={null}
curl -X GET "https://api.lightspark.com/grid/2025-10-13/platform/internal-accounts?currency=USD" \
  -H "Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

### Response

```json theme={null}
{
  "data": [
    {
      "id": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
      "balance": {
        "amount": 0,
        "currency": {
          "code": "USD",
          "name": "United States Dollar",
          "symbol": "$",
          "decimals": 2
        }
      },
      "fundingPaymentInstructions": [
        {
          "instructionsNotes": "Include the reference code in your ACH transfer memo",
          "accountOrWalletInfo": {
            "accountType": "US_ACCOUNT",
            "reference": "FUND-BTC123",
            "accountNumber": "9876543210",
            "routingNumber": "021000021",
            "accountHolderName": "Lightspark Payments FBO John Doe",
            "bankName": "JP Morgan Chase"
          }
        },
        { 
          "accountOrWalletInfo": {
            "accountType": "SPARK_WALLET",
            "assetType": "USDB",
            "address": "spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu",
            "invoice": "lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs"
          }
        },
        {
          "accountOrWalletInfo": {
            "accountType": "SOLANA_WALLET",
            "assetType": "USDC",
            "address": "4Nd1m6Qkq7RfKuE5vQ9qP9Tn6H94Ueqb4xXHzsAbd8Wg"
          }
        }
      ],
      "createdAt": "2025-10-03T12:00:00Z",
      "updatedAt": "2025-10-03T12:00:00Z"
    }
  ]
}
```

The `fundingPaymentInstructions` provide the bank account details and reference code needed to fund this internal account via ACH pull from the customer's bank.

<Note>
  You can also see that there are Spark wallet funding instructions in this
  example response which can be used to fund the internal account with USDB
  instantly.
</Note>

## Step 2: Fund your Internal Account

You can initiate an ACH transfer from your bank to the account details provided in the funding instructions, making sure to include the reference code `FUND-BTC123` in the transfer memo.

<Note>
  In sandbox mode, you can use the `/sandbox/internal-accounts/{accountId}/fund`
  endpoint to simulate receiving funds. In production, actual ACH transfers
  typically take 1-3 business days to settle.
</Note>

### Webhook Notification

When the funds are received and the internal account balance is updated, you'll receive a webhook notification:

```json theme={null}
{
  "id": "Webhook:019542f5-b3e7-1d02-0000-000000000020",
  "type": "INTERNAL_ACCOUNT.BALANCE_UPDATED",
  "timestamp": "2025-10-03T14:32:00Z",
  "data": {
    "id": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
    "type": "INTERNAL_FIAT",
    "status": "ACTIVE",
    "balance": {
      "amount": 200000,
      "currency": {
        "code": "USD",
        "name": "United States Dollar",
        "symbol": "$",
        "decimals": 2
      }
    },
    "fundingPaymentInstructions": [],
    "createdAt": "2025-10-03T12:00:00Z",
    "updatedAt": "2025-10-03T14:32:00Z"
  }
}
```

The internal account now has a balance of \$2,000.00 (200000 cents). You can use this balance to instantly distribute Bitcoin rewards to your customers.

## Step 3: Customer Onboarding

This guide assumes you have a Spark wallet address for your customer who will receive the Bitcoin reward.
For rewards, the only entity who needs to be KYB'd is the entity paying for the reward - in this case, you, the platform!
All you need in order to pay out a reward is the wallet address. No need to go through the full hosted KYC flow
for this use case! To generate a spark wallet, you can use a tool like [Privy](https://privy.io) or the Spark SDK directly.

## Step 4: Register the Destination Spark Wallet

Register the customer's Spark wallet as an external account.

### Request

```bash theme={null}
curl -X POST "https://api.lightspark.com/grid/2025-10-13/customers/external-accounts" \
  -H "Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
    "currency": "BTC",
    "accountInfo": {
      "accountType": "SPARK_WALLET",
      "address": "spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu"
    }
  }'
```

### Response

```json theme={null}
{
  "id": "ExternalAccount:b23dcbd6-dced-4ec4-b756-3c3a9ea3d456",
  "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
  "status": "ACTIVE",
  "currency": "BTC",
  "accountInfo": {
    "accountType": "SPARK_WALLET",
    "address": "spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu"
  }
}
```

## Step 5: Create and Execute a Quote to the Customer's Spark Wallet

Create and execute a trade from USD to BTC using the external account as the destination.

### Request

```bash theme={null}
curl -X POST "https://api.lightspark.com/grid/2025-10-13/quotes" \
  -H "Authorization: Basic $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:b23dcbd6-dced-4ec4-b756-3c3a9ea3d456"
    },
    "lockedCurrencySide": "SENDING",
    "lockedCurrencyAmount": 100,
    "immediatelyExecute": true,
    "description": "Bitcoin reward payout!"
  }'
```

<Note>
  **Immediate Quote Execution (Market Order)**: Note that `immediatelyExecute` is set to `true` in this example.
  Because we always just want to send \$1.00 worth of BTC to users as a reward at the current market rate, we don't
  need to lock a quote and view the rate details before executing. If you want to lock a quote and confirm fees
  and exchange rate details before executing the quote, set `immediatelyExecute` to `false` or omit the field.
</Note>

### Response

```json theme={null}
{
  "id": "Quote:019542f5-b3e7-1d02-0000-000000000020",
  "status": "PROCESSING",
  "createdAt": "2025-10-03T15:00:00Z",
  "expiresAt": "2025-10-03T15:05:00Z",
  "source": {
    "sourceType": "ACCOUNT",
    "accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965"
  },
  "destination": {
    "destinationType": "ACCOUNT",
    "accountId": "ExternalAccount:b23dcbd6-dced-4ec4-b756-3c3a9ea3d456"
  },
  "sendingCurrency": {
    "code": "USD",
    "name": "United States Dollar",
    "symbol": "$",
    "decimals": 2
  },
  "receivingCurrency": {
    "code": "BTC",
    "name": "Bitcoin",
    "symbol": "₿",
    "decimals": 8
  },
  "totalSendingAmount": 100,
  "totalReceivingAmount": 810,
  "exchangeRate": 8.1,
  "feesIncluded": 5,
  "transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000025"
}
```

The quote shows:

* **Sending**: \$1.00 USD (including \$0.05 fee)
* **Receiving**: 0.0000081 BTC (810 satoshis)
* **Exchange rate**: 8.1 sats per USD cent (\~\$123,000 per BTC)
  The quote status changes to `PROCESSING` and the Bitcoin transfer is initiated. USD is debited from the internal account, Bitcoin is purchased, and then sent to the Spark wallet address.

### Completion Webhook

When the Bitcoin transfer completes, you'll receive a webhook notification:

```json theme={null}
{
  "id": "Webhook:019542f5-b3e7-1d02-0000-000000000030",
  "type": "OUTGOING_PAYMENT.COMPLETED",
  "timestamp": "2025-10-03T15:02:00Z",
  "data": {
    "id": "Transaction:019542f5-b3e7-1d02-0000-000000000025",
    "status": "COMPLETED",
    "type": "OUTGOING",
    "sentAmount": {
      "amount": 100,
      "currency": {
        "code": "USD",
        "name": "United States Dollar",
        "symbol": "$",
        "decimals": 2
      }
    },
    "receivedAmount": {
      "amount": 810,
      "currency": {
        "code": "BTC",
        "name": "Bitcoin",
        "symbol": "₿",
        "decimals": 8
      }
    },
    "settledAt": "2025-10-03T15:01:45Z",
    "createdAt": "2025-10-03T15:00:00Z",
    "description": "Bitcoin purchase for self-custody",
    "exchangeRate": 8.1,
    "quoteId": "Quote:019542f5-b3e7-1d02-0000-000000000020"
  }
}
```

<Note>
  Bitcoin transfers to Spark wallets typically complete within seconds, much
  faster than traditional Bitcoin on-chain transactions.
</Note>

## Summary

You've successfully completed a Bitcoin purchase and transfer to a self-custody Spark wallet! Here's what happened:

1. ✅ Listed internal accounts and obtained USD funding instructions
2. ✅ Funded the internal account with USD via ACH
3. ✅ Generated a Spark wallet for the customer
4. ✅ Registered the destination Spark wallet as an external account
5. ✅ Created and executed a quote to purchase Bitcoin and send to the Spark wallet

The customer now has 810 Satoshis in their self-custody Spark wallet!

## Next Steps

* **Transaction history**: Use `GET /transactions` to track all Bitcoin purchases
* **Price monitoring**: Build price alerts using the lookup endpoint to monitor rates
* **Webhook verification**: Implement signature verification for webhook security (see [Webhooks guide](/rewards/platform-tools/webhooks))

## Related Resources

* [API Reference](/api-reference) - Complete API documentation
* [Platform Configuration](/rewards/developer-guides/platform-configuration) - Configure your platform settings
* [Webhooks](/rewards/platform-tools/webhooks) - Webhook security and verification
