Skip to main content
POST
Customer Batch Intake

Choose your workflow

  • Origination lists: send outer scheduleMode: "enroll", a header Idempotency-Key, and a row idempotencyKey for each application. Follow Enroll a List (Batch) for the full contract, limits, retry behavior and examples.
  • Existing customer creation: omit scheduleMode. The remainder of this guide describes that existing workflow only.
Both return a background job. Check batch progress with the returned job ID. Enrollment uses the shared origination cadence service; it does not run the customer-create scheduling workflow below.

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 a Customer, 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 loanId is removed in favor of loanIds. The fields documented on this page reflect what is enforced today, and we will give partners ample time to adjust before introducing any breaking changes. See Upcoming API 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:

Individual Customer Schema

Each object in the customers array follows the same schema as the single customer endpoint: 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. A company-invalid task type fails the row during processing with a 422: message listing the valid types. An accepted batch still returns HTTP 202.
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 a Customer endpoint for details.
  • isTest - Mark customer as test customer (default: false)
Deprecated (will be removed in a future update):
  • loanId - Does not select loans to import; use loanIds for that. On rows with an origination task type for companies configured for origination boarding, loanId is read as the LMS application reference; on all other rows it is accepted and then ignored.

Response Format

The batch endpoint immediately returns a job ID for tracking:

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:

Status Values

  • pending - Job is queued but not yet started
  • processing - Job is currently processing customers
  • completed - Job has finished processing all customers. Individual customers may still have failed — check failures
  • failed - Job encountered a fatal error
status: completed does not mean every customer succeeded — it means the job finished. Always reconcile against failed and failures rather than treating completed as success.

Failures

failures lists every customer that could not be created — it is never truncated, however many there are. Successful rows are not enumerated; they are the set you submitted minus these. index is the position in your array, not within a server-side batch, so you can walk failures straight against your source file. Common failure messages:
  • 422: Missing required fields: ... — a required field was absent for that customer
  • 422: Invalid task type. Valid types for this company: [...] — taskType isn’t configured for your company
  • 422: Invalid phone number. Phone number must contain at least one digit. — the number contained no digits
  • 422: State ... is not supported for ... — a state restriction applies to your company
  • 502: sync=true but failed to fetch customer data from LMS or 502: LMS returned invalid customer data — an LMS dependency failure, not invalid caller input
  • 500: Internal error processing this customer — an internal failure. Check the customer’s current state before resubmitting; the error alone does not prove that no writes occurred
Customers are processed in parallel batches, and each batch publishes its failures when it finishes, so failures fills in in bursts and is partial while status is processing. Poll until status is completed or failed before treating the list as the final record. The array is always sorted by index regardless of which batch finished first.
failures was added in August 2026. Jobs that ran before then report an empty array even if they had failures — the per-row detail was not retained at the time.

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 shows how many customers failed, and failures names each one
  • Nothing is truncated - Every failed row is reported, however many there are
  • 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)
    • Creates the customer, or updates it in place when a customer with the same id already exists for your company — the same upsert behavior as the single endpoint
    • Creates call schedule for supported task types (e.g., Collections)
Because rows are upserts keyed on id, resubmitting failed rows (or the whole batch) does not create duplicate customers.

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

An accepted batch returns HTTP 202 Accepted, with a job ID for GET /customers/batch/{jobId}. Invalid request envelopes return HTTP 422 before queuing. Failures discovered during processing appear per row in the status response; a 422: message prefix does not change the batch HTTP status. Individual customer errors during processing may include:
  • 422 UNPROCESSABLE CONTENT - Missing required fields, invalid task type, or state restrictions
  • 502 BAD GATEWAY - LMS fetch failure or malformed provider data (malformed optional birthdays are skipped)
  • 500 INTERNAL SERVER ERROR - Server error during processing
Use GET /customers/batch/{jobId} to monitor the processed and failed counts during processing, and read the failures array for the specific rows that were rejected and why.

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

Authorizations

X-API-Key
string
header
required

Headers

Idempotency-Key
string

Required for scheduleMode=enroll. Stable key for this exact ordered list. Separate from each row idempotencyKey.

Pattern: ^[A-Za-z0-9._:-]{1,128}$

Body

application/json

Choose origination list enrollment or legacy customer creation. Enrollment row fields are validated individually by the worker; invalid rows are reported in results.

customers
object[]
required

Array of customer records to create

Response

Batch job accepted for async processing. Use GET /customers/batch/{jobId} to check status.

jobId
string

Unique identifier for the batch job. Use this to check status via GET /customers/batch/{jobId}

Example:

"550e8400-e29b-41d4-a716-446655440000"

totalCustomers
integer

Total number of customers queued for processing

Example:

100

message
string

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