> ## Documentation Index
> Fetch the complete documentation index at: https://ramps-04-30-docs-add-grid-tutorial-skill-interactive-zero-t.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuring Customers

> Creating and managing customers for global P2P payments

This guide provides comprehensive information about creating customers in the Grid API, including customer types, onboarding models, registration, and management.

## Onboarding model

There are two models for regulated and unregulated platforms.

* Regulated platforms: Use your existing compliance processes. Create individual and business customers directly via `POST /customers`. The information you supply is used for beneficiary/counterparty compliance screening.
* Unregulated platforms: Grid performs KYC/KYB. Generate a hosted KYC/KYB link, redirect your customer to complete verification in their locale, receive a KYC result webhook. While KYC is pending, allow customers to finish account setup but block funding and money movement.

## Customer Types

The Grid API supports both individual and business customers. While the API schema itself makes most Personally Identifiable Information (PII) optional at initial creation, specific fields may become mandatory based on the currencies the customer will transact with.

Your platform’s configuration (retrieved via `GET /config`) includes a supportedCurrencies array. Each currency object within this array has a providerRequiredCustomerFields list. If a customer is intended to use a specific currency, any fields listed for that currency must be provided when creating or updating the customer.

The only required field for all customers is `customerType` (`INDIVIDUAL` or `BUSINESS`). It's recommended to also pass a `platformCustomerId` to tie the customer to your internal identifier, but if you don't, one will be generated automatically.

If using sending and receiving to just-in-time UMA addresses, you'll also need to specify the bank account information

## Creating Customers

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

### Individual customers

In some cases, only the above fields are required at customer creation. Beyond those base requirements, additional fields commonly associated with individual customers include:

* Full name
* Date of birth (YYYY-MM-DD format)
* Physical address (including country, state, city, postalCode)

**Note:** Check the `providerRequiredCustomerFields` for each relevant currency in your platform's configuration to determine which of these fields are strictly mandatory at creation/update time for that customer to transact in those currencies.

### Business customers

Beyond the base requirements, additional fields commonly associated with business customers include:

* Business information:
  * Legal name (this is often required, check `providerRequiredCustomerFields`)
  * Registration number (optional, unless specified by `providerRequiredCustomerFields`)
  * Tax ID (optional, unless specified by `providerRequiredCustomerFields`)
* Physical address (including country, state, city, postalCode)

**Note:** Check the `providerRequiredCustomerFields` for each relevant currency in your platform's configuration to determine which of these fields are strictly mandatory at creation/update time for that customer to transact in those currencies.

When creating or updating customers, the `customerType` field must be specified as either `INDIVIDUAL` or `BUSINESS`.

<Tip>
  There can be multiple customers with the same platformCustomerId but different UMA addresses. This is useful if you want to track multiple UMA addresses and/or bank accounts for the same customer in your platform.
</Tip>

## Customer Creation Process

### Creating a new individual customer (regulated institutions)

To register a new customer directly, use the `POST /customers` endpoint (regulated institutions):

```bash theme={null}
curl -sS -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": "9f84e0c2a72c4fa",
    "customerType": "INDIVIDUAL",
    "fullName": "Jane Doe",
  }'
```

