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

# Configuring Customers

> Create and manage customers for ramp conversions

export const FeatureCardGrid = ({cols = 3, children}) => <div className={`not-prose feature-cards-grid feature-cards-cols-${cols}`}>
    {children}
  </div>;

export const FeatureCard = ({icon, title, children, href, linkHref, linkText, color, tag, tagPosition, layout, variant, iconSize}) => {
  const isHorizontal = layout === 'horizontal';
  const isFlat = variant === 'flat';
  const isLargeIcon = iconSize === 'lg';
  const isInlineTag = tagPosition === 'inline';
  const card = <div className={`feature-card ${href ? 'feature-card-link' : ''} ${!icon ? 'feature-card-no-icon' : ''} ${isHorizontal ? 'feature-card-horizontal' : ''} ${isFlat ? 'feature-card-flat' : ''} ${isLargeIcon ? 'feature-card-icon-lg' : ''}`}>
      {icon && <div className="feature-card-icon-wrapper">
          {color ? <div className="feature-card-icon" style={{
    WebkitMaskImage: `url(${icon})`,
    maskImage: `url(${icon})`,
    backgroundColor: color,
    width: '24px',
    height: '24px',
    WebkitMaskSize: 'contain',
    maskSize: 'contain',
    WebkitMaskRepeat: 'no-repeat',
    maskRepeat: 'no-repeat'
  }} /> : <img src={icon} alt="" className="feature-card-icon" />}
        </div>}
      <div className="feature-card-content">
        {isInlineTag ? <div className="feature-card-title-row">
            <span className="feature-card-title">{title}</span>
            {tag && <span className="feature-card-tag">{tag}</span>}
          </div> : <div className="feature-card-title">{title}</div>}
        <div className="feature-card-desc">{children}</div>
        {tag && !isInlineTag && <div className="feature-card-tag-row"><span className="feature-card-tag">{tag}</span></div>}
        {linkText && <div className="feature-card-link-row">
            {linkHref ? <a href={linkHref} className="feature-card-text-link" style={{
    color: color
  }}>
                {linkText}
              </a> : <span className="feature-card-text-link feature-card-coming-soon" style={{
    color: color,
    opacity: 0.6
  }}>
                {linkText}
              </span>}
          </div>}
      </div>
    </div>;
  return href ? <a href={href} className="feature-card-anchor">{card}</a> : card;
};

Customers must complete identity verification before processing conversions. The required information varies based on your platform's regulatory status.

