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

> Send your first cross-border payment

<img src="https://mintcdn.com/ramps/lbnt1x9X03UqaU0y/images/heroes/hero-quickstart-payouts-light.jpg?fit=max&auto=format&n=lbnt1x9X03UqaU0y&q=85&s=df29dbebe58337854df8abf2e4d28cf1" alt="Payouts quickstart hero" className="page-hero block dark:hidden" width="1856" height="800" data-path="images/heroes/hero-quickstart-payouts-light.jpg" />

<img src="https://mintcdn.com/ramps/lbnt1x9X03UqaU0y/images/heroes/hero-quickstart-payouts-dark.jpg?fit=max&auto=format&n=lbnt1x9X03UqaU0y&q=85&s=a3edd20858ae04a7109c152e309739a5" alt="Payouts quickstart hero" className="page-hero hidden dark:block" width="1856" height="800" data-path="images/heroes/hero-quickstart-payouts-dark.jpg" />

This quickstart covers an example of sending a prefunded cross-border payout for a business customer on an unregulated platform.

## Understanding Entity Mapping for B2B Payouts

In this guide, the entities map as follows:

| Entity Type          | Who They Are               | In This Example                               |
| -------------------- | -------------------------- | --------------------------------------------- |
| **Platform**         | Your payouts platform      | Your company providing AP automation          |
| **Customer**         | Business sending payments  | Your client company (e.g., Acme Corp)         |
| **External Account** | Vendors receiving payments | Maria Garcia (freelance contractor in Mexico) |

**Flow**: Your customer (a business) funds their internal account → uses your platform to send payments → to their vendors' external bank accounts.

## Get API credentials

Create Sandbox API credentials in the dashboard, then set environment variables for local use.

```bash theme={null}
export GRID_BASE_URL="https://api.lightspark.com/grid/2025-10-13"
export GRID_CLIENT_ID="YOUR_SANDBOX_CLIENT_ID"
export GRID_CLIENT_SECRET="YOUR_SANDBOX_CLIENT_SECRET"
```

<Tip>
  Use Basic Auth in cURL with `-u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"`.
</Tip>

## Onboard a Customer

Onboard a customer using the hosted KYC/KYB link flow. The flow is two steps: create the customer, then generate a hosted KYC link for that customer.

### Create the customer

Call `POST /customers` with the customer's `customerType` and any details you already have.

```bash theme={null}
curl -X POST "https://api.lightspark.com/grid/2025-10-13/customers" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "customerType": "INDIVIDUAL",
    "platformCustomerId": "019542f5-b3e7-1d02-0000-000000000001",
    "region": "US",
    "currencies": ["USD", "USDC"],
    "email": "jane.doe@example.com",
    "fullName": "Jane Doe"
  }'
```

Persist the returned `id` — you'll use it as `customerId` in the next step.

### Generate a KYC link

Call `POST /customers/{customerId}/kyc-link` to get a single-use hosted URL.

```bash theme={null}
curl -X POST "https://api.lightspark.com/grid/2025-10-13/customers/Customer:019542f5-b3e7-1d02-0000-000000000001/kyc-link" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "redirectUri": "https://yourapp.com/onboarding-complete"
  }'
```

**Response:**

