Skip to content

Customer Profile Management

Complete guide to managing customer profiles, preferences, consent, and GDPR compliance in the Reserva platform.


Overview

The customer profile system provides comprehensive self-service management with GDPR compliance:

  • Profile Management - View and update personal information
  • Preference Management - Booking preferences, communication channels, localization
  • Consent Management - Marketing, data processing, and analytics preferences
  • Account Deletion - GDPR-compliant right to be forgotten

Key Concepts:

  • Profile = Personal information (name, phone, date of birth, gender)
  • Preferences = Booking defaults, communication settings, localization
  • Consent = Privacy controls for marketing, analytics, and data processing
  • GDPR Compliance = Full data deletion and anonymization capabilities

Get Customer Profile

Retrieve the authenticated customer's complete profile information with loyalty and booking statistics.

Endpoint

GET /api/v1/customers/profile

Authentication: Required (Customer JWT token)

Response

{
  "id": "507f1f77bcf86cd799439011",
  "email": "jane.smith@example.com",
  "first_name": "Jane",
  "last_name": "Smith",
  "phone": "+6281234567890",
  "date_of_birth": "1990-05-15",
  "gender": "female",
  "email_verified": true,
  "phone_verified": false,
  "preferences": {
    "preferred_outlet_id": "507f1f77bcf86cd799439012",
    "preferred_staff_ids": ["507f1f77bcf86cd799439013"],
    "preferred_services": ["507f1f77bcf86cd799439014"],
    "communication_preferences": {
      "email": true,
      "sms": false,
      "push": true,
      "whatsapp": false
    },
    "marketing_consent": false,
    "language": "en",
    "timezone": "Asia/Jakarta"
  },
  "loyalty_points": 450,
  "membership_tier": "silver",
  "total_appointments": 12,
  "last_appointment_date": "2025-09-30",
  "created_at": "2024-06-01T00:00:00Z"
}

Membership Tiers:

Loyalty tier calculation based on accumulated points:

  • basic - 0-99 points
  • silver - 100-499 points
  • gold - 500-999 points
  • platinum - 1000+ points

Features:

  • Complete customer profile with personal details
  • Email and phone verification status
  • Loyalty points and membership tier calculation
  • Booking history summary statistics
  • Customer preferences and settings
  • Account creation and verification timestamps

Business Rules:

  • Profile data is filtered for privacy compliance
  • Loyalty tier calculated based on points
  • Booking statistics include all non-deleted appointments
  • Verification status reflects current email/phone validation

Update Customer Profile

Update the authenticated customer's personal profile information with validation.

Endpoint

POST /api/v1/customers/profile

Authentication: Required (Customer JWT token)

Request Body

{
  "first_name": "Jane",
  "last_name": "Smith",
  "phone": "+6281234567890",
  "date_of_birth": "1990-05-15",
  "gender": "female"
}

Parameters:

  • first_name (optional) - Customer's first name (1-50 characters)
  • last_name (optional) - Customer's last name (1-50 characters)
  • phone (optional) - Phone number in E.164 format (e.g., +6281234567890)
  • date_of_birth (optional) - Date of birth in YYYY-MM-DD format
  • gender (optional) - Gender: male, female, other, prefer_not_to_say

Response

Returns the updated customer profile (same format as GET profile):

{
  "id": "507f1f77bcf86cd799439011",
  "email": "jane.smith@example.com",
  "first_name": "Jane",
  "last_name": "Smith",
  "phone": "+6281234567890",
  "date_of_birth": "1990-05-15",
  "gender": "female",
  "email_verified": true,
  "phone_verified": false,
  "loyalty_points": 450,
  "membership_tier": "silver",
  "total_appointments": 12,
  "created_at": "2024-06-01T00:00:00Z"
}

Business Rules:

  • Email cannot be changed through this endpoint (security)
  • Phone changes reset verification status to false
  • Names are trimmed and validated for length
  • At least one field must be provided for update
  • Date of birth validation for reasonable age ranges
  • All fields are optional (partial updates supported)

Process:

  1. Validate at least one field is provided
  2. Sanitize and validate all input fields
  3. Reset verification status for changed contact info
  4. Update customer record with new information
  5. Return updated profile with computed fields

Get Customer Preferences

Retrieve the authenticated customer's complete preferences and settings.

Endpoint

GET /api/v1/customers/preferences

Authentication: Required (Customer JWT token)

Response

