> ## Documentation Index
> Fetch the complete documentation index at: https://docs.finosu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Customers (Batch)

> Create multiple customers in a single batch request. Each customer is processed independently with detailed individual results.

## Overview

This batch endpoint allows you to create multiple customers in a single API request for improved efficiency.

The endpoint processes customers **asynchronously** - it immediately returns a job ID (HTTP 202 Accepted) and processes customers in the background. Use `GET /customers/batch/{jobId}` to check the processing status.

Each customer in the batch is processed independently, making it ideal for bulk customer imports from your LMS system or initial data migration.

## Upcoming Contract Changes

This endpoint shares its per-customer payload with [Create Customer](./create.mdx), so the upcoming
required-field changes apply here identically: `birthday`, `ssnLastFour`, and `state` become required;
`email`/`phoneNumber` and `timezone`/`zipCode` become at-least-one pairs; and `test` and `loanId` are
removed in favor of `isTest` and `loanIds`.

Nothing below has changed yet — the fields documented on this page reflect what is enforced today. We
will give partners ample time to adjust before introducing any breaking changes. See [Upcoming API
Changes](/api-reference/upcoming-changes) for the new contract and migration examples.

## Request Body Format

The batch endpoint accepts an array of customer records wrapped in a `customers` field:

```json theme={null}
{
  "customers": [
    {
      "id": "CUST123",
      "firstName": "John",
      "lastName": "Doe",
      "email": "john.doe@example.com",
      "birthday": "1990-01-15",
      "ssnLastFour": "1234",
      "phoneNumber": "+15551234567",
      "timezone": "America/New_York",
      "taskType": "Collections",
      "streetAddress1": "123 Main St",
      "streetAddress2": "Apt 4B",
      "city": "New York",
      "state": "NY",
      "zipCode": "10001",
      "doNotCall": false,
      "externalMetadata": {
        "employer": "Acme Corp",
        "paySchedule": "biweekly"
      }
    },
    {
      "id": "CUST124",
      "firstName": "Jane",
      "lastName": "Smith",
      "email": "jane.smith@example.com",
      "birthday": "1985-05-20",
      "ssnLastFour": "5678",
      "phoneNumber": "+15559876543",
      "timezone": "America/Los_Angeles",
      "taskType": "Collections",
      "streetAddress1": "456 Oak Ave",
      "city": "Los Angeles",
      "state": "CA",
      "zipCode": "90001",
      "doNotCall": false
    }
  ]
}
```

### Individual Customer Schema

Each object in the `customers` array follows the same schema as the [single customer endpoint](./create.mdx):

**Always required:**

* `id` - External customer reference ID **(required)**
* `firstName` - Customer's first name **(required)**
* `lastName` - Customer's last name **(required)**
* `phoneNumber` - Customer's phone number **(required)** - Used for automated calling and SMS communications
* `timezone` - Customer's timezone as an IANA timezone name (e.g., "America/New\_York", "America/Los\_Angeles", "America/Chicago") **(required)** - Required for TCPA compliance to ensure calls are made during appropriate hours. Must be a valid IANA timezone identifier.
* `taskType` - Task type for customer's call schedule **(required)** - Valid task types depend on your company configuration. If an invalid task type is provided for your company, the API will return a `400 Bad Request` error with a list of valid task types.

**Required unless `sync: true`:**

* `email` - Customer email address **(required)**
* `streetAddress1` - Street address line 1 **(required)**
* `city` - City name **(required)**
* `state` - State code (e.g., "NY", "CA") **(required)**
* `zipCode` - ZIP/postal code **(required)**

**Optional Fields:**

* `birthday` - Customer birthday (YYYY-MM-DD format) - Used for identity verification on calls. Will become required — see Upcoming API Changes.
* `ssnLastFour` - Last 4 digits of SSN - Used for identity verification on calls. Will become required — see Upcoming API Changes.
* `streetAddress2` - Street address line 2
* `doNotCall` - Whether to mark customer for Do Not Call (default: false)
* `externalMetadata` - Custom JSON object with additional customer data
* `loanIds` - Array of loan IDs to import for the customer (e.g., `[123, 456, 789]`). If provided, only the specified loans will be imported. If omitted, all loans for the customer will be imported. Pass a single-element array to import exactly one loan.
* `sync` - When `true`, auto-fetch missing customer data from your company's LMS (default: `false`). See the [Create Customer endpoint](/api-reference/endpoint/customers/create#lms-auto-fetch-sync) for details.

**Deprecated (will be removed in a future update):**

* `test` - Mark customer as test customer (default: false). Replaced by `isTest`; note `isTest` is not accepted on the request yet, so keep sending `test` until you are notified that the change is live.
* `loanId` - Has no effect on this endpoint; it is accepted and then ignored. Use `loanIds` instead.