```json theme={null}
{
  "kycUrl": "https://kyc.lightspark.com/onboard/abc123def456",
  "expiresAt": "2027-01-15T14:32:00Z",
  "provider": "SUMSUB",
  "token": "_act-sbx-jwt-eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

<Tip>
  The `token` is only present for providers that support direct SDK integration. You can pass it to the provider's SDK to embed verification in your own UI instead of redirecting; both paths update the customer's `kycStatus` identically.
</Tip>

### Redirect Customer

Redirect your customer to the returned `kycUrl` where they can complete their identity verification in the hosted interface.

<Warning>
  The KYC link is single-use and expires at `expiresAt`. If a customer needs to retry, call the endpoint again to generate a new link.
</Warning>

### Customer Completes Verification

The customer completes the identity verification process in the hosted KYC interface, providing required documents and information.

<Info>
  The hosted interface handles document collection, verification checks, and compliance requirements automatically.
</Info>

### Track the decision

Reaching the `redirectUri` only means the customer **finished the hosted flow** — not that they were approved. Wait for the final decision via the `CUSTOMER.KYC_APPROVED` / `CUSTOMER.KYC_REJECTED` webhook (use the `CUSTOMER.KYB_*` siblings for business customers) — recommended — or by polling `GET /customers/{customerId}` and inspecting `kycStatus`. On `APPROVED`, the customer is ready to transact and you can unlock funding.

## Get the Customer's Internal Account

Once the customer is created, internal accounts will automatically be created on their behalf. Get their internal account in the desired currency for funding instructions.

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

**Response:**

```json theme={null}
{
  "data": [
    {
      "id": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
      "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
      "balance": {
        "amount": 0, // USD balance in cents
        "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": "US_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-03T12:00:00Z"
    }
  ],
  "hasMore": false,
  "totalCount": 1
}
```

The `fundingPaymentInstructions` provide the bank account details and reference code needed to fund
this internal account via ACH or wire transfer from the customer's bank. It might also include stablecoin
funding details for instant funding of the internal account.

## Fund the Internal Account

For this quickstart, we'll fund the account using the `/sandbox/internal-accounts/{accountId}/fund` endpoint to simulate receiving funds.

In production, your customer would initiate a transfer from their bank or wallet to the account details provided in the funding instructions,
making sure to include the reference code `FUND-ABC123` in the transfer memo if applicable.

```bash theme={null}
# Sandbox: fund internal account directly
curl -X POST "https://api.lightspark.com/grid/2025-10-13/sandbox/internal-accounts/InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965/fund" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 100000
  }'
```

During the funding process, you'll receive transaction status update webhooks.

**Webhook Notification:**

```json theme={null}
{
  "id": "Webhook:019542f5-b3e7-1d02-0000-000000000020",
  "type": "INCOMING_PAYMENT.COMPLETED",
  "timestamp": "2025-10-03T14:32:00Z",
  "data": {
    "id": "Transaction:019542f5-b3e7-1d02-0000-000000000010",
    "status": "COMPLETED",
    "type": "INCOMING",
    "receivedAmount": {
      "amount": 100000,
      "currency": {
        "code": "USD",
        "name": "United States Dollar",
        "symbol": "$",
        "decimals": 2
      }
    },
    "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
    "settledAt": "2025-10-03T14:30:00Z",
    "createdAt": "2025-10-03T14:25:00Z",
    "description": "Internal account funding"
  }
}
```

The internal account now has a balance of \$1,000.00 (100000 cents).

## Add the beneficiary as an External Account

Now add the beneficiary bank account where you want to send the funds. In this example, we'll add a
Mexican CLABE account as the external account.

```bash 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": "MXN",
    "platformAccountId": "maria_garcia_account",
    "accountInfo": {
      "accountType": "CLABE",
      "clabeNumber": "123456789012345678",
      "bankName": "BBVA Mexico",
      "beneficiary": {
        "beneficiaryType": "INDIVIDUAL",
        "fullName": "Maria Garcia",
        "birthDate": "1990-01-01",
        "nationality": "MX",
        "address": {
          "line1": "Av. Reforma 123",
          "city": "Ciudad de México",
          "state": "CDMX",
          "postalCode": "06600",
          "country": "MX"
        }
      }
    }
  }'
```

**Response:**

```json theme={null}
{
  "id": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123",
  "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
  "status": "ACTIVE",
  "currency": "MXN",
  "platformAccountId": "maria_garcia_account",
  "accountInfo": {
    "accountType": "CLABE",
    "clabeNumber": "123456789012345678",
    "bankName": "BBVA Mexico",
    "beneficiary": {
      "beneficiaryType": "INDIVIDUAL",
      "fullName": "Maria Garcia",
      "birthDate": "1990-01-01",
      "nationality": "MX",
      "address": {
        "line1": "Av. Reforma 123",
        "city": "Ciudad de México",
        "state": "CDMX",
        "postalCode": "06600",
        "country": "MX"
      }
    }
  }
}
```

## Create a quote

Create a quote to lock in the exchange rate, fees, and get the 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" # USD internal account
    },
    "destination": {
      "destinationType": "ACCOUNT",
      "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123"
    },
    "lockedCurrencySide": "SENDING",
    "lockedCurrencyAmount": 50000,
    "description": "Payment to Maria Garcia for services"
  }'
```

