> ## Documentation Index
> Fetch the complete documentation index at: https://docs-restapi.wplimit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Get Customer

> Retrieves detailed information of a specific customer

## Description

This endpoint returns all available information for a specific customer, including their personal data, statistics, bookings, and custom fields.

## Authentication

<ParamField header="X-API-Key" type="string" required>
  Your LatePoint API Key with read permissions
</ParamField>

## Path Parameters

<ParamField path="id" type="integer" required>
  Unique ID of the customer to retrieve
</ParamField>

## Query Parameters

### Included Fields

<ParamField query="include" type="string">
  Additional fields to include in the response (comma-separated)

  **Possible values:**

  * `bookings` - Include all customer bookings
  * `upcoming_bookings` - Only future bookings
  * `past_bookings` - Only past bookings
  * `stats` - Include detailed statistics
  * `custom_fields` - Include custom fields
  * `notes` - Include customer notes
  * `avatar` - Include avatar information
</ParamField>

<ParamField query="bookings_limit" type="integer" default="10">
  Limit of bookings to include (when including bookings)
</ParamField>

<ParamField query="bookings_status" type="string">
  Filter bookings by specific status

  **Possible values:**

  * `pending` - Pending
  * `confirmed` - Confirmed
  * `completed` - Completed
  * `cancelled` - Cancelled
  * `no_show` - No show
</ParamField>

## Response

### Successful Response (200 OK)

<ResponseField name="status" type="string">
  Response status ("success")
</ResponseField>

<ResponseField name="data" type="object">
  Complete customer object

  <Expandable title="Customer Information">
    <ResponseField name="id" type="integer">
      Unique customer ID
    </ResponseField>

    <ResponseField name="first_name" type="string">
      Customer's first name
    </ResponseField>

    <ResponseField name="last_name" type="string">
      Customer's last name
    </ResponseField>

    <ResponseField name="email" type="string">
      Customer's email
    </ResponseField>

    <ResponseField name="phone" type="string">
      Customer's phone
    </ResponseField>

    <ResponseField name="status" type="string">
      Customer status (active, inactive, blocked)
    </ResponseField>

    <ResponseField name="avatar_url" type="string">
      Customer's avatar URL
    </ResponseField>

    <ResponseField name="date_of_birth" type="string">
      Date of birth (if configured)
    </ResponseField>

    <ResponseField name="gender" type="string">
      Customer's gender
    </ResponseField>

    <ResponseField name="address" type="string">
      Customer's street address
    </ResponseField>

    <ResponseField name="city" type="string">
      Customer's city
    </ResponseField>

    <ResponseField name="state" type="string">
      Customer's state or province
    </ResponseField>

    <ResponseField name="zipcode" type="string">
      Customer's ZIP or postal code
    </ResponseField>

    <ResponseField name="country" type="string">
      Customer's country
    </ResponseField>

    <ResponseField name="created_at" type="string">
      Customer registration date
    </ResponseField>

    <ResponseField name="updated_at" type="string">
      Last update date
    </ResponseField>

    <ResponseField name="stats" type="object">
      Customer statistics (if included)

      <Expandable title="Detailed Statistics">
        <ResponseField name="total_bookings" type="integer">
          Total number of bookings
        </ResponseField>

        <ResponseField name="completed_bookings" type="integer">
          Number of completed bookings
        </ResponseField>

        <ResponseField name="cancelled_bookings" type="integer">
          Number of cancelled bookings
        </ResponseField>

        <ResponseField name="no_show_bookings" type="integer">
          Number of no-shows
        </ResponseField>

        <ResponseField name="pending_bookings" type="integer">
          Number of pending bookings
        </ResponseField>

        <ResponseField name="future_bookings_count" type="integer">
          Number of future bookings
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="bookings" type="array">
      List of customer bookings (if included)

      <Expandable title="Bookings">
        <ResponseField name="id" type="integer">
          Booking ID
        </ResponseField>

        <ResponseField name="booking_code" type="string">
          Booking code
        </ResponseField>

        <ResponseField name="status" type="string">
          Booking status
        </ResponseField>

        <ResponseField name="start_date" type="string">
          Booking date
        </ResponseField>

        <ResponseField name="start_time" type="string">
          Start time
        </ResponseField>

        <ResponseField name="end_time" type="string">
          End time
        </ResponseField>

        <ResponseField name="service" type="object">
          Service information
        </ResponseField>

        <ResponseField name="agent" type="object">
          Agent information
        </ResponseField>

        <ResponseField name="location" type="object">
          Location information
        </ResponseField>

        <ResponseField name="price" type="string">
          Booking price
        </ResponseField>

        <ResponseField name="payment_status" type="string">
          Payment status
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="custom_fields" type="object">
      Customer custom fields (if included)
    </ResponseField>

    <ResponseField name="notes" type="string">
      Customer notes (if included)
    </ResponseField>

    <ResponseField name="is_guest" type="boolean">
      Whether the customer is a guest (no account)
    </ResponseField>

    <ResponseField name="wordpress_user_id" type="integer">
      Associated WordPress user ID (if applicable)
    </ResponseField>
  </Expandable>
</ResponseField>

## Examples

