GET
/
wp-json
/
latepoint-api
/
v1
/
customers
List Customers
curl --request GET \
  --url https://your-site.com/wp-json/latepoint-api/v1/customers \
  --header 'X-API-Key: <x-api-key>'
{
  "status": "error",
  "error": {
    "code": "invalid_parameters",
    "message": "Invalid query parameters",
    "details": {
      "per_page": "Maximum allowed value is 100",
      "order_by": "Invalid sorting field"
    }
  }
}

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

X-API-Key
string
required
Your LatePoint API Key with read permissions

Query Parameters

Pagination

page
integer
default:"1"
Page number to retrieve
per_page
integer
default:"20"
Number of customers per page (maximum 100)

Filters

status
string
Filter by customer statusPossible values:
  • active - Active customers
  • inactive - Inactive customers
  • blocked - Blocked customers
created_after
string
Show only customers created after this date (format: YYYY-MM-DD)
created_before
string
Show only customers created before this date (format: YYYY-MM-DD)
has_bookings
boolean
Filter customers who have or don’t have bookings
  • true - Only customers with bookings
  • false - Only customers without bookings

Dynamic Field Filters

first_name
string
Filter by customer’s first name (partial match)
last_name
string
Filter by customer’s last name (partial match)
email
string
Filter by customer’s email address (partial match)
phone
string
Filter by customer’s phone number (partial match)
is_guest
boolean
Filter by guest status
  • true - Only guest customers
  • false - Only registered customers
wordpress_user_id
integer
Filter by WordPress user ID (exact match)
created_at
string
Filter by creation date (partial match, format: YYYY-MM-DD)
updated_at
string
Filter by last update date (partial match, format: YYYY-MM-DD)
Search customers by name, email or phone

Sorting

order_by
string
default:"created_at"
Field to sort results byPossible values:
  • id - By customer ID
  • created_at - By registration date
order_direction
string
default:"desc"
Sort directionPossible values:
  • asc - Ascending
  • desc - Descending

Included Fields

include
string
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)

status
string
Response status (“success”)
data
array
Array of customer objects
pagination
object
Pagination information

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"

Advanced Pagination

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

{
  "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
  }));
}
// 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

1. Efficient Pagination

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