curl --request GET \
--url https://your-site.com/wp-json/latepoint-api/v1/customers/{id} \
--header 'X-API-Key: <x-api-key>'{
"status": "error",
"error": {
"code": "customer_not_found",
"message": "Customer with ID 45 was not found"
}
}
Retrieves detailed information of a specific customer
curl --request GET \
--url https://your-site.com/wp-json/latepoint-api/v1/customers/{id} \
--header 'X-API-Key: <x-api-key>'{
"status": "error",
"error": {
"code": "customer_not_found",
"message": "Customer with ID 45 was not found"
}
}
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 informationpending - Pendingconfirmed - Confirmedcompleted - Completedcancelled - Cancelledno_show - No showShow Customer Information
Show Detailed Statistics
Show Bookings
curl -X GET "https://your-site.com/wp-json/latepoint-api/v1/customers/45" \
-H "X-API-Key: lp_live_1234567890abcdef"
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"
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"
{
"status": "success",
"data": {
"id": 45,
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"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": "[email protected]"
},
"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": "[email protected]"
},
"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."
}
}
{
"status": "error",
"error": {
"code": "customer_not_found",
"message": "Customer with ID 45 was not found"
}
}
// 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);
// 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;
}
// 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');
// 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);
}
// 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
// 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;
}
// 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;
}
}
include parameter selectively to get only the data you need and improve performance.