### Get Basic Customer

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://your-site.com/wp-json/latepoint-api/v1/customers/45" \
    -H "X-API-Key: lp_live_1234567890abcdef"
  ```

  ```javascript JavaScript theme={null}
  const customerId = 45;

  const response = await fetch(`https://your-site.com/wp-json/latepoint-api/v1/customers/${customerId}`, {
    headers: {
      'X-API-Key': 'lp_live_1234567890abcdef'
    }
  });

  const customer = await response.json();
  console.log(customer);
  ```

  ```python Python theme={null}
  import requests

  customer_id = 45

  response = requests.get(
      f'https://your-site.com/wp-json/latepoint-api/v1/customers/{customer_id}',
      headers={
          'X-API-Key': 'lp_live_1234567890abcdef'
      }
  )

  customer = response.json()
  print(customer)
  ```

  ```php PHP theme={null}
  <?php
  $customer_id = 45;

  $curl = curl_init();

  curl_setopt_array($curl, [
      CURLOPT_URL => "https://your-site.com/wp-json/latepoint-api/v1/customers/{$customer_id}",
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPHEADER => [
          'X-API-Key: lp_live_1234567890abcdef'
      ]
  ]);

  $response = curl_exec($curl);
  $customer = json_decode($response, true);

  curl_close($curl);
  print_r($customer);
  ?>
  ```
</CodeGroup>

### Get Customer with Complete Information

<CodeGroup>
  ```bash cURL theme={null}
  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"
  ```

  ```javascript JavaScript theme={null}
  const customerId = 45;
  const params = new URLSearchParams({
    include: 'stats,bookings,custom_fields,preferences,notes',
    bookings_limit: 20,
    bookings_status: 'confirmed'
  });

  const response = await fetch(`https://your-site.com/wp-json/latepoint-api/v1/customers/${customerId}?${params}`, {
    headers: {
      'X-API-Key': 'lp_live_1234567890abcdef'
    }
  });

  const customer = await response.json();
  console.log('Complete customer:', customer.data);
  ```

  ```python Python theme={null}
  import requests

  customer_id = 45
  params = {
      'include': 'stats,bookings,custom_fields,preferences',
      'bookings_limit': 20,
      'bookings_status': 'confirmed'
  }

  response = requests.get(
      f'https://your-site.com/wp-json/latepoint-api/v1/customers/{customer_id}',
      headers={'X-API-Key': 'lp_live_1234567890abcdef'},
      params=params
  )

  customer = response.json()
  print(customer)
  ```
</CodeGroup>

### Get Only Future Bookings

<CodeGroup>
  ```bash cURL theme={null}
  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"
  ```

  ```javascript JavaScript theme={null}
  // Get customer with only their upcoming appointments
  const customerId = 45;
  const params = new URLSearchParams({
    include: 'upcoming_bookings,stats',
    bookings_limit: 5
  });

  const response = await fetch(`https://your-site.com/wp-json/latepoint-api/v1/customers/${customerId}?${params}`, {
    headers: {
      'X-API-Key': 'lp_live_1234567890abcdef'
    }
  });

  const customer = await response.json();

  if (customer.status === 'success') {
    const upcomingBookings = customer.data.bookings || [];
    console.log(`${customer.data.first_name} has ${upcomingBookings.length} upcoming appointments`);
    
    upcomingBookings.forEach(booking => {
      console.log(`- ${booking.start_date} ${booking.start_time} - ${booking.service.name}`);
    });
  }
  ```
</CodeGroup>

## Example Response

### Complete Customer

```json theme={null}
{
  "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

<ResponseExample>
  ```json Error 404 - Customer Not Found theme={null}
  {
    "status": "error",
    "error": {
      "code": "customer_not_found",
      "message": "Customer with ID 45 was not found"
    }
  }
  ```

  ```json Error 401 - Unauthorized theme={null}
  {
    "status": "error",
    "error": {
      "code": "unauthorized",
      "message": "Invalid or missing API Key"
    }
  }
  ```

  ```json Error 403 - Insufficient Permissions theme={null}
  {
    "status": "error",
    "error": {
      "code": "insufficient_permissions",
      "message": "You don't have permission to access this customer's information",
      "details": {
        "required_permission": "read_customers",
        "customer_id": 45
      }
    }
  }
  ```

  ```json Error 400 - Invalid Parameters theme={null}
  {
    "status": "error",
    "error": {
      "code": "invalid_parameters",
      "message": "Invalid query parameters",
      "details": {
        "include": "Value 'invalid_field' is not valid",
        "bookings_limit": "Value must be a number between 1 and 100"
      }
    }
  }
  ```
</ResponseExample>

## Common Use Cases

### 1. Complete Customer Profile

```javascript theme={null}
// 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

```javascript theme={null}
// 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

```javascript theme={null}
// 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

```javascript theme={null}
// 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

```javascript theme={null}
// 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

```javascript theme={null}
// 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

```javascript theme={null}
// 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

<Note>
  **Sensitive Information**: Customer data may include sensitive information. Make sure to handle it according to applicable privacy regulations.
</Note>

<Tip>
  **Optimization**: Use the `include` parameter selectively to get only the data you need and improve performance.
</Tip>

<Warning>
  **Cache**: If you implement customer data caching, make sure to invalidate it when customer information is updated.
</Warning>

<Info>
  **Statistics**: Statistics are calculated in real time, so they may affect response time if the customer has many bookings.
</Info>
