Description
This endpoint returns all available information for a specific customer, including their personal data, statistics, bookings, and custom fields.Authentication
Your LatePoint API Key with read permissions
Path Parameters
Unique ID of the customer to retrieve
Query Parameters
Included Fields
Additional fields to include in the response (comma-separated)Possible values:
bookings
- Include all customer bookingsupcoming_bookings
- Only future bookingspast_bookings
- Only past bookingsstats
- Include detailed statisticscustom_fields
- Include custom fieldsnotes
- Include customer notesavatar
- Include avatar information
Limit of bookings to include (when including bookings)
Filter bookings by specific statusPossible values:
pending
- Pendingconfirmed
- Confirmedcompleted
- Completedcancelled
- Cancelledno_show
- No show
Response
Successful Response (200 OK)
Response status (“success”)
Complete customer object
Show Customer Information
Show Customer Information
Unique customer ID
Customer’s first name
Customer’s last name
Customer’s email
Customer’s phone
Customer status (active, inactive, blocked)
Customer’s avatar URL
Date of birth (if configured)
Customer’s gender
Customer’s street address
Customer’s city
Customer’s state or province
Customer’s ZIP or postal code
Customer’s country
Customer registration date
Last update date
Customer statistics (if included)
Show Detailed Statistics
Show Detailed Statistics
Total number of bookings
Number of completed bookings
Number of cancelled bookings
Number of no-shows
Number of pending bookings
Number of future bookings
List of customer bookings (if included)
Show Bookings
Show Bookings
Booking ID
Booking code
Booking status
Booking date
Start time
End time
Service information
Agent information
Location information
Booking price
Payment status
Customer custom fields (if included)
Customer notes (if included)
Whether the customer is a guest (no account)
Associated WordPress user ID (if applicable)
Examples
Get Basic Customer
Copy
curl -X GET "https://your-site.com/wp-json/latepoint-api/v1/customers/45" \
-H "X-API-Key: lp_live_1234567890abcdef"
Get Customer with Complete Information
Copy
curl -X GET "https://your-site.com/wp-json/latepoint-api/v1/customers/45?include=stats,bookings,custom_fields,preferences&bookings_limit=20" \
-H "X-API-Key: lp_live_1234567890abcdef"
Get Only Future Bookings
Copy
curl -X GET "https://your-site.com/wp-json/latepoint-api/v1/customers/45?include=upcoming_bookings&bookings_limit=5" \
-H "X-API-Key: lp_live_1234567890abcdef"
Example Response
Complete Customer
Copy
{
"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",
"date_of_birth": "1985-03-15",
"gender": "male",
"address": {
"street": "123 Main Street",
"city": "New York",
"state": "NY",
"postal_code": "10001",
"country": "United States"
},
"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,
"pending_bookings": 1,
"total_spent": "850.00",
"average_booking_value": "70.83",
"first_booking_date": "2023-06-20T14:30:00Z",
"last_booking_date": "2024-01-15T14:30:00Z",
"next_booking_date": "2024-01-25T16:00:00Z",
"favorite_agent": {
"id": 3,
"display_name": "Dr. Sarah Johnson",
"booking_count": 8
},
"favorite_service": {
"id": 7,
"name": "General Consultation",
"booking_count": 6
},
"favorite_location": {
"id": 1,
"name": "Main Clinic",
"booking_count": 10
},
"booking_frequency": "monthly"
},
"bookings": [
{
"id": 123,
"booking_code": "LP-2024-001",
"status": "confirmed",
"start_date": "2024-01-25",
"start_time": "16:00",
"end_time": "17:00",
"service": {
"id": 7,
"name": "General Consultation",
"duration": 60
},
"agent": {
"id": 3,
"display_name": "Dr. Sarah Johnson",
"email": "sarah.johnson@clinic.com"
},
"location": {
"id": 1,
"name": "Main Clinic",
"address": "123 Main Street, NY"
},
"price": "75.00",
"payment_status": "paid"
},
{
"id": 118,
"booking_code": "LP-2024-002",
"status": "completed",
"start_date": "2024-01-15",
"start_time": "14:30",
"end_time": "15:30",
"service": {
"id": 7,
"name": "General Consultation",
"duration": 60
},
"agent": {
"id": 3,
"display_name": "Dr. Sarah Johnson",
"email": "sarah.johnson@clinic.com"
},
"location": {
"id": 1,
"name": "Main Clinic",
"address": "123 Main Street, NY"
},
"price": "75.00",
"payment_status": "paid"
}
],
"custom_fields": {
"emergency_contact": "Jane Smith - +1 555 987 6543",
"preferred_language": "en",
"medical_notes": "Allergic to penicillin",
"insurance_provider": "Blue Cross Blue Shield",
"referral_source": "Google"
},
"notes": "Very punctual and friendly customer. Prefers afternoon appointments.",
"notes": "Very punctual and friendly customer. Prefers afternoon appointments."
}
}
Error Codes
Copy
{
"status": "error",
"error": {
"code": "customer_not_found",
"message": "Customer with ID 45 was not found"
}
}
Common Use Cases
1. Complete Customer Profile
Copy
// Function to get complete customer profile
async function getCustomerProfile(customerId) {
try {
const params = new URLSearchParams({
include: 'stats,upcoming_bookings,custom_fields,preferences,notes',
bookings_limit: 10
});
const response = await fetch(
`/wp-json/latepoint-api/v1/customers/${customerId}?${params}`,
{
headers: { 'X-API-Key': 'your_api_key' }
}
);
if (!response.ok) {
throw new Error(`Error ${response.status}: ${response.statusText}`);
}
const result = await response.json();
if (result.status === 'success') {
const customer = result.data;
return {
basicInfo: {
id: customer.id,
name: `${customer.first_name} ${customer.last_name}`,
email: customer.email,
phone: customer.phone,
status: customer.status
},
stats: customer.stats,
upcomingBookings: customer.bookings || [],
preferences: customer.preferences,
customFields: customer.custom_fields,
notes: customer.notes
};
} else {
throw new Error(result.error.message);
}
} catch (error) {
console.error('Error getting customer profile:', error);
throw error;
}
}
// Usage
const profile = await getCustomerProfile(45);
console.log('Customer profile:', profile);
2. Check Booking History
Copy
// Function to analyze customer history
async function analyzeCustomerHistory(customerId) {
const params = new URLSearchParams({
include: 'stats,bookings',
bookings_limit: 50
});
const response = await fetch(
`/wp-json/latepoint-api/v1/customers/${customerId}?${params}`,
{
headers: { 'X-API-Key': 'your_api_key' }
}
);
const result = await response.json();
if (result.status === 'success') {
const customer = result.data;
const stats = customer.stats;
const bookings = customer.bookings || [];
// Pattern analysis
const analysis = {
customerInfo: {
name: `${customer.first_name} ${customer.last_name}`,
memberSince: customer.created_at,
status: customer.status
},
loyaltyMetrics: {
totalBookings: stats.total_bookings,
completionRate: ((stats.completed_bookings / stats.total_bookings) * 100).toFixed(1),
noShowRate: ((stats.no_show_bookings / stats.total_bookings) * 100).toFixed(1),
averageValue: stats.average_booking_value,
totalSpent: stats.total_spent
},
preferences: {
favoriteAgent: stats.favorite_agent?.display_name,
favoriteService: stats.favorite_service?.name,
favoriteLocation: stats.favorite_location?.name,
bookingFrequency: stats.booking_frequency
},
recentActivity: {
lastBooking: stats.last_booking_date,
nextBooking: stats.next_booking_date,
daysSinceLastBooking: stats.last_booking_date ?
Math.floor((new Date() - new Date(stats.last_booking_date)) / (1000 * 60 * 60 * 24)) : null
},
riskAssessment: {
riskLevel: calculateRiskLevel(stats),
recommendations: generateRecommendations(stats, bookings)
}
};
return analysis;
}
throw new Error('Error getting customer data');
}
function calculateRiskLevel(stats) {
const daysSinceLastBooking = stats.last_booking_date ?
Math.floor((new Date() - new Date(stats.last_booking_date)) / (1000 * 60 * 60 * 24)) : 999;
const noShowRate = (stats.no_show_bookings / stats.total_bookings) * 100;
if (daysSinceLastBooking > 180 || noShowRate > 20) return 'high';
if (daysSinceLastBooking > 90 || noShowRate > 10) return 'medium';
return 'low';
}
function generateRecommendations(stats, bookings) {
const recommendations = [];
const daysSinceLastBooking = stats.last_booking_date ?
Math.floor((new Date() - new Date(stats.last_booking_date)) / (1000 * 60 * 60 * 24)) : 999;
if (daysSinceLastBooking > 90) {
recommendations.push('Send reactivation campaign');
}
if (stats.no_show_bookings > 2) {
recommendations.push('Implement additional reminders');
}
if (stats.total_bookings > 10 && stats.total_spent > 500) {
recommendations.push('Candidate for loyalty program');
}
return recommendations;
}
3. Customer Information Widget
Copy
// Create quick customer information widget
function createCustomerWidget(customerId, containerId) {
async function loadCustomerWidget() {
try {
const params = new URLSearchParams({
include: 'stats,upcoming_bookings',
bookings_limit: 3
});
const response = await fetch(
`/wp-json/latepoint-api/v1/customers/${customerId}?${params}`,
{
headers: { 'X-API-Key': 'your_api_key' }
}
);
const result = await response.json();
if (result.status === 'success') {
const customer = result.data;
const container = document.getElementById(containerId);
container.innerHTML = `
<div class="customer-widget">
<div class="customer-header">
<img src="${customer.avatar_url || '/default-avatar.png'}" alt="Avatar" class="avatar">
<div class="customer-info">
<h3>${customer.first_name} ${customer.last_name}</h3>
<p class="email">${customer.email}</p>
<p class="phone">${customer.phone}</p>
<span class="status status-${customer.status}">${customer.status}</span>
</div>
</div>
<div class="customer-stats">
<div class="stat">
<span class="label">Total Bookings:</span>
<span class="value">${customer.stats.total_bookings}</span>
</div>
<div class="stat">
<span class="label">Total Spent:</span>
<span class="value">$${customer.stats.total_spent}</span>
</div>
<div class="stat">
<span class="label">Last Visit:</span>
<span class="value">${formatDate(customer.stats.last_booking_date)}</span>
</div>
</div>
<div class="upcoming-bookings">
<h4>Upcoming Appointments</h4>
${customer.bookings && customer.bookings.length > 0 ?
customer.bookings.map(booking => `
<div class="booking-item">
<span class="date">${formatDate(booking.start_date)} ${booking.start_time}</span>
<span class="service">${booking.service.name}</span>
</div>
`).join('') :
'<p class="no-bookings">No upcoming appointments</p>'
}
</div>
</div>
`;
}
} catch (error) {
console.error('Error loading customer widget:', error);
document.getElementById(containerId).innerHTML =
'<div class="error">Error loading customer information</div>';
}
}
function formatDate(dateString) {
if (!dateString) return 'N/A';
return new Date(dateString).toLocaleDateString('en-US');
}
loadCustomerWidget();
}
// Usage
createCustomerWidget(45, 'customer-widget-container');
4. Customer Validation for Bookings
Copy
// Validate customer before creating a booking
async function validateCustomerForBooking(customerId) {
try {
const params = new URLSearchParams({
include: 'stats,upcoming_bookings'
});
const response = await fetch(
`/wp-json/latepoint-api/v1/customers/${customerId}?${params}`,
{
headers: { 'X-API-Key': 'your_api_key' }
}
);
const result = await response.json();
if (result.status === 'success') {
const customer = result.data;
const validation = {
isValid: true,
warnings: [],
errors: [],
customer: customer
};
// Check customer status
if (customer.status === 'blocked') {
validation.isValid = false;
validation.errors.push('Customer blocked - cannot make bookings');
}
if (customer.status === 'inactive') {
validation.warnings.push('Customer inactive - verify information');
}
// Check no-show history
const noShowRate = (customer.stats.no_show_bookings / customer.stats.total_bookings) * 100;
if (noShowRate > 20) {
validation.warnings.push(`High no-show rate (${noShowRate.toFixed(1)}%)`);
}
// Check pending bookings
const pendingBookings = customer.bookings?.filter(b => b.status === 'pending') || [];
if (pendingBookings.length > 2) {
validation.warnings.push(`Has ${pendingBookings.length} pending bookings`);
}
// Check contact information
if (!customer.phone || !customer.email) {
validation.warnings.push('Incomplete contact information');
}
return validation;
} else {
return {
isValid: false,
errors: ['Customer not found'],
warnings: [],
customer: null
};
}
} catch (error) {
return {
isValid: false,
errors: ['Error validating customer'],
warnings: [],
customer: null
};
}
}
// Usage
const validation = await validateCustomerForBooking(45);
if (validation.isValid) {
if (validation.warnings.length > 0) {
console.warn('Warnings:', validation.warnings);
}
console.log('Customer valid for booking');
} else {
console.error('Errors:', validation.errors);
}
Best Practices
1. Efficient Use of Include Parameter
Copy
// Only include data you actually need
const basicCustomer = await getCustomer(45); // Basic data only
const customerWithStats = await getCustomer(45, 'stats'); // With statistics
const fullCustomer = await getCustomer(45, 'stats,bookings,custom_fields'); // Complete
2. Customer Data Caching
Copy
// Implement cache for customer data
const customerCache = new Map();
async function getCachedCustomer(customerId, include = '') {
const cacheKey = `${customerId}_${include}`;
if (customerCache.has(cacheKey)) {
const cached = customerCache.get(cacheKey);
if (Date.now() - cached.timestamp < 300000) { // 5 minutes
return cached.data;
}
}
const params = include ? `?include=${include}` : '';
const response = await fetch(`/wp-json/latepoint-api/v1/customers/${customerId}${params}`);
const result = await response.json();
customerCache.set(cacheKey, {
data: result,
timestamp: Date.now()
});
return result;
}
3. Robust Error Handling
Copy
// Function with complete error handling
async function safeGetCustomer(customerId, include = '') {
try {
const params = include ? new URLSearchParams({ include }) : '';
const url = `/wp-json/latepoint-api/v1/customers/${customerId}${params ? '?' + params : ''}`;
const response = await fetch(url, {
headers: { 'X-API-Key': 'your_api_key' }
});
if (!response.ok) {
if (response.status === 404) {
throw new Error('Customer not found');
} else if (response.status === 403) {
throw new Error('No permission to access this customer');
} else {
throw new Error(`Server error: ${response.status}`);
}
}
const result = await response.json();
if (result.status === 'success') {
return result.data;
} else {
throw new Error(result.error.message);
}
} catch (error) {
console.error(`Error getting customer ${customerId}:`, error.message);
throw error;
}
}
Important Notes
Sensitive Information: Customer data may include sensitive information. Make sure to handle it according to applicable privacy regulations.
Optimization: Use the
include
parameter selectively to get only the data you need and improve performance.Cache: If you implement customer data caching, make sure to invalidate it when customer information is updated.
Statistics: Statistics are calculated in real time, so they may affect response time if the customer has many bookings.