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

# Account Model

> Internal accounts, external accounts, and how they work together

Grid uses two types of accounts: **internal accounts** (Grid-managed balances) and **external accounts** (connected bank accounts and wallets). Understanding when to use each type is key to building efficient payment flows.

## Internal Accounts

Internal accounts are Lightspark managed accounts that hold funds within the Grid platform. They allow you to receive deposits and send payments to external bank accounts or other payment destinations.

They are useful for holding funds on behalf or the platform or customers which will be used for instant, 24/7 quotes and transfers out of the system.

Internal accounts are created for both:

* **Platform-level accounts**: Hold pooled funds for your platform operations (rewards distribution, reconciliation, etc.)
* **Customer accounts**: Hold individual customer funds for their transactions

<Info>
  Internal accounts are automatically created when you onboard a customer, based
  on your platform's currency configuration. Platform-level internal accounts
  are created when you configure your platform with supported currencies.
</Info>

## How internal accounts work

Internal accounts act as an intermediary holding account in the payment flow:

1. **Deposit funds**: You or your customers deposit money into internal accounts using bank transfers (ACH, wire, PIX, etc.) or crypto transfers
2. **Hold balance**: Funds are held securely in the internal account until needed
3. **Send payments**: You initiate transfers from internal accounts to external destinations

Each internal account:

* Is denominated in a single currency (USD, EUR, etc.)
* Has a unique balance that you can query at any time
* Includes unique payment instructions for depositing funds
* Supports multiple funding methods depending on the currency

## Retrieving internal accounts

### List customer internal accounts

To retrieve all internal accounts for a specific customer, use the customer ID to filter the results:

```bash Request internal accounts for a customer 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"
```

<Accordion title="Response">
  ```json theme={null}
  {
    "data": [
      {
        "id": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
        "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
        "type": "INTERNAL_FIAT",
        "status": "ACTIVE",
        "balance": {
          "amount": 50000,
          "currency": {
            "code": "USD",
            "name": "United States Dollar",
            "symbol": "$",
            "decimals": 2
          }
        },
        "fundingPaymentInstructions": [
          {
            "instructionsNotes": "Include the reference code in your ACH transfer memo",
            "accountOrWalletInfo": {
              "reference": "FUND-ABC123",
              "accountType": "USD_ACCOUNT",
              "accountNumber": "9876543210",
              "routingNumber": "021000021",
              "accountHolderName": "Lightspark Payments FBO John Doe",
              "bankName": "JP Morgan Chase"
            }
          },
          {
            "accountOrWalletInfo": {
              "accountType": "SOLANA_WALLET",
              "assetType": "USDC",
              "address": "4Nd1m6Qkq7RfKuE5vQ9qP9Tn6H94Ueqb4xXHzsAbd8Wg"
            }
          }
        ],
        "createdAt": "2025-10-03T12:00:00Z",
        "updatedAt": "2025-10-03T14:30:00Z"
      }
    ],
    "hasMore": false,
    "totalCount": 1
  }
  ```
</Accordion>

### Filter by currency

You can filter internal accounts by currency to find accounts for specific denominations:

```bash theme={null}
curl -X GET 'https://api.lightspark.com/grid/2025-10-13/customers/internal-accounts?customerId=Customer:019542f5-b3e7-1d02-0000-000000000001&currency=USD' \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

### List platform internal accounts

To retrieve platform-level internal accounts (not tied to individual customers), use the platform internal accounts endpoint:

```bash theme={null}
curl -X GET 'https://api.lightspark.com/grid/2025-10-13/platform/internal-accounts' \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

<Info>
  Platform internal accounts are useful for managing pooled funds, distributing
  rewards, or handling platform-level operations.
</Info>

## Understanding funding payment instructions

Each internal account includes `fundingPaymentInstructions` that tell your customers how to deposit funds. The structure varies by payment rail and currency:

<AccordionGroup>
  <Accordion title="US ACH or wire transfers">
    For USD accounts, instructions include routing and account numbers:

    ```json theme={null}
    {
      "instructionsNotes": "Include the reference code in your ACH transfer memo",
      "accountOrWalletInfo": {
        "accountType": "USD_ACCOUNT",
        "reference": "FUND-ABC123",
        "accountNumber": "9876543210",
        "routingNumber": "021000021",
        "accountHolderName": "Lightspark Payments FBO John Doe",
        "bankName": "JP Morgan Chase"
      }
    }
    ```

    <Tip>
      Each internal account has unique banking details in the `accountOrWalletInfo`
      field, which ensures deposits are automatically credited to the correct
      account.
    </Tip>
  </Accordion>

  <Accordion title="SEPA EUR transfers">
    For EUR accounts, instructions use SEPA IBAN numbers:

    ```json theme={null}
    {
      "instructionsNotes": "Include reference in SEPA transfer description",
      "accountOrWalletInfo": {
        "accountType": "EUR_ACCOUNT",
        "reference": "FUND-EUR789",
        "iban": "DE89370400440532013000",
        "swiftCode": "DEUTDEFF",
        "accountHolderName": "Lightspark Payments FBO Maria Garcia",
        "bankName": "Banco de México"
      }
    }
    ```
  </Accordion>

  <Accordion title="Spark Stablecoin Funding">
    For stablecoin accounts, using a Spark wallet as the funding source:

    ```json theme={null}
    {
      "invoice": "lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs",
      "instructionsNotes": "Use the invoice when making Spark payment",
      "accountOrWalletInfo": {
        "accountType": "SPARK_WALLET",
        "assetType": "USDB",
        "address": "spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu"
      }
    }
    ```
  </Accordion>

  <Accordion title="Solana Stablecoin Funding">
    For Solana wallet accounts, using a Solana wallet as the funding source:

    ```json theme={null}
    {
      "accountOrWalletInfo": {
        "accountType": "SOLANA_WALLET",
        "assetType": "USDC",
        "address": "4Nd1m6Qkq7RfKuE5vQ9qP9Tn6H94Ueqb4xXHzsAbd8Wg"
      }
    }
    ```
  </Accordion>

  <Accordion title="Tron Stablecoin Funding">
    For Tron wallet accounts, using a Tron wallet as the funding source:

    ```json theme={null}
    {
      "accountOrWalletInfo": {
        "accountType": "TRON_WALLET",
        "assetType": "USDT",
        "address": "TNPeeaaFB7K9cmo4uQpcU32zGK8G1NYqeL"
      }
    }
    ```
  </Accordion>

  <Accordion title="Polygon Stablecoin Funding">
    For Polygon wallet accounts, using a Polygon wallet as the funding source:

    ```json theme={null}
    {
      "accountOrWalletInfo": {
        "accountType": "POLYGON_WALLET",
        "assetType": "USDC",
        "address": "0xAbCDEF1234567890aBCdEf1234567890ABcDef12"
      }
    }
    ```
  </Accordion>

  <Accordion title="Base Stablecoin Funding">
    For Base wallet accounts, using a Base wallet as the funding source:

    ```json theme={null}
    {
      "accountOrWalletInfo": {
        "accountType": "BASE_WALLET",
        "assetType": "USDC",
        "address": "0xAbCDEF1234567890aBCdEf1234567890ABcDef12"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Checking account balances

The internal account balance reflects all deposits and withdrawals. The balance includes:

* **amount**: The balance amount in the smallest currency unit (cents for USD, centavos for MXN/BRL, etc.)
* **currency**: Full currency details including code, name, symbol, and decimal places

### Example balance check

```bash Fetch the balance of an internal account theme={null}
curl -X GET 'https://api.lightspark.com/grid/2025-10-13/customers/internal-accounts?customerId=Customer:019542f5-b3e7-1d02-0000-000000000001&currency=USD' \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

<Accordion title="Response">
  ```json theme={null}
  {
    "data": [
      {
        "id": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
        "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
        "type": "INTERNAL_FIAT",
        "status": "ACTIVE",
        "balance": {
          "amount": 50000,
          "currency": {
            "code": "USD",
            "name": "United States Dollar",
            "symbol": "$",
            "decimals": 2
          }
        }
      }
    ],
    "hasMore": false,
    "totalCount": 1
  }
  ```
</Accordion>

<Tip>
  Always check the `decimals` field in the currency object to correctly convert
  between display amounts and API amounts. For example, USD has 2 decimals, so
  an amount of 50000 represents \$500.00.
</Tip>

## Displaying funding instructions to customers

When customers need to deposit funds themselves, display the funding payment instructions in your application:

<Steps>
  <Step title="Retrieve the internal account">
    Fetch the customer's internal account for their desired currency using the API.
  </Step>

  <Step title="Extract payment instructions">
    Parse the `fundingPaymentInstructions` array and select the appropriate instructions based on your customer's preferred payment method.

    ```javascript theme={null}
    const instructions = account.fundingPaymentInstructions[0];
    const bankInfo = instructions.accountOrWalletInfo;
    ```
  </Step>

  <Step title="Display instructions clearly">
    Show the payment details prominently in your UI:

    * Account holder name
    * Bank name and routing information (account/routing number, CLABE, PIX key, etc.)
    * Reference code (if provided)
    * Any additional notes from `instructionsNotes`

    <Tip>
      The unique banking details in each internal account automatically route
      deposits to the correct destination.
    </Tip>
  </Step>

  <Step title="Monitor for deposits">
    Set up webhook listeners to receive notifications when deposits are credited to the internal account. The account balance will update automatically.

    <Info>
      You'll receive `INTERNAL_ACCOUNT.BALANCE_UPDATED` webhook events when the internal account balance changes.
    </Info>
  </Step>
</Steps>

## Best practices

<AccordionGroup>
  <Accordion title="Display complete funding instructions">
    Ensure your customers have all the information needed to make deposits. Consider implementing:

    * Clear display of all banking details from `fundingPaymentInstructions`
    * Copy-to-clipboard functionality for account numbers and reference codes
    * Email/SMS confirmations with complete deposit instructions
  </Accordion>

  <Accordion title="Monitor account balances proactively">
    Set up monitoring to alert customers when their balance is low:

    ```javascript theme={null}
    if (account.balance.amount < minimumThreshold) {
      await notifyCustomer({
        type: 'LOW_BALANCE',
        account: account.id,
        instructions: account.fundingPaymentInstructions
      });
    }
    ```
  </Accordion>

  <Accordion title="Handle multiple currencies efficiently">
    If your platform supports multiple currencies, organize internal accounts by currency in your UI:

    ```javascript theme={null}
    const accountsByCurrency = accounts.data.reduce((acc, account) => {
      const code = account.balance.currency.code;
      acc[code] = account;
      return acc;
    }, {});

    // Quick lookup: accountsByCurrency['USD']

    ```
  </Accordion>

  <Accordion title="Cache account data appropriately">
    Internal account details (especially funding instructions) rarely change, so you can cache them safely. However, always fetch fresh balance data before initiating transfers.
  </Accordion>
</AccordionGroup>

## External Accounts

**External accounts** represent bank accounts, crypto wallets, or other payment instruments outside of Grid for on-ramping or off-ramping funds.

### Characteristics

* Represent real-world accounts (bank accounts, crypto wallets)
* Used as funding sources or payout destinations
* Subject to verification and compliance screening
* Have associated beneficiary information
* Status indicates readiness for use

### Supported Account Types

<Tabs>
  <Tab title="US Bank Accounts">
    ```json theme={null}
    {
      "accountType": "USD_ACCOUNT",
      "currency": "USD",
      "accountNumber": "1234567890",
      "routingNumber": "110000000",
      "bankAccountType": "CHECKING",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Alice Johnson",
        "address": {
          "line1": "123 Main St",
          "city": "San Francisco",
          "state": "CA",
          "postalCode": "94105",
          "country": "US"
        }
      }
    }
    ```
  </Tab>

  <Tab title="IBAN (Europe)">
    ```json theme={null}
    {
      "accountType": "EUR_ACCOUNT",
      "currency": "EUR",
      "iban": "DE89370400440532013000",
      "swiftCode": "DEUTDEFF",
      "bankName": "Deutsche Bank",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Hans Schmidt"
      }
    }
    ```
  </Tab>

  <Tab title="PIX (Brazil)">
    ```json theme={null}
    {
      "accountType": "BRL_ACCOUNT",
      "currency": "BRL",
      "pixKey": "user@example.com",
      "pixKeyType": "EMAIL",
      "bankName": "Nubank",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Maria Silva",
        "taxId": "12345678900"
      }
    }
    ```
  </Tab>

  <Tab title="CLABE (Mexico)">
    ```json theme={null}
    {
      "accountType": "MXN_ACCOUNT",
      "clabeNumber": "012345678901234567",
      "bankName": "BBVA Mexico",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Carlos Rodriguez"
      }
    }
    ```
  </Tab>

  <Tab title="UPI (India)">
    ```json theme={null}
    {
      "accountType": "INR_ACCOUNT",
      "currency": "INR",
      "vpa": "user@paytm",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Priya Sharma"
      }
    }
    ```
  </Tab>

  <Tab title="NGN (Nigeria)">
    ```json theme={null}
    {
      "accountType": "NGN_ACCOUNT",
      "currency": "NGN",
      "accountNumber": "0123456789",
      "bankName": "First Bank of Nigeria",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Chukwuemeka Okonkwo"
      }
    }
    ```
  </Tab>

  <Tab title="CAD (Canada)">
    ```json theme={null}
    {
      "accountType": "CAD_ACCOUNT",
      "currency": "CAD",
      "bankCode": "001",
      "branchCode": "00012",
      "accountNumber": "1234567",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Emily Thompson"
      }
    }
    ```
  </Tab>

  <Tab title="Spark Wallet (Crypto)">
    ```json theme={null}
    {
      "accountType": "SPARK_WALLET",
      "address": "spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu",
      "currency": "BTC"
    }
    ```
  </Tab>