{
  "preferred_outlet_id": "507f1f77bcf86cd799439012",
  "preferred_staff_ids": ["507f1f77bcf86cd799439013", "507f1f77bcf86cd799439014"],
  "preferred_services": ["507f1f77bcf86cd799439015"],
  "communication_preferences": {
    "email": true,
    "sms": false,
    "push": true,
    "whatsapp": false
  },
  "marketing_consent": false,
  "data_processing_consent": true,
  "analytics_consent": false,
  "language": "en",
  "timezone": "Asia/Jakarta",
  "notification_settings": {
    "booking_reminders": true,
    "promotional_offers": false,
    "appointment_updates": true,
    "loyalty_updates": true
  },
  "notes": null
}

Features:

  • Booking preferences with outlet, staff, and service selections
  • Communication channel preferences
  • Privacy and consent management
  • Notification and alert settings
  • Localization preferences (language, timezone)
  • Default values for unset preferences

Business Rules:

  • Default preferences applied for missing values
  • Communication preferences default to privacy-safe settings
  • Consent preferences default to minimal required permissions
  • Language defaults to English, timezone to UTC
  • Preferred entities must exist and be accessible

Default Values:

{
  "communication_preferences": {
    "email": true,
    "sms": false,
    "push": true,
    "whatsapp": false
  },
  "marketing_consent": false,
  "data_processing_consent": true,
  "analytics_consent": false,
  "language": "en",
  "timezone": "UTC",
  "notification_settings": {
    "booking_reminders": true,
    "promotional_offers": false,
    "appointment_updates": true,
    "loyalty_updates": true
  }
}

Update Customer Preferences

Update the authenticated customer's preferences and settings with validation.

Endpoint

PUT /api/v1/customers/preferences

Authentication: Required (Customer JWT token)

Request Body

{
  "preferred_outlet_id": "507f1f77bcf86cd799439012",
  "preferred_staff_ids": ["507f1f77bcf86cd799439013", "507f1f77bcf86cd799439014"],
  "preferred_services": ["507f1f77bcf86cd799439015"],
  "communication_preferences": {
    "email": true,
    "sms": false,
    "push": true,
    "whatsapp": false
  },
  "marketing_consent": false,
  "language": "en",
  "timezone": "Asia/Jakarta",
  "notification_settings": {
    "booking_reminders": true,
    "promotional_offers": false
  }
}

Parameters:

  • preferred_outlet_id (optional) - Default outlet for bookings (ObjectId string)
  • preferred_staff_ids (optional) - List of preferred staff members (array of ObjectId strings)
  • preferred_services (optional) - List of favorite services (array of ObjectId strings)
  • communication_preferences (optional) - Channel preferences (email, sms, push, whatsapp)
  • marketing_consent (optional) - Consent for promotional communications (boolean)
  • language (optional) - Language code: en, id, ms
  • timezone (optional) - IANA timezone string (e.g., "Asia/Jakarta")
  • notification_settings (optional) - Notification preferences by category

Response

Returns the updated preferences object (same format as GET preferences).

Business Rules:

  • Preferred outlets must exist and be active in tenant
  • Preferred staff must exist and be active in tenant
  • Preferred services must exist and be active in tenant
  • Communication preferences merge with existing settings
  • Language must be supported (en, id, ms)
  • Timezone validation for valid timezone strings
  • All parameters are optional (partial updates supported)

Entity Validation:

The endpoint validates that all referenced entities exist and are accessible:

# Outlet validation
if preferred_outlet_id:
    outlet = await db.outlets.find_one({
        "_id": ObjectId(preferred_outlet_id),
        "tenant_id": tenant_id,
        "is_active": True,
        "is_deleted": {"$ne": True}
    })
    if not outlet:
        raise HTTPException(400, "Invalid outlet ID")

# Staff validation
if preferred_staff_ids:
    staff_count = await db.staff.count_documents({
        "_id": {"$in": [ObjectId(id) for id in preferred_staff_ids]},
        "tenant_id": tenant_id,
        "is_active": True,
        "is_deleted": {"$ne": True}
    })
    if staff_count != len(preferred_staff_ids):
        raise HTTPException(400, "Invalid staff IDs")

Process:

  1. Validate current customer exists
  2. Merge new preferences with existing preferences
  3. Validate entity references (outlets, staff, services)
  4. Apply preference updates with validation
  5. Save updated preferences to customer record

Update customer consent preferences for marketing, data processing, and communications with GDPR compliance.

Endpoint

PUT /api/v1/customers/consent

Authentication: Required (Customer JWT token)

Request Body