<AccordionGroup>
  <Accordion title="Regulated Platforms" icon="">
    <Check>
      **Regulated platforms** have lighter KYC requirements since they handle compliance verification internally.
    </Check>

    The KYC/KYB flow allows you to onboard customers through direct API calls.

    Regulated financial institutions can:

    * **Direct API Onboarding**: Create customers directly via API calls with minimal verification
    * **Internal KYC/KYB**: Handle identity verification through your own compliance systems
    * **Reduced Documentation**: Only provide essential customer information required by your payment counterparty or service provider.
    * **Faster Onboarding**: Streamlined process for known, verified customers

    #### Creating Customers via Direct API

    For regulated platforms, you can create customers directly through the API without requiring external KYC verification:

    To register a new customer in the system, use the `POST /customers` endpoint:

    ```bash theme={null}
    curl -X POST "https://api.lightspark.com/grid/2025-10-13/customers" \
      -H "Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
      -H "Content-Type: application/json" \
      -d '{
        "platformCustomerId": "customer_12345",
        "customerType": "INDIVIDUAL",
        "fullName": "Jane Doe",
        "birthDate": "1992-03-25",
        "nationality": "US",
        "address": {
          "line1": "123 Pine Street",
          "city": "Seattle",
          "state": "WA",
          "postalCode": "98101",
          "country": "US"
        }
      }'
    ```

    The examples below show a more comprehensive set of data. Not all fields are strictly required by the API for customer creation itself, but become necessary based on currency and UMA provider requirements if using UMA.

    <Tabs>
      <Tab title="Individual customer">
        ```json theme={null}
        {
          "platformCustomerId": "9f84e0c2a72c4fa",
          "customerType": "INDIVIDUAL",
          "fullName": "John Sender",
          "birthDate": "1985-06-15",
          "address": {
            "line1": "Paseo de la Reforma 222",
            "line2": "Piso 15",
            "city": "Ciudad de México",
            "state": "Ciudad de México",
            "postalCode": "06600",
            "country": "MX"
          }
        }
        ```
      </Tab>

      <Tab title="Business Customer">
        ```json theme={null}
        {
          "platformCustomerId": "b87d2e4a9c13f5b",
          "customerType": "BUSINESS",
          "businessInfo": {
            "legalName": "Acme Corporation",
            "registrationNumber": "789012345",
            "taxId": "123-45-6789"
          },
          "address": {
            "line1": "456 Oak Avenue",
            "line2": "Floor 12",
            "city": "New York",
            "state": "NY",
            "postalCode": "10001",
            "country": "US"
          }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="Unregulated Platforms" icon="">
    <Warning>
      **Unregulated platforms** require full KYC/KYB verification of customers through hosted flows.
    </Warning>

    Unregulated platforms must:

    * **Hosted KYC Flow**: Use the hosted KYC link for complete identity verification
    * **Extended Review**: Customers may require manual review and approval in some cases

    ### Hosted KYC Link Flow

    The hosted KYC flow provides a secure, hosted interface where customers can complete their identity verification and onboarding process.

    #### Generate KYC Link

    ```bash theme={null}
    curl -X GET "https://api.lightspark.com/grid/2025-10-13/customers/kyc-link?redirectUri=https://yourapp.com/onboarding-complete&platformCustomerId=019542f5-b3e7-1d02-0000-000000000001" \
      -H "Authorization: Basic $GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
    ```

    **Response:**

    ```json theme={null}
    {
      "kycUrl": "https://kyc.lightspark.com/onboard/abc123def456",
      "platformCustomerId": "019542f5-b3e7-1d02-0000-000000000001"
    }
    ```

    #### Complete KYC Process

    <Steps>
      <Step title="Generate KYC Link">
        Call the `/customers/kyc-link` endpoint with your `redirectUri` parameter to generate a hosted KYC URL for your customer.

        <Note>
          The `redirectUri` parameter is embedded in the generated KYC URL and will be used to automatically redirect the customer back to your application after they complete verification.
        </Note>
      </Step>

      <Step title="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 after a limited time period for security.
        </Warning>
      </Step>

      <Step title="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>

        <Note>
          After verification processing, you'll receive a KYC status webhook notification indicating the final verification result.
        </Note>
      </Step>

      <Step title="Automatic Redirect">
        Upon successful KYC completion, the customer is automatically redirected to your specified `redirectUri` URL.

        <Check>
          The customer account will be automatically created by the system upon successful KYC completion. You can identify the new customer using your `platformCustomerId` or other identifiers.
        </Check>
      </Step>

      <Step title="Handle Completion">
        On your redirect page, handle the completed KYC flow and integrate the new customer into your application.
      </Step>
    </Steps>
  </Accordion>
</AccordionGroup>

## Monitor verification status

After a customer completes the KYC/KYB verification process, you'll receive webhook notifications about their KYC status. These notifications are sent to your configured webhook endpoint.

<Note>
  For regulated platforms, customers are created with `APPROVED` KYC status by default.
</Note>

**Webhook Payload (sent to your endpoint):**

```json theme={null}
{
  "id": "Webhook:019542f5-b3e7-1d02-0000-000000000020",
  "type": "CUSTOMER.KYC_APPROVED",
  "timestamp": "2025-07-21T17:32:28Z",
  "data": {
    "id": "Customer:019542f5-b3e7-1d02-0000-000000000001",
    "platformCustomerId": "9f84e0c2a72c4fa",
    "customerType": "INDIVIDUAL",
    "umaAddress": "$john.doe@uma.domain.com",
    "kycStatus": "APPROVED",
    "fullName": "John Michael Doe",
    "birthDate": "1990-01-15",
    "nationality": "US",
    "address": {
      "line1": "123 Main Street",
      "line2": "Apt 4B",
      "city": "San Francisco",
      "state": "CA",
      "postalCode": "94105",
      "country": "US"
    },
    "createdAt": "2025-07-21T17:32:28Z",
    "updatedAt": "2025-07-21T17:32:28Z",
    "isDeleted": false
  }
}
```

**Webhook Headers:**

* `Content-Type: application/json`
* `X-Grid-Signature: {"v": "1", "s": "base64_signature..."}`

<ResponseField name="id" type="string" required>
  Unique identifier for this webhook delivery. Use this for idempotency to prevent processing duplicate webhooks.
</ResponseField>

<ResponseField name="type" type="string" required>
  Status-specific event type. KYC webhooks use `CUSTOMER.*` types:

  * `CUSTOMER.KYC_APPROVED`: Customer verification completed successfully
  * `CUSTOMER.KYC_REJECTED`: Customer verification was rejected
  * `CUSTOMER.KYC_SUBMITTED`: KYC verification was initially submitted
  * `CUSTOMER.KYC_MANUALLY_APPROVED`: Customer was manually approved by platform
  * `CUSTOMER.KYC_MANUALLY_REJECTED`: Customer was manually rejected by platform
</ResponseField>

<ResponseField name="data" type="object" required>
  The full customer resource object, same as the corresponding `GET /customers/{id}` endpoint would return. Includes all customer fields such as `id`, `kycStatus`, `fullName`, `birthDate`, `nationality`, `address`, etc.
</ResponseField>

<Note>
  Intermediate states like `PENDING_REVIEW` do not trigger webhook notifications. Only final resolution states will send webhook notifications.
</Note>

<Accordion title="Webhook Implementation Example">
  ```javascript theme={null}
  // Example webhook handler for KYC status updates
  // Note: Only final states trigger webhook notifications
  app.post('/webhooks/kyc-status', async (req, res) => {
    const { type, data } = req.body;

    switch (type) {
      case 'CUSTOMER.KYC_APPROVED':
        // Activate customer account
        await activateCustomer(data.id);
        await sendWelcomeEmail(data.id);
        break;

      case 'CUSTOMER.KYC_REJECTED':
        // Notify support and customer
        await notifySupport(data.id, 'KYC_REJECTED');
        await sendRejectionEmail(data.id);
        break;

      case 'CUSTOMER.KYC_MANUALLY_APPROVED':
        // Handle manual approval
        await activateCustomer(data.id);
        await sendWelcomeEmail(data.id);
        break;

      case 'CUSTOMER.KYC_MANUALLY_REJECTED':
        // Handle manual rejection
        await notifySupport(data.id, 'KYC_MANUALLY_REJECTED');
        await sendRejectionEmail(data.id);
        break;

      default:
        // Log unexpected types
        console.log(`Unexpected webhook type ${type} for customer ${data.id}`);
    }

    res.status(200).send('OK');
  });
  ```
</Accordion>

<Tip>
  Only customers with `APPROVED` status can create quotes and process
  conversions.
</Tip>

***

## Customer types

<AccordionGroup>
  <Accordion title="Individual customers" icon="user">
    For personal conversions and consumer wallets.

    **Required fields:** `fullName`, `email`, `birthDate`, `address`

    ```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 '{
        "platformCustomerId": "user_12345",
        "customerType": "INDIVIDUAL",
        "fullName": "Alice Johnson",
        "email": "alice@example.com",
        "birthDate": "1990-01-15",
        "address": {...}
      }'
    ```
  </Accordion>

  <Accordion title="Business customers" icon="building">
    For corporate conversions and business accounts.

    **Required fields:** `businessName`, `email`, `taxId`, `address`

    ```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 '{
        "platformCustomerId": "biz_67890",
        "customerType": "BUSINESS",
        "businessName": "Acme Corporation",
        "email": "finance@acme.com",
        "taxId": "12-3456789",
        "address": {...}
      }'
    ```
  </Accordion>
</AccordionGroup>

***

## Next steps

<FeatureCardGrid cols={2}>
  <FeatureCard icon="/images/icons/wallet1.svg" title="Internal Accounts" href="/ramps/accounts/internal-accounts">
    Fund crypto for off-ramp conversions
  </FeatureCard>

  <FeatureCard icon="/images/icons/bank.svg" title="External Accounts" href="/ramps/accounts/external-accounts">
    Set up wallet destinations
  </FeatureCard>

  <FeatureCard icon="/images/icons/arrow-left-right.svg" title="Fiat-to-Crypto" href="/ramps/conversion-flows/fiat-crypto-conversion">
    Build conversion flows
  </FeatureCard>

  <FeatureCard icon="/images/icons/code.svg" title="API Reference" href="/api-reference">
    Complete customer API docs
  </FeatureCard>
</FeatureCardGrid>
