Description
This endpoint returns a paginated list of all customers registered in the system. You can filter, search and sort the results according to your needs.
Authentication
Your LatePoint API Key with read permissions
Query Parameters
Number of customers per page (maximum 100)
Filters
Filter by customer status Possible values:
active
- Active customers
inactive
- Inactive customers
blocked
- Blocked customers
Show only customers created after this date (format: YYYY-MM-DD)
Show only customers created before this date (format: YYYY-MM-DD)
Filter customers who have or don’t have bookings
true
- Only customers with bookings
false
- Only customers without bookings
Dynamic Field Filters
Filter by customer’s first name (partial match)
Filter by customer’s last name (partial match)
Filter by customer’s email address (partial match)
Filter by customer’s phone number (partial match)
Filter by guest status
true
- Only guest customers
false
- Only registered customers
Filter by WordPress user ID (exact match)
Filter by creation date (partial match, format: YYYY-MM-DD)
Filter by last update date (partial match, format: YYYY-MM-DD)
Search
Search customers by name, email or phone
Sorting
order_by
string
default: "created_at"
Field to sort results by Possible values:
id
- By customer ID
created_at
- By registration date
Sort direction Possible values:
asc
- Ascending
desc
- Descending
Included Fields
Additional fields to include in the response (comma-separated) Possible values:
bookings
- Include customer bookings
stats
- Include customer statistics
custom_fields
- Include custom fields
notes
- Include customer notes
avatar
- Include avatar URL
Response
Successful Response (200 OK)
Response status (“success”)
Array of customer objects Customer status (active, inactive, blocked)
Customer’s avatar URL (if included)
Customer registration date
Customer statistics (if included) Number of completed bookings
Number of cancelled bookings
Total amount spent by customer
Customer custom fields (if included)
Notes about the customer (if included)
Examples
List All Customers
curl -X GET "https://your-site.com/wp-json/latepoint-api/v1/customers" \
-H "X-API-Key: lp_live_1234567890abcdef"
Search Customers with Dynamic Filters
curl -X GET "https://your-site.com/wp-json/latepoint-api/v1/customers?first_name=Carlos&last_name=Lopez&status=active" \
-H "X-API-Key: lp_live_1234567890abcdef"
Filter by Phone and Guest Status
curl -X GET "https://your-site.com/wp-json/latepoint-api/v1/customers?phone=555&is_guest=true&include=stats" \
-H "X-API-Key: lp_live_1234567890abcdef"
Filter by Creation Date
curl -X GET "https://your-site.com/wp-json/latepoint-api/v1/customers?created_at=2024-01&has_bookings=true" \
-H "X-API-Key: lp_live_1234567890abcdef"
// Function to get all customers with pagination
async function getAllCustomers () {
let allCustomers = [];
let currentPage = 1 ;
let hasNextPage = true ;
while ( hasNextPage ) {
const params = new URLSearchParams ({
page: currentPage ,
per_page: 100 ,
include: 'stats'
});
const response = await fetch ( `https://your-site.com/wp-json/latepoint-api/v1/customers? ${ params } ` , {
headers: {
'X-API-Key' : 'lp_live_1234567890abcdef'
}
});
const result = await response . json ();
if ( result . status === 'success' ) {
allCustomers = allCustomers . concat ( result . data );
hasNextPage = result . meta . has_next_page ;
currentPage ++ ;
console . log ( `Page ${ result . meta . current_page } / ${ result . meta . total_pages } - ${ result . data . length } customers` );
} else {
throw new Error ( 'Error fetching customers' );
}
}
return allCustomers ;
}
// Usage
const allCustomers = await getAllCustomers ();
console . log ( `Total customers retrieved: ${ allCustomers . length } ` );
Example Response
Customer List
{
"status" : "success" ,
"data" : [
{
"id" : 45 ,
"first_name" : "John" ,
"last_name" : "Smith" ,
"email" : "john.smith@email.com" ,
"phone" : "+1 555 123 4567" ,
"status" : "active" ,
"avatar_url" : "https://your-site.com/wp-content/uploads/avatars/45.jpg" ,
"created_at" : "2023-06-15T10:30:00Z" ,
"updated_at" : "2024-01-20T14:15:00Z" ,
"stats" : {
"total_bookings" : 12 ,
"completed_bookings" : 10 ,
"cancelled_bookings" : 2 ,
"no_show_bookings" : 0 ,
"total_spent" : "850.00" ,
"last_booking_date" : "2024-01-15T14:30:00Z" ,
"next_booking_date" : "2024-01-25T16:00:00Z"
},
"custom_fields" : {
"emergency_contact" : "Mary Smith - +1 555 987 6543" ,
"preferred_language" : "en" ,
"medical_notes" : "Allergic to penicillin"
}
},
{
"id" : 67 ,
"first_name" : "Anna" ,
"last_name" : "Johnson" ,
"email" : "anna.johnson@email.com" ,
"phone" : "+1 555 987 6543" ,
"status" : "active" ,
"avatar_url" : null ,
"created_at" : "2023-08-22T09:15:00Z" ,
"updated_at" : "2024-01-18T11:45:00Z" ,
"stats" : {
"total_bookings" : 8 ,
"completed_bookings" : 7 ,
"cancelled_bookings" : 1 ,
"no_show_bookings" : 0 ,
"total_spent" : "600.00" ,
"last_booking_date" : "2024-01-10T10:00:00Z" ,
"next_booking_date" : null
},
"custom_fields" : {
"preferred_language" : "en" ,
"referral_source" : "Google"
}
}
],
"meta" : {
"current_page" : 1 ,
"per_page" : 20 ,
"total" : 156 ,
"total_pages" : 8 ,
"has_next_page" : true ,
"has_previous_page" : false
}
}
Error Codes
Error 400 - Invalid Parameters
Error 401 - Unauthorized
Error 403 - Insufficient Permissions
{
"status" : "error" ,
"error" : {
"code" : "invalid_parameters" ,
"message" : "Invalid query parameters" ,
"details" : {
"per_page" : "Maximum allowed value is 100" ,
"order_by" : "Invalid sorting field"
}
}
}
Common Use Cases
1. Active Customers Dashboard
// Get most active customers for dashboard
async function getActiveCustomersDashboard () {
const params = new URLSearchParams ({
status: 'active' ,
has_bookings: 'true' ,
include: 'stats' ,
order_by: 'total_bookings' ,
order_direction: 'desc' ,
per_page: 10
});
const response = await fetch ( `/wp-json/latepoint-api/v1/customers? ${ params } ` , {
headers: { 'X-API-Key' : 'your_api_key' }
});
const result = await response . json ();
return result . data . map ( customer => ({
name: ` ${ customer . first_name } ${ customer . last_name } ` ,
email: customer . email ,
totalBookings: customer . stats . total_bookings ,
totalSpent: customer . stats . total_spent ,
lastBooking: customer . stats . last_booking_date
}));
}
2. Dynamic Field Search
// Advanced search using dynamic field filters
function createAdvancedCustomerSearch () {
let searchTimeout ;
return function searchCustomers ( filters , callback ) {
clearTimeout ( searchTimeout );
searchTimeout = setTimeout ( async () => {
const params = new URLSearchParams ({
status: 'active' ,
per_page: 10 ,
order_by: 'last_name' ,
... filters // Spread dynamic filters
});
try {
const response = await fetch ( `/wp-json/latepoint-api/v1/customers? ${ params } ` , {
headers: { 'X-API-Key' : 'your_api_key' }
});
const result = await response . json ();
if ( result . status === 'success' ) {
const customers = result . data . map ( customer => ({
id: customer . id ,
name: ` ${ customer . first_name } ${ customer . last_name } ` ,
email: customer . email ,
phone: customer . phone ,
isGuest: customer . is_guest
}));
callback ( customers );
} else {
callback ([]);
}
} catch ( error ) {
console . error ( 'Search error:' , error );
callback ([]);
}
}, 300 ); // 300ms debounce
};
}
// Usage examples
const searchCustomers = createAdvancedCustomerSearch ();
// Search by first name
searchCustomers ({ first_name: 'Carlos' }, ( customers ) => {
console . log ( 'Carlos customers:' , customers );
});
// Search by email domain
searchCustomers ({ email: 'gmail.com' }, ( customers ) => {
console . log ( 'Gmail customers:' , customers );
});
// Search guest customers with phone pattern
searchCustomers ({ phone: '555' , is_guest: 'true' }, ( customers ) => {
console . log ( 'Guest customers with 555:' , customers );
});
3. Inactive Customers Analysis
// Identify customers that need follow-up
async function getInactiveCustomersAnalysis () {
const sixMonthsAgo = new Date ();
sixMonthsAgo . setMonth ( sixMonthsAgo . getMonth () - 6 );
const dateFilter = sixMonthsAgo . toISOString (). split ( 'T' )[ 0 ];
const params = new URLSearchParams ({
status: 'active' ,
has_bookings: 'true' ,
last_booking_before: dateFilter ,
include: 'stats' ,
order_by: 'last_booking_date' ,
order_direction: 'asc' ,
per_page: 100
});
const response = await fetch ( `/wp-json/latepoint-api/v1/customers? ${ params } ` , {
headers: { 'X-API-Key' : 'your_api_key' }
});
const result = await response . json ();
if ( result . status === 'success' ) {
return result . data . map ( customer => {
const daysSinceLastBooking = Math . floor (
( new Date () - new Date ( customer . stats . last_booking_date )) / ( 1000 * 60 * 60 * 24 )
);
return {
id: customer . id ,
name: ` ${ customer . first_name } ${ customer . last_name } ` ,
email: customer . email ,
lastBookingDate: customer . stats . last_booking_date ,
daysSinceLastBooking ,
totalBookings: customer . stats . total_bookings ,
totalSpent: customer . stats . total_spent ,
riskLevel: daysSinceLastBooking > 365 ? 'high' :
daysSinceLastBooking > 180 ? 'medium' : 'low'
};
});
}
return [];
}
4. Export Customer List
// Export all customers to CSV
async function exportCustomersToCSV () {
let allCustomers = [];
let currentPage = 1 ;
let hasNextPage = true ;
// Get all customers
while ( hasNextPage ) {
const params = new URLSearchParams ({
page: currentPage ,
per_page: 100 ,
include: 'stats,custom_fields' ,
status: 'active'
});
const response = await fetch ( `/wp-json/latepoint-api/v1/customers? ${ params } ` , {
headers: { 'X-API-Key' : 'your_api_key' }
});
const result = await response . json ();
if ( result . status === 'success' ) {
allCustomers = allCustomers . concat ( result . data );
hasNextPage = result . meta . has_next_page ;
currentPage ++ ;
} else {
break ;
}
}
// Convert to CSV
const csvHeaders = [
'ID' , 'First Name' , 'Last Name' , 'Email' , 'Phone' ,
'Status' , 'Registration Date' , 'Total Bookings' , 'Total Spent' , 'Last Booking'
];
const csvRows = allCustomers . map ( customer => [
customer . id ,
customer . first_name ,
customer . last_name ,
customer . email ,
customer . phone ,
customer . status ,
customer . created_at ,
customer . stats ?. total_bookings || 0 ,
customer . stats ?. total_spent || '0.00' ,
customer . stats ?. last_booking_date || 'N/A'
]);
const csvContent = [ csvHeaders , ... csvRows ]
. map ( row => row . map ( field => `" ${ field } "` ). join ( ',' ))
. join ( ' \n ' );
// Download file
const blob = new Blob ([ csvContent ], { type: 'text/csv;charset=utf-8;' });
const link = document . createElement ( 'a' );
link . href = URL . createObjectURL ( blob );
link . download = `customers_ ${ new Date (). toISOString (). split ( 'T' )[ 0 ] } .csv` ;
link . click ();
return allCustomers . length ;
}
Best Practices
// Use appropriate pagination for large datasets
const OPTIMAL_PAGE_SIZE = 50 ; // Balance between performance and usability
const params = new URLSearchParams ({
page: currentPage ,
per_page: OPTIMAL_PAGE_SIZE ,
order_by: 'created_at' ,
order_direction: 'desc'
});
2. Smart Dynamic Filtering
// Combine dynamic field filters for precise queries
const params = new URLSearchParams ({
first_name: 'Ana' ,
email: 'gmail.com' ,
status: 'active' ,
is_guest: 'false' ,
has_bookings: 'true' ,
created_after: '2024-01-01' ,
include: 'stats'
});
// Filter by phone area code and guest status
const phoneAreaParams = new URLSearchParams ({
phone: '+1555' ,
is_guest: 'true' ,
status: 'active'
});
// Filter by creation month
const monthlyParams = new URLSearchParams ({
created_at: '2024-01' ,
status: 'active' ,
include: 'stats'
});
3. Result Caching
// Implement simple cache for frequent queries
const customerCache = new Map ();
async function getCachedCustomers ( cacheKey , params ) {
if ( customerCache . has ( cacheKey )) {
const cached = customerCache . get ( cacheKey );
if ( Date . now () - cached . timestamp < 300000 ) { // 5 minutes
return cached . data ;
}
}
const response = await fetch ( `/wp-json/latepoint-api/v1/customers? ${ params } ` );
const result = await response . json ();
customerCache . set ( cacheKey , {
data: result ,
timestamp: Date . now ()
});
return result ;
}
Important Notes
Performance : For large customer lists, use appropriate pagination and filters to maintain good performance.
Included Fields : Use the include
parameter only when you need additional information to avoid unnecessarily large responses.
Rate Limiting : Be mindful of rate limits when making multiple requests, especially when paginating through large datasets.
Search : Text search is sensitive to accents and case. For better results, normalize search queries.