Description
This endpoint allows you to create a new customer in the LatePoint system. You can provide basic or complete customer information, including contact details, address, preferences, and custom fields.
Authentication
Your LatePoint API Key with write permissions
Request Body
Required Fields
Customer’s first name Validations:
Minimum 2 characters
Maximum 50 characters
Only letters, spaces, and hyphens
Customer’s last name Validations:
Minimum 2 characters
Maximum 50 characters
Only letters, spaces, and hyphens
Customer’s email (must be unique) Validations:
Valid email format
Unique in the system
Maximum 100 characters
Optional Fields
Customer’s phone number Validations:
Valid phone format
Can include country code
Maximum 20 characters
Initial customer status Possible values:
active
- Active customer (default)
inactive
- Inactive customer
pending
- Pending verification
Customer’s date of birth (format: YYYY-MM-DD)
Customer’s gender Possible values:
male
- Male
female
- Female
other
- Other
prefer_not_to_say
- Prefer not to say
Customer’s street address
Customer’s state or province
Customer’s ZIP or postal code
Custom Fields
Custom fields defined in your configuration Example: {
"emergency_contact" : "Mary Smith - +1 555 987 6543" ,
"insurance_provider" : "Health Insurance Co" ,
"referral_source" : "Google" ,
"medical_notes" : "Allergic to penicillin"
}
Additional notes about the customer Validations:
Whether the customer is a guest (no account)
Associated WordPress user ID (if applicable)
Response
Successful Response (201 Created)
Response status (“success”)
Created customer information Unique ID of the created customer
Automatically generated unique customer code
WordPress user ID (if created)
Indicates if welcome email was sent
Examples
Basic Customer
curl -X POST "https://your-site.com/wp-json/latepoint-api/v1/customers" \
-H "Content-Type: application/json" \
-H "X-API-Key: lp_live_1234567890abcdef" \
-d '{
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@email.com",
"phone": "+1 555 123 4567"
}'
Complete Customer with Address
curl -X POST "https://your-site.com/wp-json/latepoint-api/v1/customers" \
-H "Content-Type: application/json" \
-H "X-API-Key: lp_live_1234567890abcdef" \
-d '{
"first_name": "Sarah",
"last_name": "Johnson",
"email": "sarah.johnson@email.com",
"phone": "+1 555 987 6543",
"date_of_birth": "1990-05-15",
"gender": "female",
"address": "123 Main Street, Apt 4B",
"city": "New York",
"state": "NY",
"zipcode": "10001",
"country": "US",
"custom_fields": {
"emergency_contact": "John Johnson - +1 555 111 2222",
"insurance_provider": "Blue Cross Blue Shield",
"referral_source": "Referral"
},
"notes": "VIP customer, prefers morning appointments"
}'
// Function to create customer from form
async function createCustomerFromForm ( formData ) {
try {
// Validate form data
const validation = validateCustomerData ( formData );
if ( ! validation . isValid ) {
throw new Error ( 'Invalid data: ' + validation . errors . join ( ', ' ));
}
// Prepare customer data
const customerData = {
first_name: formData . firstName . trim (),
last_name: formData . lastName . trim (),
email: formData . email . toLowerCase (). trim (),
phone: formData . phone ?. trim (),
date_of_birth: formData . dateOfBirth ,
gender: formData . gender ,
preferences: {
language: formData . language || 'en' ,
communication_preferences: {
email_notifications: formData . emailNotifications !== false ,
sms_notifications: formData . smsNotifications === true ,
marketing_emails: formData . marketingEmails === true
}
},
send_welcome_email: formData . sendWelcomeEmail !== false ,
create_wp_user: formData . createAccount === true
};
// Add address if complete
if ( formData . street && formData . city ) {
customerData . address = {
street: formData . street ,
city: formData . city ,
state: formData . state ,
postal_code: formData . postalCode ,
country: formData . country || 'US'
};
}
// Add custom fields
if ( formData . customFields ) {
customerData . custom_fields = formData . customFields ;
}
// Create customer
const response = await fetch ( '/wp-json/latepoint-api/v1/customers' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'X-API-Key' : 'your_api_key'
},
body: JSON . stringify ( customerData )
});
if ( ! response . ok ) {
throw new Error ( `HTTP Error: ${ response . status } ` );
}
const result = await response . json ();
if ( result . status === 'success' ) {
return {
success: true ,
customer: result . data ,
message: 'Customer created successfully'
};
} else {
throw new Error ( result . error . message );
}
} catch ( error ) {
console . error ( 'Error creating customer:' , error );
return {
success: false ,
error: error . message
};
}
}
function validateCustomerData ( data ) {
const errors = [];
if ( ! data . firstName || data . firstName . trim (). length < 2 ) {
errors . push ( 'First name must be at least 2 characters' );
}
if ( ! data . lastName || data . lastName . trim (). length < 2 ) {
errors . push ( 'Last name must be at least 2 characters' );
}
if ( ! data . email || ! isValidEmail ( data . email )) {
errors . push ( 'Invalid email' );
}
if ( data . phone && ! isValidPhone ( data . phone )) {
errors . push ( 'Invalid phone number' );
}
return {
isValid: errors . length === 0 ,
errors
};
}
function isValidEmail ( email ) {
const emailRegex = / ^ [ ^ \s@ ] + @ [ ^ \s@ ] + \. [ ^ \s@ ] + $ / ;
return emailRegex . test ( email );
}
function isValidPhone ( phone ) {
const phoneRegex = / ^ [ \+ ] ? [ 1-9 ][ \d\s\- \(\) ] {7,15} $ / ;
return phoneRegex . test ( phone );
}
// Usage
const formData = {
firstName: 'Anna' ,
lastName: 'Martinez' ,
email: 'anna.martinez@email.com' ,
phone: '+1 555 444 3333' ,
emailNotifications: true ,
smsNotifications: false ,
sendWelcomeEmail: true ,
createAccount: false
};
const result = await createCustomerFromForm ( formData );
if ( result . success ) {
console . log ( 'Customer created:' , result . customer );
// Redirect or show success message
} else {
console . error ( 'Error:' , result . error );
// Show error message to user
}
Example Response
Customer Created Successfully
{
"status" : "success" ,
"message" : "Customer created successfully" ,
"data" : {
"id" : 47 ,
"first_name" : "Sarah" ,
"last_name" : "Johnson" ,
"email" : "sarah.johnson@email.com" ,
"phone" : "+1 555 987 6543" ,
"status" : "active" ,
"customer_code" : "CUST-2024-047" ,
"avatar_url" : "https://your-site.com/wp-content/plugins/latepoint/images/default-avatar.png" ,
"date_of_birth" : "1990-05-15" ,
"gender" : "female" ,
"address" : {
"street" : "123 Main Street, Apt 4B" ,
"city" : "New York" ,
"state" : "NY" ,
"postal_code" : "10001" ,
"country" : "US"
},
"preferences" : {
"preferred_agent_id" : 3 ,
"preferred_location_id" : 1 ,
"preferred_time_slots" : [ "09:00-12:00" , "14:00-17:00" ],
"language" : "en" ,
"communication_preferences" : {
"email_notifications" : true ,
"sms_notifications" : true ,
"reminder_hours" : 48 ,
"marketing_emails" : false
}
},
"custom_fields" : {
"emergency_contact" : "John Johnson - +1 555 111 2222" ,
"insurance_provider" : "Blue Cross Blue Shield" ,
"referral_source" : "Referral"
},
"notes" : "VIP customer, prefers morning appointments" ,
"created_at" : "2024-01-20T15:30:00Z" ,
"updated_at" : "2024-01-20T15:30:00Z" ,
"wp_user_id" : 156 ,
"welcome_email_sent" : true
}
}
Error Codes
Error 400 - Invalid Data
Error 409 - Duplicate Email
Error 422 - Inconsistent Data
Error 401 - Unauthorized
Error 403 - Insufficient Permissions
{
"status" : "error" ,
"error" : {
"code" : "validation_failed" ,
"message" : "The provided data is not valid" ,
"details" : {
"first_name" : "First name is required and must be at least 2 characters" ,
"email" : "Email format is not valid" ,
"phone" : "Phone format is not valid"
}
}
}
Automatic Validations
Data Validations
First and Last Name :
Minimum 2 characters, maximum 50
Only letters, spaces, hyphens and apostrophes
Extra spaces are automatically removed
Email :
Valid email format
Unique in the system
Automatically converted to lowercase
Maximum 100 characters
Phone :
Valid format (can include country code)
Spaces and special characters are normalized
Maximum 20 characters
Date of Birth :
YYYY-MM-DD format
Cannot be future date
Configurable minimum age (default 13 years)
Business Validations
References :
Agent, location and service IDs must exist and be active
Time slot preferences must be valid
Custom Fields :
Must match defined configuration
Specific validations according to field type
Address :
Country code must be valid (ISO 3166-1 alpha-2)
Postal code must match country format
Recommended Flow
1. Pre-validation
// Validate email before creating
async function checkEmailAvailability ( email ) {
const response = await fetch ( `/wp-json/latepoint-api/v1/customers?search= ${ email } &search_field=email` , {
headers: { 'X-API-Key' : 'your_api_key' }
});
const result = await response . json ();
return result . data . length === 0 ; // true if available
}
const emailAvailable = await checkEmailAvailability ( 'new@email.com' );
if ( ! emailAvailable ) {
console . log ( 'Email is already in use' );
return ;
}
2. Create Customer
// Create customer with error handling
async function createCustomer ( customerData ) {
try {
const response = await fetch ( '/wp-json/latepoint-api/v1/customers' , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'X-API-Key' : 'your_api_key'
},
body: JSON . stringify ( customerData )
});
const result = await response . json ();
if ( result . status === 'success' ) {
return result . data ;
} else {
throw new Error ( result . error . message );
}
} catch ( error ) {
console . error ( 'Error creating customer:' , error );
throw error ;
}
}
3. Post-Creation Handling
// Actions after creating customer
async function handleCustomerCreated ( customer ) {
console . log ( `Customer created: ${ customer . first_name } ${ customer . last_name } ` );
console . log ( `ID: ${ customer . id } , Code: ${ customer . customer_code } ` );
// Register in analytics
if ( typeof gtag !== 'undefined' ) {
gtag ( 'event' , 'customer_created' , {
customer_id: customer . id ,
customer_email: customer . email
});
}
// Show success message
showSuccessMessage ( `Welcome ${ customer . first_name } ! Your account has been created successfully.` );
// Redirect or continue flow
if ( customer . wp_user_id ) {
// WordPress user created, can login
window . location . href = '/my-account/' ;
} else {
// Continue with booking process
window . location . href = `/booking?customer_id= ${ customer . id } ` ;
}
}
Common Use Cases
1. Quick Registration during Booking
// Create minimal customer during booking process
const quickCustomer = {
first_name: 'John' ,
last_name: 'Smith' ,
email: 'john.smith@email.com' ,
phone: '+1 555 123 4567' ,
send_welcome_email: false , // Don't send email during booking
create_wp_user: false // Don't create account for now
};
const customer = await createCustomer ( quickCustomer );
console . log ( 'Customer created for booking:' , customer . id );
2. Full Registration with Account
// Full registration with user account
const fullCustomer = {
first_name: 'Mary' ,
last_name: 'Johnson' ,
email: 'mary.johnson@email.com' ,
phone: '+1 555 987 6543' ,
preferences: {
language: 'en' ,
communication_preferences: {
email_notifications: true ,
sms_notifications: true ,
marketing_emails: false
}
},
send_welcome_email: true ,
create_wp_user: true ,
wp_user_role: 'customer'
};
const customer = await createCustomer ( fullCustomer );
console . log ( 'Customer and user created:' , customer );
3. Bulk Customer Import
// Import multiple customers
async function importCustomers ( customersData ) {
const results = {
success: [],
errors: []
};
for ( const customerData of customersData ) {
try {
// Check if email already exists
const emailExists = await checkEmailAvailability ( customerData . email );
if ( ! emailExists ) {
results . errors . push ({
email: customerData . email ,
error: 'Email already exists'
});
continue ;
}
// Create customer
const customer = await createCustomer ({
... customerData ,
send_welcome_email: false , // Don't send bulk emails
create_wp_user: false // Don't create users in bulk
});
results . success . push ( customer );
// Pause to avoid rate limiting
await new Promise ( resolve => setTimeout ( resolve , 100 ));
} catch ( error ) {
results . errors . push ({
email: customerData . email ,
error: error . message
});
}
}
return results ;
}
// Usage
const customersToImport = [
{ first_name: 'Anna' , last_name: 'Williams' , email: 'anna@email.com' },
{ first_name: 'Charles' , last_name: 'Brown' , email: 'charles@email.com' },
// ... more customers
];
const importResults = await importCustomers ( customersToImport );
console . log ( `Imported: ${ importResults . success . length } , Errors: ${ importResults . errors . length } ` );
Best Practices
1. Client-Side Validation
// Validate data before sending
function validateCustomerForm ( formData ) {
const errors = {};
// Validate name
if ( ! formData . first_name || formData . first_name . trim (). length < 2 ) {
errors . first_name = 'Name must be at least 2 characters' ;
}
// Validate email
const emailRegex = / ^ [ ^ \s@ ] + @ [ ^ \s@ ] + \. [ ^ \s@ ] + $ / ;
if ( ! formData . email || ! emailRegex . test ( formData . email )) {
errors . email = 'Invalid email' ;
}
// Validate phone (optional)
if ( formData . phone ) {
const phoneRegex = / ^ [ \+ ] ? [ 1-9 ][ \d\s\- \(\) ] {7,15} $ / ;
if ( ! phoneRegex . test ( formData . phone )) {
errors . phone = 'Invalid phone format' ;
}
}
return {
isValid: Object . keys ( errors ). length === 0 ,
errors
};
}
2. Robust Error Handling
// Function with automatic retries
async function createCustomerWithRetry ( customerData , maxRetries = 3 ) {
for ( let attempt = 1 ; attempt <= maxRetries ; attempt ++ ) {
try {
return await createCustomer ( customerData );
} catch ( error ) {
if ( attempt === maxRetries ) {
throw error ;
}
// Only retry on network errors, not validation errors
if ( error . message . includes ( 'validation' ) || error . message . includes ( 'already_exists' )) {
throw error ;
}
// Wait before next attempt
await new Promise ( resolve => setTimeout ( resolve , 1000 * attempt ));
}
}
}
// Create multiple customers efficiently
async function createCustomersBatch ( customersData , batchSize = 5 ) {
const results = [];
for ( let i = 0 ; i < customersData . length ; i += batchSize ) {
const batch = customersData . slice ( i , i + batchSize );
const batchPromises = batch . map ( customerData =>
createCustomer ( customerData ). catch ( error => ({ error: error . message , data: customerData }))
);
const batchResults = await Promise . all ( batchPromises );
results . push ( ... batchResults );
// Pause between batches to respect rate limits
if ( i + batchSize < customersData . length ) {
await new Promise ( resolve => setTimeout ( resolve , 500 ));
}
}
return results ;
}
Important Notes
Unique Email : The email must be unique throughout the system. If you try to create a customer with an existing email, you will receive a 409 error.
Custom Fields : Custom fields must be previously configured in your LatePoint installation to be accepted.
Rate Limiting : Respect API rate limits, especially when creating multiple customers. Implement pauses between requests.
WordPress User : If you create an associated WordPress user, the customer will be able to access the customer area and manage their bookings.