<Note>
  **Amount Locking**: You can lock either the sending amount (`SENDING`) or receiving amount (`RECEIVING`).
  In this example, we're locking the sending amount to exactly \$500.00 USD (50000 cents). Alternatively,
  you can lock the receiving amount to ensure that the receiver receives exactly some amount of the
  destination currency.
</Note>

**Response:**

```json theme={null}
{
  "id": "Quote:019542f5-b3e7-1d02-0000-000000000006",
  "status": "PENDING",
  "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:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123"
  },
  "sendingCurrency": {
    "code": "USD",
    "name": "United States Dollar",
    "symbol": "$",
    "decimals": 2
  },
  "receivingCurrency": {
    "code": "MXN",
    "name": "Mexican Peso",
    "symbol": "$",
    "decimals": 2
  },
  "totalSendingAmount": 50000,
  "totalReceivingAmount": 861250,
  "exchangeRate": 17.25,
  "feesIncluded": 250,
  "transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000015"
}
```

The quote shows:

* **Sending**: \$500.00 USD (including \$2.50 fee)
* **Receiving**: \$8,612.50 MXN
* **Exchange rate**: 17.25 MXN per USD
* **Quote expires**: In 5 minutes

<Warning>
  Quotes typically expire in 1-5 minutes. Make sure to execute the quote before the `expiresAt` timestamp, or you'll need to create a new quote.
</Warning>

## Execute the quote

Execute the quote to initiate the transfer from the internal account to the external bank account.

```bash theme={null}
curl -X POST "https://api.lightspark.com/grid/2025-10-13/quotes/Quote:019542f5-b3e7-1d02-0000-000000000006/execute" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

**Response:**

```json theme={null}
{
  "id": "Quote:019542f5-b3e7-1d02-0000-000000000006",
  "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:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123"
  },
  "sendingCurrency": {
    "code": "USD",
    "name": "United States Dollar",
    "symbol": "$",
    "decimals": 2
  },
  "receivingCurrency": {
    "code": "MXN",
    "name": "Mexican Peso",
    "symbol": "$",
    "decimals": 2
  },
  "totalSendingAmount": 50000,
  "totalReceivingAmount": 861250,
  "exchangeRate": 17.25,
  "feesIncluded": 250,
  "transactionId": "Transaction:019542f5-b3e7-1d02-0000-000000000015"
}
```

The quote status changes to `PROCESSING` and the transfer is initiated. You'll receive a webhook when the transfer completes:

**Completion Webhook:**

```json theme={null}
{
  "id": "Webhook:019542f5-b3e7-1d02-0000-000000000025",
  "type": "OUTGOING_PAYMENT.COMPLETED",
  "timestamp": "2025-10-03T15:03:00Z",
  "data": {
    "id": "Transaction:019542f5-b3e7-1d02-0000-000000000015",
    "status": "COMPLETED",
    "type": "OUTGOING",
    "sentAmount": {
      "amount": 50000,
      "currency": {
        "code": "USD",
        "name": "United States Dollar",
        "symbol": "$",
        "decimals": 2
      }
    },
    "receivedAmount": {
      "amount": 861250,
      "currency": {
        "code": "MXN",
        "name": "Mexican Peso",
        "symbol": "$",
        "decimals": 2
      }
    },
    "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
    "settledAt": "2025-10-03T15:02:30Z",
    "createdAt": "2025-10-03T15:00:00Z",
    "description": "Payment to Maria Garcia for services",
    "exchangeRate": 17.25,
    "quoteId": "Quote:019542f5-b3e7-1d02-0000-000000000006"
  }
}
```

Congrats, you've sent a real time cross-border payout to a Mexican bank account!