## Response Format

The batch endpoint immediately returns a job ID for tracking:

```json theme={null}
{
  "jobId": "550e8400-e29b-41d4-a716-446655440000",
  "totalCustomers": 100,
  "message": "Batch job created with 4 parallel batches. Use GET /customers/batch/550e8400-e29b-41d4-a716-446655440000 to check status."
}
```

### Response Fields

* **jobId** - Unique identifier for the batch job. Use this to check status via `GET /customers/batch/{jobId}`
* **totalCustomers** - Total number of customers queued for processing
* **message** - Status message with instructions for checking progress

## Checking Job Status

Use `GET /customers/batch/{jobId}` to check the processing status:

```json theme={null}
{
  "jobId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing",
  "totalCustomers": 100,
  "processed": 75,
  "failed": 2,
  "progressPercentage": 75.0,
  "createdAt": "2024-01-15T10:30:00Z",
  "processingStartedAt": "2024-01-15T10:30:05Z",
  "processingCompletedAt": null,
  "errorMessage": null
}
```

### Status Values

* **pending** - Job is queued but not yet started
* **processing** - Job is currently processing customers
* **completed** - Job has finished processing all customers
* **failed** - Job encountered a fatal error

## Partial Success Handling

The batch endpoint uses **partial success** handling to ensure maximum processing:

* **Individual failures don't stop processing** - If one customer fails, the remaining customers are still processed
* **Detailed tracking** - The `failed` count in job status shows how many customers failed
* **Transaction isolation** - Each customer is processed in its own transaction to prevent one failure from affecting others

## What the Endpoint Does

When you submit a batch request, Finosu:

1. **Queues the job** - Stores customer data and creates a background job
2. **Returns immediately** - Returns HTTP 202 with job ID for status tracking
3. **Processes asynchronously** - For each customer in parallel batches:
   * Validates the customer data (required fields, state restrictions, task type)
   * Checks for duplicates (verifies customer ID doesn't already exist)
   * Creates the customer in the database
   * Creates call schedule for supported task types (e.g., Collections)

## When to Use Batch vs Single

**Use the batch endpoint when:**

* Importing multiple customers from your LMS system
* Performing initial data migration
* You have more than 5-10 customers to create
* You want to minimize API calls for efficiency

**Use the [single endpoint](./create.mdx) when:**

* Creating individual customers in real-time
* You only have 1-2 customers to create
* You need simpler error handling
* Testing or debugging individual customer creation

## Error Handling

The endpoint returns HTTP status 202 Accepted for all requests, with a job ID that can be used to check processing status via `GET /customers/batch/{job_id}`.

**Individual customer errors during processing may include:**

* **400 BAD REQUEST** - Missing required fields, invalid task type, duplicate customer ID, or state restrictions
* **500 INTERNAL SERVER ERROR** - Server error during processing

Use `GET /customers/batch/{jobId}` to monitor the `processed` and `failed` counts during processing.

## Authentication

Authentication via **X-API-Key header**:

* API key is company-scoped
* Must be obtained from Finosu
* Same authentication as single customer endpoint

## Example Usage

This endpoint is typically used for:

* **Bulk customer import** - Import multiple customers from your loan management system
* **Initial setup** - Create multiple customers during initial platform setup
* **Scheduled jobs** - Automated daily/weekly customer sync workflows
* **Data migration** - Migrate customer data from legacy systems


## OpenAPI

````yaml POST /customers/batch
openapi: 3.1.0
info:
  title: Finosu API
  description: Finosu API
  license:
    name: MIT
  version: 1.0.0
servers: []
security:
  - apiKeyAuth: []
paths:
  /customers/batch:
    post:
      description: >-
        Create multiple customers in a single batch request. Each customer is
        processed independently with detailed individual results.
      requestBody:
        description: Batch of customer records
        content:
          application/json:
            schema:
              type: object
              required:
                - customers
              properties:
                customers:
                  type: array
                  description: Array of customer records to create
                  items:
                    $ref: '#/components/schemas/NewCustomer'
        required: true
      responses:
        '202':
          description: >-
            Batch job accepted for async processing. Use GET
            /customers/batch/{jobId} to check status.
          content:
            application/json:
              schema:
                type: object
                properties:
                  jobId:
                    type: string
                    description: >-
                      Unique identifier for the batch job. Use this to check
                      status via GET /customers/batch/{jobId}
                    example: 550e8400-e29b-41d4-a716-446655440000
                  totalCustomers:
                    type: integer
                    description: Total number of customers queued for processing
                    example: 100
                  message:
                    type: string
                    description: Status message with instructions for checking progress
                    example: >-
                      Batch job created with 4 parallel batches. Use GET
                      /customers/batch/550e8400-e29b-41d4-a716-446655440000 to
                      check status.
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    NewCustomer:
      description: >-
        Customer creation payload. NOTE: the required-field contract for this
        endpoint is changing — see the Upcoming API Changes page
        (/api-reference/upcoming-changes) for the new contract.
      required:
        - id
        - taskType
        - firstName
        - lastName
        - phoneNumber
        - timezone
      type: object
      properties:
        id:
          description: >-
            Unique identifier for the customer. This is your customer reference
            and should match your internal system's ID.
          type: string
        firstName:
          description: The first name of the customer
          type: string
        lastName:
          description: The last name of the customer
          type: string
        email:
          description: >-
            Customer email address. Required unless sync is true. UPCOMING: at
            least one of email or phoneNumber will be required — see
            /api-reference/upcoming-changes.
          type: string
          format: email
          example: john.doe@example.com
        birthday:
          description: >-
            Customer birthday in YYYY-MM-DD format. UPCOMING: this field will
            become required — see /api-reference/upcoming-changes.
          type: string
          format: date
          example: '1985-06-15'
        ssnLastFour:
          description: >-
            Last 4 digits of SSN. UPCOMING: this field will become required —
            see /api-reference/upcoming-changes.
          type: string
          example: '1234'
        timezone:
          description: >-
            Timezone of the customer (IANA timezone name, e.g.,
            'America/New_York', 'America/Los_Angeles'). Required for TCPA
            compliance so calls are placed during permitted hours. UPCOMING: at
            least one of timezone or zipCode will be required, and timezone will
            be derived from zipCode when omitted — see
            /api-reference/upcoming-changes.
          type: string
        phoneNumber:
          description: >-
            Phone number of the customer. UPCOMING: at least one of email or
            phoneNumber will be required — see /api-reference/upcoming-changes.
          type: string
        streetAddress1:
          description: Street address line 1. Required unless sync is true.
          type: string
          example: 123 Main St
        streetAddress2:
          description: Street address line 2 (optional)
          type: string
          example: Apt 4B
        city:
          description: City. Required unless sync is true.
          type: string
          example: San Francisco
        state:
          description: >-
            State code. Required unless sync is true. UPCOMING: this field will
            be required in all cases — see /api-reference/upcoming-changes.
          type: string
          example: CA
        zipCode:
          description: >-
            ZIP/postal code. Required unless sync is true. UPCOMING: at least
            one of timezone or zipCode will be required — see
            /api-reference/upcoming-changes.
          type: string
          example: '94102'
        doNotCall:
          description: Do not call the customer
          type: boolean
        test:
          description: >-
            DEPRECATED — mark customer as test customer. This field will be
            removed in a future update; use isTest instead once the change is
            live. See /api-reference/upcoming-changes.
          type: boolean
          default: false
          deprecated: true
        taskType:
          description: >-
            Type of tasks to create for the customer's automated call schedule.
            Valid values depend on company configuration. This field is
            required.
          type: string
          example: collections
        externalMetadata:
          description: >-
            Additional custom metadata about the customer (e.g. employer
            information, pay schedule, additional contact details)
          type: object
          properties:
            home_phone:
              type: string
              example: '+14155555555'
            cell_phone:
              type: string
              example: '+14155556666'
            employer_name:
              type: string
              example: Acme Corporation
            employer_address:
              type: string
              example: 456 Business Ave
            employer_city:
              type: string
              example: San Francisco
            employer_state:
              type: string
              example: CA
            employer_zip:
              type: string
              example: '94103'
            employer_department:
              type: string
              example: Sales
            employer_phone:
              type: string
              example: '+14155557777'
            employer_direct_line:
              type: string
              example: '+14155558888'
            pay_frequency:
              type: string
              example: biweekly
            pay_day:
              type: string
              example: Friday
        loanIds:
          description: >-
            Array of loan IDs to import. If provided, only these loans are
            imported. If omitted, all loans are imported. Pass a single-element
            array to import exactly one loan.
          type: array
          items:
            type: integer
          example:
            - 123
            - 456
            - 789
        sync:
          type: boolean
          default: false
          description: >-
            When true, auto-fetch missing customer data from your integrated
            lending system. Defaults to false.
        loanId:
          type: string
          description: >-
            DEPRECATED — has no effect on this endpoint and will be removed in a
            future update. Pass the loan ID as a single-element loanIds array
            instead. See /api-reference/upcoming-changes.
          deprecated: true
    Error:
      required:
        - error
        - message
      type: object
      properties:
        error:
          type: integer
          format: int32
        message:
          type: string
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key

````