</Tabs>

### Creating External Accounts

```bash Creating a US bank account theme={null}
curl -X POST https://api.lightspark.com/grid/2025-10-13/customers/external-accounts \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
    "currency": "USD",
    "accountInfo": {
      "accountType": "USD_ACCOUNT",
      "accountNumber": "9876543210",
      "routingNumber": "110000000",
      "bankAccountType": "CHECKING",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Alice Johnson",
        "address": {
          "line1": "123 Main St",
          "city": "San Francisco",
          "state": "CA",
          "postalCode": "94105",
          "country": "US"
        }
      }
    }
  }'
```

**Response:**

```json theme={null}
{
  "id": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123",
  "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
  "currency": "USD",
  "status": "PENDING",
  "accountInfo": {
    "accountType": "USD_ACCOUNT",
    "accountNumber": "****3210",
    "routingNumber": "110000000"
  }
}
```

### External Account Status

External accounts progress through verification:

```
PENDING → ACTIVE
```

* **PENDING**: Created, undergoing verification/screening
* **ACTIVE**: Verified, ready for transactions
* **INACTIVE**: Disabled (can be reactivated)
* **UNDER\_REVIEW**: Additional review required

You'll receive `INTERNAL_ACCOUNT.BALANCE_UPDATED` webhooks as balance changes, and `INTERNAL_ACCOUNT.STATUS_UPDATED` webhooks when account status changes (e.g., ACTIVE to FROZEN).

### Using External Accounts

<Tabs>
  <Tab title="As Destination (Payout)">
    Send funds from internal account to external account:

    ```bash theme={null}
    POST /transfer-out

    {
      "source": {"accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965"},
      "destination": {"accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123"},
      "amount": 100000
    }
    ```

    Or via quote for cross-currency:

    ```bash theme={null}
    POST /quotes

    {
      "source": {"sourceType": "ACCOUNT", "accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965"},
      "destination": {"destinationType": "ACCOUNT", "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123"},
      "lockedCurrencySide": "SENDING",
      "lockedCurrencyAmount": 100000
    }
    ```
  </Tab>

  <Tab title="As Source (Funding)">
    Pull funds from external account to internal account:

    ```bash theme={null}
    POST /transfer-in

    {
      "source": {"accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123"},
      "destination": {"accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965"},
      "amount": 100000
    }
    ```

    Only works for "pullable" external accounts (e.g., debit cards).
  </Tab>
</Tabs>

***

## Account Combinations

Common patterns for combining internal and external accounts:

### Pattern 1: Prefunded Payouts

**Use case:** Send payouts from customer's prefunded balance

```
Customer Internal Account (USD) → External Bank Account (EUR)
```

1. Customer funds internal account via ACH
2. Create quote: Internal USD → External EUR
3. Execute quote
4. Recipient receives EUR in their bank

### Pattern 2: JIT Funded Payouts

**Use case:** On-demand payments without maintaining balance

```
Customer → Payment Instructions → Internal Account → External Account
```

1. Create quote with `source: {customerId}`
2. Grid provides payment instructions
3. Customer sends funds to instructions
4. Quote auto-executes when received
5. Recipient receives payout

### Pattern 3: Platform Rewards

**Use case:** Platform distributes Bitcoin rewards

```
Platform Internal Account (USD) → Customer External Wallet (BTC)
```

1. Platform funds its own internal USD account
2. Create quote: Platform Internal USD → Customer Spark Wallet
3. Execute with `immediatelyExecute: true`
4. Customer receives BTC instantly

### Pattern 4: Crypto On-Ramp

**Use case:** Customer buys Bitcoin

```
Customer External Bank → Customer Internal Account (USD) → Customer External Wallet (BTC)
```

1. Customer links bank account
2. Pull funds to internal USD account
3. Create quote: Internal USD → External Spark Wallet
4. Execute quote
5. BTC delivered to customer's wallet