{
  "marketing_consent": false,
  "data_processing_consent": true,
  "analytics_consent": false,
  "communication_consent": {
    "email": true,
    "sms": false,
    "push": true,
    "whatsapp": false
  }
}

Parameters:

  • marketing_consent (optional) - Consent for marketing communications (boolean)
  • data_processing_consent (optional) - Consent for data processing and optimization (boolean)
  • analytics_consent (optional) - Consent for analytics tracking (boolean)
  • communication_consent (optional) - Channel-specific communication preferences

Response

{
  "marketing_consent": false,
  "data_processing_consent": true,
  "analytics_consent": false,
  "communication_preferences": {
    "email": true,
    "sms": false,
    "push": true,
    "whatsapp": false
  },
  "last_updated": "2025-10-18T10:30:00Z",
  "message": "Consent preferences updated successfully"
}

Features:

  • Granular consent management by category
  • Timestamp tracking for all consent changes
  • Communication channel-specific preferences
  • GDPR-compliant consent recording
  • Comprehensive audit logging
  • Withdrawal capability for all consent types

Business Rules:

  • Consent can be granted or withdrawn at any time
  • All changes recorded with precise timestamps
  • Marketing consent affects promotional communications
  • Data processing consent affects analytics and optimization
  • Communication consent controls channel preferences
  • At least one consent field must be provided for update

Audit Trail:

All consent changes are logged for GDPR compliance:

{
  "action": "CUSTOMER_CONSENT_UPDATED",
  "entity_type": "customer",
  "entity_id": "507f1f77bcf86cd799439011",
  "tenant_id": "507f1f77bcf86cd799439010",
  "details": {
    "consent_changes": {
      "marketing": false,
      "analytics": false
    },
    "consent_timestamp": "2025-10-18T10:30:00Z"
  },
  "created_at": "2025-10-18T10:30:00Z"
}

Process:

  1. Validate at least one consent field is provided
  2. Update consent preferences with timestamps
  3. Merge communication preferences with existing settings
  4. Save updated preferences to customer record
  5. Log consent changes for audit compliance

Note: Implements GDPR consent management requirements (Articles 7 & 13).


Delete Customer Account

Permanently delete customer account and all associated data (GDPR Right to be Forgotten).

Endpoint

DELETE /api/v1/customers/account

Authentication: Required (Customer JWT token)

Request Body

No request body required.

Response

{
  "success": true,
  "message": "Account deletion completed successfully. All personal data has been permanently removed in compliance with GDPR."
}

Features:

  • Complete account deletion with data anonymization
  • GDPR-compliant data removal process
  • Past appointment anonymization for business records
  • Payment record anonymization for accounting
  • Comprehensive audit logging
  • Immediate session termination

Business Rules:

  • Cannot delete with pending or processing payments
  • Cannot delete with future appointments (not cancelled/no-show)
  • Past appointments anonymized but preserved for business records
  • Completed payments anonymized but preserved for accounting
  • All other customer data permanently deleted
  • Action is irreversible once completed

Pre-Deletion Checks:

# Check 1: Pending payments
pending_payments = await db.payments.count_documents({
    "customer_id": customer_id,
    "status": {"$in": ["pending", "processing"]}
})
if pending_payments > 0:
    raise HTTPException(400, "Cannot delete with pending payments")

# Check 2: Future appointments
future_appointments = await db.appointments.count_documents({
    "customer_id": customer_id,
    "appointment_date": {"$gte": today},
    "status": {"$nin": ["cancelled", "no_show"]}
})
if future_appointments > 0:
    raise HTTPException(400, "Cannot delete with upcoming appointments")

GDPR Deletion Process (10 Steps)

The deletion follows a comprehensive data removal process:

  1. Anonymize Past Appointments - Remove PII, keep business data

    await db.appointments.update_many(
        {"customer_id": customer_id},
        {
            "$set": {
                "customer_id": None,
                "customer_name": "DELETED_USER",
                "customer_email": "deleted@privacy.local",
                "customer_phone": None,
                "notes": "Customer data deleted per GDPR request"
            }
        }
    )
    

  2. Delete Customer Sessions - Remove all active sessions

  3. Delete Customer Wallet - Remove wallet and balance

  4. Delete Customer Reviews - Remove all reviews and ratings

  5. Delete Customer Notifications - Remove notification history

  6. Delete Saved Payment Methods - Remove stored payment data

  7. Anonymize Completed Payments - Keep for accounting, remove PII

    await db.payments.update_many(
        {
            "customer_id": customer_id,
            "status": "completed"
        },
        {
            "$set": {
                "customer_id": None,
                "customer_email": "deleted@privacy.local",
                "customer_name": "DELETED_USER",
                "customer_phone": None
            }
        }
    )
    

  8. Delete Incomplete Payments - Permanently remove non-completed payments

  9. Delete Customer Record - Hard delete customer document

  10. Audit Logging - Record deletion for compliance

    {
      "action": "CUSTOMER_ACCOUNT_DELETED",
      "entity_type": "customer",
      "entity_id": "507f1f77bcf86cd799439011",
      "details": {
        "email": "jane.smith@example.com",
        "deletion_timestamp": "2025-10-18T10:30:00Z",
        "gdpr_deletion": true,
        "reason": "Customer requested account deletion (GDPR Right to be Forgotten)"
      }
    }
    