The API allows creating a customer with minimal PII. However, to enable transactions for a customer in specific currencies, you must include any PII fields mandated by the `providerRequiredCustomerFields` for those currencies (found in your platform's configuration via `GET /config`).

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 provider requirements.

Example request body for an individual customer with UMA instant payments enabled (ensure all `providerRequiredCustomerFields` for intended currencies are included):

<Note>
  Typically bank account information is provided separately via internal and external account management. However, when using UMA for instant payments, since funding and withdrawals are instant, bank account information can be provided at time of customer creation.
</Note>

```json theme={null}
{
  "umaAddress": "$john.sender@mycompany.com",
  "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"
  }
}
```

<Note>
  UMA addresses follow the format `$username@domain`. For your platform:

  1. The `domain` part will be your configured UMA domain (set in platform configuration)
  2. The `username` part can be chosen by you or your customers, following these rules:
     * Must start with a \$ symbol. This is to differentiate from email addresses and clearly identify an uma address.
     * The `username` portion is limited to a-z0-9-\_.+
     * Addresses are case-insensitive, but by convention are written only with lowercase letters
     * Like email addresses, the maximum number of characters for the `username` portion of the address is 64 characters (including the \$).

  The Grid API validates these requirements and will return an error if they are not met.
</Note>

### Creating a new business customer (regulated institutions)

```bash theme={null}
curl -sS -X POST "https://api.lightspark.com/grid/2025-10-13/customers" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "umaAddress": "$acme.corp@mycompany.com",
    "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"
    }
  }'
```

### Onboarding customers (unregulated institutions)

Unregulated institutions should initiate a hosted KYC/KYB flow. Generate a link and redirect the customer to complete verification. While KYC is pending, allow account setup but block funding and money movement.

1. Request a hosted KYC link for a customer using your `platformCustomerId` (optional `redirectUri` to return the user to your app when finished):

```bash theme={null}
curl -sS -G "https://api.lightspark.com/grid/2025-10-13/customers/kyc-link" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  --data-urlencode "platformCustomerId=9f84e0c2a72c4fa" \
  --data-urlencode "redirectUri=https://app.example.com/onboarding/completed"
```

Response:

```json theme={null}
{
  "kycUrl": "https://kyc.grid.example/onboard/abc123",
  "platformCustomerId": "9f84e0c2a72c4fa",
  "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001"
}
```

2. Redirect the customer to `kycUrl` to complete KYC/KYB in their locale.
3. After the user is redirected back to your app, they can continue with account setup until KYC review is complete.
4. Handle the KYC status webhook. Grid notifies you when a decision is reached; update your records and unlock funding on APPROVED.

### Handling KYC/KYB Webhooks

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>

## Customer management

### Retrieving customer information

You can retrieve customer information using either the Grid-assigned customer ID or your platform's customer ID:

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

or list customers with a filter:

```bash theme={null}
curl -sS -G "https://api.lightspark.com/grid/2025-10-13/customers" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  --data-urlencode "umaAddress={umaAddress}" \
  --data-urlencode "platformCustomerId={platformCustomerId}" \
  --data-urlencode "customerType={customerType}" \
  --data-urlencode "createdAfter={createdAfter}" \
  --data-urlencode "createdBefore={createdBefore}" \
  --data-urlencode "cursor={cursor}" \
  --data-urlencode "limit={limit}"
```

Note that this example shows all available filters. You can use any combination of them.

## Data validation

The Grid API performs validation on all customer data. Common validation rules include:

* All required fields must be present based on customer type
* Date of birth must be in YYYY-MM-DD format and represent a valid date
* Names must not contain special characters
* Bank account information must follow country-specific formats
* Addresses must include all required fields including country code

If validation fails, the API will return a 400 Bad Request response with detailed error information.

## Bulk customer import operations

For scenarios where you need to add many customers to the system at once, the API provides a CSV file upload endpoint.

### CSV file upload

For large-scale customer imports, you can upload a CSV file containing customer information:

```bash theme={null}
curl -sS -X POST "https://api.lightspark.com/grid/2025-10-13/customers/bulk/csv" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET" \
  -F "file=@customers.csv"
```

The CSV file should follow a specific format with required and optional columns based on customer type. Here's an example:

```csv theme={null}
umaAddress,platformCustomerId,customerType,fullName,birthDate,addressLine1,city,state,postalCode,country,accountType,accountNumber,bankName,platformAccountId,businessLegalName,routingNumber,accountCategory
$john.doe@uma.domain.com,cust_user123,INDIVIDUAL,John Doe,1990-01-15,123 Main St,San Francisco,CA,94105,US,US_ACCOUNT,123456789,Chase Bank,chase_primary_1234,,222888888,SAVINGS
$acme@uma.domain.com,cust_biz456,BUSINESS,,,400 Commerce Way,Austin,TX,78701,US,US_ACCOUNT,987654321,Bank of America,boa_business_5678,Acme Corp,121212121,CHECKING
```

<Tip>
  CSV Upload Best Practices

  1. Use a spreadsheet application to prepare your CSV file
  2. Validate data before upload (e.g., date formats, required fields)
  3. Include a header row with column names
  4. Use UTF-8 encoding for special characters
  5. Keep file size under 100MB for optimal processing
</Tip>

You can track the job status through:

1. Webhook notifications (if configured)
2. Status endpoint:

```bash theme={null}
curl -sS -X GET "https://api.lightspark.com/grid/2025-10-13/customers/bulk/jobs/{jobId}" \
  -u "$GRID_CLIENT_ID:$GRID_CLIENT_SECRET"
```

Example job status response:

```json theme={null}
{
  "jobId": "job_123456789",
  "status": "PROCESSING",
  "progress": {
    "total": 5000,
    "processed": 2500,
    "successful": 2499,
    "failed": 1
  },
  "errors": [
    {
      "platformCustomerId": "cust_biz456",
      "error": {
        "code": "validation_error",
        "message": "Invalid bank account number"
      }
    }
  ]
}
```