Data Retention for Business Compliance:

Data Type Action Reason
Customer Record Hard delete GDPR compliance
Past Appointments Anonymize Business records, analytics
Completed Payments Anonymize Accounting, tax compliance
Incomplete Payments Hard delete No compliance requirement
Sessions Hard delete No longer needed
Wallet Hard delete GDPR compliance
Reviews Hard delete User-generated content
Notifications Hard delete Personal communications

Important Notes:

  • This implements GDPR Article 17 "Right to be Forgotten"
  • Deletion is immediate and irreversible
  • Customer will be immediately logged out after deletion
  • Business records (appointments, payments) are anonymized, not deleted
  • Audit logs are retained for compliance purposes

Subscription Plan Limitations

Customer profile features are available across all subscription plans with no restrictions:

Feature FREE PRO ENTERPRISE
Profile Management ✅ Full access ✅ Full access ✅ Full access
Preference Updates ✅ Full access ✅ Full access ✅ Full access
Consent Management ✅ Full access ✅ Full access ✅ Full access
Account Deletion ✅ Full access ✅ Full access ✅ Full access
Loyalty Points ✅ Enabled ✅ Enabled ✅ Enabled
Membership Tiers ✅ All tiers ✅ All tiers ✅ All tiers

Note: Customer profile management is a core feature available to all customers regardless of the tenant's subscription plan. Subscription limits apply to tenant-level features (outlets, staff, appointments) as documented in Subscription Management.



Security & Privacy

Data Protection

Personal Information Security:

  • All profile data encrypted at rest
  • JWT tokens for authentication
  • Password hashing with bcrypt
  • Secure session management
  • Rate limiting on profile updates

GDPR Compliance:

  • Right to access (GET /profile)
  • Right to rectification (PUT /profile)
  • Right to data portability (GET /profile returns all data)
  • Right to erasure (DELETE /account)
  • Right to withdraw consent (PUT /consent)
  • Consent tracking with timestamps
  • Comprehensive audit logging

Privacy Controls

Customer Privacy Features:

  • Granular consent management
  • Communication channel preferences
  • Marketing opt-out capability
  • Analytics opt-out capability
  • Data processing transparency
  • Account deletion with anonymization

Data Anonymization:

When customers delete their accounts, the system:

  • Removes all PII (name, email, phone)
  • Preserves business data (anonymized appointments, payments)
  • Maintains referential integrity (foreign keys set to null)
  • Keeps audit trails (compliance requirement)

Best Practices

For Customers

DO:

  • Keep profile information up-to-date for better service
  • Verify email and phone for appointment reminders
  • Set preferred outlets and staff for faster booking
  • Review consent preferences regularly
  • Update communication preferences to reduce unwanted messages
  • Cancel pending payments before account deletion

DON'T:

  • Share account credentials with others
  • Use fake or incorrect personal information
  • Ignore verification emails/SMS
  • Delete account with pending bookings or payments
  • Provide invalid phone numbers (affects SMS notifications)

For Developers

DO:

  • Always validate entity references (outlets, staff, services)
  • Log all consent changes for GDPR compliance
  • Implement idempotency for profile updates
  • Use transactions for multi-step operations
  • Sanitize and trim all user input
  • Reset verification status when contact info changes
  • Preserve business records during deletion

DON'T:

  • Allow email changes without re-verification
  • Skip validation of preferred entities
  • Delete business records (anonymize instead)
  • Process deletion without checking dependencies
  • Skip audit logging for consent changes
  • Trust client-provided verification status

Troubleshooting

Profile Update Fails

Symptoms: 400 Bad Request when updating profile

Common Causes:

  1. Invalid phone number format (must be E.164: +6281234567890)
  2. Invalid gender value (must be: male, female, other, prefer_not_to_say)
  3. No fields provided for update
  4. Name exceeds 50 characters

Fix:

  • Validate phone number format before submission
  • Use allowed gender values only
  • Provide at least one field for update
  • Keep names under 50 characters

Preference Update Rejected

Symptoms: 400 Bad Request with "Invalid outlet/staff/service ID"

Common Causes:

  1. Referenced outlet doesn't exist or is inactive
  2. Staff member not active in tenant
  3. Service not available in tenant
  4. Using wrong tenant's entity IDs

Fix:

  • Verify entity IDs belong to current tenant
  • Ensure entities are active and not deleted
  • Use GET endpoints to fetch valid entity IDs first
  • Check entity status before setting as preferred

Account Deletion Blocked

Symptoms: 400 Bad Request "Cannot delete account"

Common Causes:

  1. Pending or processing payments exist
  2. Future appointments not cancelled
  3. Incomplete payment transactions

Fix:

  • Cancel or complete all pending payments first
  • Cancel all future appointments before deletion
  • Wait for payment processing to complete
  • Contact support if issues persist

Symptoms: Consent changes don't affect communications

Common Causes:

  1. Background jobs haven't processed changes yet
  2. Communication system cache not invalidated
  3. Email already in send queue before consent withdrawal

Fix:

  • Wait 5-10 minutes for changes to propagate
  • Check consent preferences with GET /preferences
  • Contact support to stop queued communications
  • Review audit logs to confirm consent was recorded

API Reference Summary

Endpoint Method Purpose Authentication
/customers/profile GET Get customer profile Customer JWT
/customers/profile PUT Update customer profile Customer JWT
/customers/preferences GET Get customer preferences Customer JWT
/customers/preferences PUT Update customer preferences Customer JWT
/customers/consent PUT Update consent preferences Customer JWT
/customers/account DELETE Delete customer account Customer JWT

Example Workflows

Complete Profile Setup

# 1. Register and login (see customer-authentication.md)

# 2. Get current profile
curl -X GET http://localhost:8000/api/v1/customers/profile \
  -H "Authorization: Bearer $CUSTOMER_TOKEN"

# 3. Update personal information
curl -X PUT http://localhost:8000/api/v1/customers/profile \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Smith",
    "phone": "+6281234567890",
    "date_of_birth": "1990-05-15",
    "gender": "female"
  }'

# 4. Set booking preferences
curl -X PUT http://localhost:8000/api/v1/customers/preferences \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "preferred_outlet_id": "507f1f77bcf86cd799439012",
    "preferred_staff_ids": ["507f1f77bcf86cd799439013"],
    "language": "en",
    "timezone": "Asia/Jakarta",
    "communication_preferences": {
      "email": true,
      "sms": false,
      "push": true
    }
  }'

# 5. Update consent preferences
curl -X PUT http://localhost:8000/api/v1/customers/consent \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "marketing_consent": false,
    "analytics_consent": false
  }'

Privacy-Focused Configuration

# Opt out of all non-essential communications
curl -X PUT http://localhost:8000/api/v1/customers/consent \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "marketing_consent": false,
    "analytics_consent": false,
    "communication_consent": {
      "email": true,
      "sms": false,
      "push": false,
      "whatsapp": false
    }
  }'

# Minimal notification settings
curl -X PUT http://localhost:8000/api/v1/customers/preferences \
  -H "Authorization: Bearer $CUSTOMER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "notification_settings": {
      "booking_reminders": true,
      "promotional_offers": false,
      "appointment_updates": true,
      "loyalty_updates": false
    }
  }'

Account Deletion Workflow

# 1. Check for pending obligations
curl -X GET http://localhost:8000/api/v1/customers/appointments/upcoming \
  -H "Authorization: Bearer $CUSTOMER_TOKEN"

# 2. Cancel future appointments if any
curl -X PUT http://localhost:8000/api/v1/customers/appointments/{id}/cancel \
  -H "Authorization: Bearer $CUSTOMER_TOKEN"

# 3. Verify no pending payments
curl -X GET http://localhost:8000/api/v1/customers/payments?status=pending \
  -H "Authorization: Bearer $CUSTOMER_TOKEN"

# 4. Delete account
curl -X DELETE http://localhost:8000/api/v1/customers/account \
  -H "Authorization: Bearer $CUSTOMER_TOKEN"

Next Steps:

  1. Complete customer profile after registration
  2. Set booking preferences for faster checkout
  3. Configure notification preferences
  4. Review and update consent settings
  5. Verify email and phone for appointment reminders

For authentication and registration, see Customer Authentication. For booking appointments, see Customer Booking.