Skip to content

Staff Management

Complete guide to managing staff members, skills, commissions, and performance tracking in the Reserva platform.


Overview

The staff management system provides comprehensive tools for managing service providers across multiple outlets:

  • Staff CRUD - Create, read, update, and delete staff members
  • Skills Management - Assign service capabilities and expertise levels
  • Commission Configuration - Set up earnings structures and rates
  • Position Templates - Tenant-specific position naming consistency
  • Availability Tracking - Monitor staff schedules and bookings
  • Performance Analytics - Track ratings, bookings, and utilization
  • Multi-Outlet Assignment - Assign staff to specific outlets

Key Concepts:

  • Staff Member = Service provider with skills, availability, and outlet assignment
  • Position = Flexible role/title (e.g., "Senior Stylist", "Massage Therapist")
  • Skills = Service capabilities that determine booking eligibility
  • Commission = Earnings structure (base rate, service-specific, performance tiers)
  • Bookable = Staff available for customer appointments

Subscription Limits

Staff creation is subject to subscription plan limits:

Plan Max Staff per Outlet
FREE 5
PRO 50
ENTERPRISE Unlimited (-1)

Important Notes:

  • Limits apply per outlet, not per tenant
  • Only active staff count toward limits
  • Deleted/terminated staff don't count
  • Upgrade subscription to increase limits: Subscription Management

List Staff Members

Retrieve paginated list of staff members with advanced filtering options.

Endpoint

GET /api/v1/staff?page=1&size=20&only_active=true

Authentication: Required (JWT token)

Query Parameters

Parameter Type Required Default Description
page integer No 1 Page number for pagination
size integer No 20 Items per page (max 100)
outlet_id string No - Filter by outlet ID
service_id string No - Filter by service capability
status string No - Filter by status (active, inactive, terminated, on_leave)
position string No - Filter by position (partial match)
employment_type string No - Filter by type (full_time, part_time, contractor)
only_active boolean No true Only show active staff
only_bookable boolean No false Only show bookable staff
search string No - Search by name or email
gender string No - Filter by gender (male, female, other, prefer_not_to_say)
include_availability boolean No false Include availability status

Response

{
  "items": [
    {
      "id": "68e61599f4ae9d40e4d8a614",
      "tenant_id": "68e4cfe3886b6f295471fd4c",
      "outlet_id": "68e4d035886b6f295471fd51",
      "first_name": "Jessica",
      "last_name": "Smith",
      "display_name": "Jessica S.",
      "email": "jessica.smith@gmail.com",
      "phone": "+1234567890",
      "gender": "female",
      "position": "Junior Stylist",
      "employment_type": "full_time",
      "employee_id": null,
      "hire_date": "2020-01-15",
      "birth_date": null,
      "hourly_rate": null,
      "salary": null,
      "is_bookable": true,
      "accepts_online_booking": true,
      "max_advance_booking_days": 30,
      "bio": null,
      "profile_image_url": null,
      "instagram_handle": null,
      "is_active": true,
      "status": "active",
      "skills": {
        "service_ids": ["507f1f77bcf86cd799439013"],
        "specialties": ["color correction"],
        "certifications": [],
        "years_experience": 5
      },
      "average_rating": null,
      "rating_count": 0,
      "total_bookings": 0,
      "next_available_slot": null,
      "created_at": "2025-10-08T07:41:13.832000",
      "updated_at": "2025-10-08T07:41:13.832000"
    }
  ],
  "total": 15,
  "page": 1,
  "size": 20,
  "pages": 1
}

Gender Values:

  • male - Male staff member
  • female - Female staff member
  • other - Other gender identity
  • prefer_not_to_say - Prefers not to disclose

Use Case: Gender filtering is useful for services requiring gender consent (e.g., massage therapy, waxing, personal care services).

Status Values:

  • active - Currently employed and working
  • inactive - Temporarily not working
  • terminated - Employment ended
  • on_leave - On approved leave

Employment Types:

  • full_time - Full-time employee
  • part_time - Part-time employee
  • contractor - Independent contractor

Create Staff Member

Create a new staff member with comprehensive validation and tenant isolation.

Endpoint

POST /api/v1/staff

Authentication: Required (JWT token) Access: SUPER_ADMIN, TENANT_ADMIN, OUTLET_MANAGER

Request Body

{
  "first_name": "Jessica",
  "last_name": "Smith",
  "display_name": "Jessica S.",
  "email": "jessica.smith@gmail.com",
  "phone": "+1234567890",
  "gender": "female",
  "position": "Senior Stylist",
  "employment_type": "full_time",
  "outlet_id": "68e4d035886b6f295471fd51",
  "employee_id": null,
  "hire_date": "2020-01-15",
  "birth_date": null,
  "hourly_rate": null,
  "salary": null,
  "is_bookable": true,
  "accepts_online_booking": true,
  "max_advance_booking_days": 30,
  "bio": null,
  "profile_image_url": null,
  "instagram_handle": null,
  "skills": {
    "service_ids": ["507f1f77bcf86cd799439013"],
    "specialties": ["color correction"],
    "certifications": [],
    "years_experience": 5
  }
}

Required Fields:

  • first_name - Staff member's first name
  • last_name - Staff member's last name
  • email - Unique email within tenant
  • position - Any custom string value
  • employment_type - full_time, part_time, or contractor
  • outlet_id - Valid outlet belonging to tenant

Optional Fields:

  • display_name - Public display name (defaults to first name)
  • phone - Contact phone number
  • gender - Staff gender for service matching (male, female, other, prefer_not_to_say)
  • employee_id - Internal employee identifier
  • hire_date - Employment start date
  • birth_date - Date of birth
  • hourly_rate - Hourly compensation rate
  • salary - Annual or monthly salary
  • is_bookable - Can be booked for appointments (default: true)
  • accepts_online_booking - Accepts online bookings (default: true)
  • max_advance_booking_days - Maximum days in advance for bookings (default: 30)
  • bio - Staff member biography/description
  • profile_image_url - Profile photo URL
  • instagram_handle - Instagram username
  • skills - Service capabilities and expertise

Response

{
  "id": "68e60e6f53e90f232d4cb99e",
  "tenant_id": "68e4cfe3886b6f295471fd4c",
  "outlet_id": "68e4d035886b6f295471fd51",
  "first_name": "Jessica",
  "last_name": "Smith",
  "display_name": "Jessica S.",
  "email": "jessica.smith@gmail.com",
  "phone": "+1234567890",
  "gender": "female",
  "position": "Senior Stylist",
  "employment_type": "full_time",
  "employee_id": null,
  "hire_date": "2020-01-15",
  "birth_date": null,
  "hourly_rate": null,
  "salary": null,
  "is_bookable": true,
  "accepts_online_booking": true,
  "max_advance_booking_days": 30,
  "bio": null,
  "profile_image_url": null,
  "instagram_handle": null,
  "is_active": true,
  "status": "active",
  "skills": {
    "service_ids": ["507f1f77bcf86cd799439013"],
    "specialties": ["color correction"],
    "certifications": [],
    "years_experience": 5
  },
  "average_rating": null,
  "rating_count": 0,
  "total_bookings": 0,
  "next_available_slot": null,
  "created_at": "2025-10-08T07:10:39.252000",
  "updated_at": "2025-10-08T07:10:39.252000"
}

Business Rules

  1. Email Uniqueness - Email must be unique within tenant scope
  2. Outlet Validation - Outlet ID must belong to current tenant
  3. Subscription Limits - Staff count must not exceed plan limits per outlet
  4. Position Flexibility - Position accepts any custom string value
  5. Service Validation - Service IDs in skills must be valid and tenant-owned
  6. Automatic Status - New staff automatically set to active status

Position Templates

The position field accepts any custom string value for maximum flexibility. For consistency, use position templates:

Get Position Templates:

GET /api/v1/staff/positions/templates

Returns tenant-specific position suggestions (see Position Templates section).

Error Responses

402 Payment Required:

{
  "detail": "Staff limit reached for this outlet. Maximum 5 staff per outlet allowed in FREE plan. Please upgrade your subscription."
}

409 Conflict:

{
  "detail": "Staff member with this email already exists"
}

400 Bad Request:

{
  "detail": "Invalid outlet ID or outlet does not belong to this tenant"
}

See Also: Subscription Management to increase staff limits


Get Staff Details

Retrieve comprehensive details for a specific staff member.

Endpoint

GET /api/v1/staff/{staff_id}?include_workload=false

Authentication: Required (JWT token)

Path Parameters

  • staff_id (required) - Staff member ID (example: 507f1f77bcf86cd799439011)

Query Parameters

  • include_workload (optional) - Include current workload and assignment status (default: false)

Response

{
  "id": "68e61599f4ae9d40e4d8a614",
  "tenant_id": "68e4cfe3886b6f295471fd4c",
  "outlet_id": "68e4d035886b6f295471fd51",
  "first_name": "Jessica",
  "last_name": "Smith",
  "display_name": "Jessica S.",
  "email": "jessica.smith@gmail.com",
  "phone": "+1234567890",
  "gender": "female",
  "position": "Junior Stylist",
  "employment_type": "full_time",
  "employee_id": null,
  "hire_date": "2020-01-15",
  "birth_date": null,
  "hourly_rate": null,
  "salary": null,
  "is_bookable": true,
  "accepts_online_booking": true,
  "max_advance_booking_days": 30,
  "bio": null,
  "profile_image_url": null,
  "instagram_handle": null,
  "is_active": true,
  "status": "active",
  "skills": {
    "service_ids": ["507f1f77bcf86cd799439013"],
    "specialties": ["color correction"],
    "certifications": [],
    "years_experience": 5
  },
  "average_rating": null,
  "rating_count": 0,
  "total_bookings": 0,
  "next_available_slot": null,
  "created_at": "2025-10-08T07:41:13.832000",
  "updated_at": "2025-10-08T07:41:13.832000"
}

With Workload Information

When include_workload=true, response includes additional metadata:

{
  "id": "68e61599f4ae9d40e4d8a614",
  "first_name": "Jessica",
  "last_name": "Smith",
  ...
  "workload": {
    "today_appointments": 3,
    "upcoming_appointments": 12,
    "total_lifetime_bookings": 234,
    "is_available_today": true,
    "current_status": "active"
  }
}

Workload Fields:

  • today_appointments - Appointments scheduled for today (pending, confirmed, in_progress)
  • upcoming_appointments - Appointments in next 7 days
  • total_lifetime_bookings - Total bookings since staff creation
  • is_available_today - Whether staff is active and bookable today
  • current_status - Current employment status

Update Staff Member

Update staff member information with comprehensive validation.

Endpoint

PUT /api/v1/staff/{staff_id}

Authentication: Required (JWT token) Access: SUPER_ADMIN, TENANT_ADMIN, OUTLET_MANAGER

Path Parameters

  • staff_id (required) - Staff member ID (example: 507f1f77bcf86cd799439011)

Request Body

All fields are optional (partial update):

{
  "first_name": "Jessica",
  "last_name": "Smith-Johnson",
  "display_name": "Jess",
  "email": "jessica.new@gmail.com",
  "phone": "+1987654321",
  "gender": "female",
  "position": "Lead Stylist",
  "employment_type": "full_time",
  "outlet_id": "68e4d035886b6f295471fd51",
  "is_bookable": true,
  "accepts_online_booking": true,
  "max_advance_booking_days": 60,
  "bio": "Award-winning colorist with 10+ years experience",
  "profile_image_url": "https://example.com/jessica.jpg",
  "instagram_handle": "@jessicastylist"
}

Response

Returns complete updated staff profile (same format as Get Staff Details).

Business Rules

  1. Email Uniqueness - Email must remain unique within tenant if changed
  2. Outlet Validation - Outlet changes must reference tenant-owned outlets
  3. Tenant Lock - Tenant ID cannot be modified (security constraint)
  4. Position Flexibility - Position can be any custom string value
  5. Audit Trail - Changes are logged with timestamp and user

Position Updates

The position field accepts any custom string value. For consistency, fetch templates first:

# 1. Get position templates
GET /api/v1/staff/positions/templates

# 2. Update staff with chosen position
PUT /api/v1/staff/68e61599f4ae9d40e4d8a614
{
  "position": "Senior Stylist"
}

See Also: Position Templates


Delete Staff Member

Soft delete a staff member with appointment validation and audit trail preservation.

Endpoint

DELETE /api/v1/staff/{staff_id}

Authentication: Required (JWT token) Access: SUPER_ADMIN, TENANT_ADMIN only

Path Parameters

  • staff_id (required) - Staff member ID (example: 507f1f77bcf86cd799439011)

Response

204 No Content - Staff deleted successfully

Business Rules

  1. Upcoming Appointments - Cannot delete staff with upcoming confirmed/pending appointments
  2. Soft Delete - Record marked as deleted but preserved in database
  3. Status Change - Status automatically changed to TERMINATED
  4. Audit Trail - Deletion timestamp and user recorded
  5. Historical Data - All past appointment data preserved
  6. Booking Prevention - Deleted staff cannot be assigned to new appointments

Error Response

409 Conflict:

{
  "detail": "Cannot delete staff member with 5 upcoming appointments. Please reassign or cancel appointments first."
}

Process:

  1. Cancel or reassign all upcoming appointments
  2. Delete the staff member
  3. Historical data remains accessible for reporting

Get Staff Availability

⚠️ Status: Pending Implementation

Retrieve staff member's availability schedule for a specified date range.

Endpoint

GET /api/v1/staff/{staff_id}/availability?start_date=2024-01-01&end_date=2024-01-31

Authentication: Required (JWT token)

Implementation Status

This endpoint is currently pending as it depends on the Availability Management system (Phase 6), which is not yet completed.

Planned Features:

  • Scheduled working hours and shifts for date range
  • Break times and blocked-out periods
  • Recurring schedule patterns (weekly/monthly)
  • Holiday and special event schedules
  • Time slot availability for booking purposes
  • Timezone-aware schedule information

Expected Release: Phase 6 - Availability Management

Alternative Solutions:

Until this endpoint is available, use these approaches:

  1. Check Staff Status:

    GET /api/v1/staff/{staff_id}
    
    Check is_bookable, is_active, and accepts_online_booking fields

  2. View Appointments:

    GET /api/v1/staff/{staff_id}/appointments?upcoming_only=true
    
    See when staff is already booked

  3. Workload Information:

    GET /api/v1/staff/{staff_id}?include_workload=true
    
    Get today's appointments and upcoming count


Get Staff Appointments

Retrieve paginated list of appointments assigned to a specific staff member.

Endpoint

GET /api/v1/staff/{staff_id}/appointments?page=1&size=20&upcoming_only=true

Authentication: Required (JWT token)

Path Parameters

  • staff_id (required) - Staff member ID (example: 507f1f77bcf86cd799439011)

Query Parameters

Parameter Type Required Default Description
page integer No 1 Page number for pagination
size integer No 20 Items per page (max 100)
status string No - Filter by status (pending, confirmed, completed, cancelled, no_show)
start_date date No - Filter appointments from date (YYYY-MM-DD)
end_date date No - Filter appointments to date (YYYY-MM-DD)
upcoming_only boolean No false Only show future appointments

Response

{
  "items": [
    {
      "id": "507f1f77bcf86cd799439020",
      "tenant_id": "68e4cfe3886b6f295471fd4c",
      "outlet_id": "68e4d035886b6f295471fd51",
      "customer_id": "507f1f77bcf86cd799439015",
      "appointment_date": "2025-10-15",
      "start_time": "10:00:00",
      "end_time": "11:30:00",
      "status": "confirmed",
      "services": [
        {
          "service_id": "507f1f77bcf86cd799439013",
          "staff_id": "68e61599f4ae9d40e4d8a614",
          "service_name": "Hair Coloring",
          "duration_minutes": 90,
          "price": 150000
        }
      ],
      "total_price": 150000,
      "notes": "Client prefers natural tones",
      "created_at": "2025-10-08T07:41:13.832000",
      "updated_at": "2025-10-08T07:41:13.832000"
    }
  ],
  "total": 45,
  "page": 1,
  "size": 20,
  "pages": 3
}

Sorting:

  • When upcoming_only=true: Sorted by appointment date ascending (nearest first)
  • When upcoming_only=false: Sorted by appointment date descending (most recent first)

Update Staff Skills

Update staff member's skills and service capabilities with validation.

Endpoint

PUT /api/v1/staff/{staff_id}/skills

Authentication: Required (JWT token) Access: SUPER_ADMIN, TENANT_ADMIN, OUTLET_MANAGER

Path Parameters

  • staff_id (required) - Staff member ID (example: 507f1f77bcf86cd799439011)

Request Body

{
  "service_ids": [
    "507f1f77bcf86cd799439013",
    "507f1f77bcf86cd799439014",
    "507f1f77bcf86cd799439015"
  ],
  "specialties": [
    "color correction",
    "balayage",
    "keratin treatments"
  ],
  "certifications": [
    "Advanced Color Theory (2023)",
    "Brazilian Blowout Certified"
  ],
  "years_experience": 8
}

Fields:

  • service_ids - Array of service IDs staff can perform
  • specialties - Array of specialty skills/techniques
  • certifications - Array of certifications and credentials
  • years_experience - Total years of experience

Response

Returns complete updated staff profile with new skills (same format as Get Staff Details).

Business Rules

  1. Service Validation - All service IDs must be valid and belong to current tenant
  2. Immediate Effect - Skills update immediately affects booking availability
  3. Booking Eligibility - Staff can only be assigned to appointments for services they're skilled in
  4. Audit Trail - Skill changes logged for compliance tracking

Impact on Bookings

Changing staff skills affects:

  • Service Assignment - Staff only appears for services they're qualified for
  • Appointment Filtering - Staff list filtered by service capabilities
  • Availability Calculation - Skills determine which time slots staff can fill

Important: Removing a service skill does not affect existing appointments with that service.


Update Staff Commission

Update staff member's commission structure and earnings configuration.

Endpoint

PUT /api/v1/staff/{staff_id}/commission

Authentication: Required (JWT token) Access: SUPER_ADMIN, TENANT_ADMIN only

Path Parameters

  • staff_id (required) - Staff member ID (example: 507f1f77bcf86cd799439011)

Request Body

{
  "base_rate": 0.30,
  "service_overrides": {
    "507f1f77bcf86cd799439013": 0.35,
    "507f1f77bcf86cd799439014": 0.40
  },
  "performance_tiers": [
    {
      "threshold": 1000000,
      "bonus_rate": 0.05
    },
    {
      "threshold": 2000000,
      "bonus_rate": 0.10
    }
  ]
}

Fields:

  • base_rate - Base commission rate (0.30 = 30%)
  • service_overrides - Service-specific commission rates (override base rate)
  • performance_tiers - Performance bonus thresholds and rates

Response

Returns complete updated staff profile with new commission structure.

Business Rules

  1. Future Only - Commission changes apply to future appointments only
  2. Historical Preservation - Past earnings remain unaffected
  3. Service Override - Service-specific rates override base rate
  4. Tier Order - Performance tiers must follow ascending threshold order
  5. Security - Only SUPER_ADMIN and TENANT_ADMIN can modify commissions

Sensitive Data Warning

⚠️ Commission information is sensitive financial data. Access is restricted to senior administrative roles only.


Get Staff Statistics

Retrieve comprehensive staff analytics and performance statistics.

Endpoint

GET /api/v1/staff/statistics/summary?outlet_id=507f1f77bcf86cd799439011

Authentication: Required (JWT token) Access: SUPER_ADMIN, TENANT_ADMIN, OUTLET_MANAGER

Query Parameters

  • outlet_id (optional) - Filter statistics to specific outlet

Response

{
  "total_staff": 15,
  "active_staff": 12,
  "bookable_staff": 10,
  "average_rating": 4.7,
  "average_bookings": 234.5,
  "by_status": {
    "active": 12,
    "inactive": 2,
    "on_leave": 1,
    "terminated": 0
  },
  "by_position": {
    "Senior Stylist": 5,
    "Junior Stylist": 4,
    "Colorist": 3,
    "Manager": 2,
    "Receptionist": 1
  },
  "by_employment_type": {
    "full_time": 10,
    "part_time": 3,
    "contractor": 2
  },
  "generated_at": "2025-10-08T07:41:13.832000"
}

Metrics:

  • total_staff - Total active staff members
  • active_staff - Currently active and working
  • bookable_staff - Available for customer bookings
  • average_rating - Average customer rating across all staff
  • average_bookings - Average lifetime bookings per staff member
  • by_status - Staff count grouped by employment status
  • by_position - Staff count grouped by position/role
  • by_employment_type - Staff count grouped by employment type
  • generated_at - Timestamp of statistics generation

Business Value

Use statistics for:

  • Staff Planning - Resource allocation and hiring decisions
  • Performance Benchmarking - KPI tracking across team
  • Capacity Planning - Business growth projections
  • Workforce Composition - Team structure analysis

Note: Statistics are calculated in real-time and reflect current tenant data only.


Get Position Templates

Retrieve the list of predefined staff position templates for the current tenant.

Endpoint

GET /api/v1/staff/positions/templates

Authentication: Required (JWT token)

Response

[
  "Junior Stylist",
  "Senior Stylist",
  "Colorist",
  "Manager",
  "Receptionist"
]

Default Templates

If tenant hasn't configured custom templates, these defaults are returned:

[
  "Service Provider",
  "Senior Provider",
  "Specialist",
  "Manager",
  "Receptionist",
  "Assistant",
  "Trainee"
]

Business Value

  • Consistency - Maintain uniform position naming across organization
  • Easier Filtering - Standardized positions improve reporting and filtering
  • Customizable - Templates adapt to match business terminology
  • Autocomplete - Use for position dropdown/autocomplete in UI

Customization

Position templates are configured in tenant settings. Contact your account manager or use the tenant configuration API to customize templates for your business type (salon, spa, fitness, clinic, etc.).

Usage Pattern

# 1. Fetch templates for autocomplete
GET /api/v1/staff/positions/templates

# Response: ["Junior Stylist", "Senior Stylist", "Colorist", ...]

# 2. Create staff with template position
POST /api/v1/staff
{
  "first_name": "Jessica",
  "last_name": "Smith",
  "position": "Senior Stylist",  // From templates
  ...
}

# 3. Or use custom position
POST /api/v1/staff
{
  "first_name": "John",
  "last_name": "Doe",
  "position": "Master Colorist & Educator",  // Custom value
  ...
}

Note: Templates are suggestions only. Staff can use custom positions if templates don't fit.


Best Practices

For Staff Creation

DO:

  • Check subscription limits before creating staff
  • Use position templates for consistency
  • Validate outlet ownership before assignment
  • Ensure email uniqueness within tenant
  • Set appropriate skills for service eligibility
  • Configure commission structures upfront

DON'T:

  • Create staff without checking subscription limits
  • Use inconsistent position naming
  • Skip skills configuration (limits booking eligibility)
  • Assign to outlets belonging to other tenants

For Skills Management

DO:

  • Keep skills updated with current capabilities
  • Use service IDs from tenant's service catalog
  • Document specialties and certifications
  • Update skills immediately when training is completed
  • Verify skills match actual service capabilities

DON'T:

  • Add skills for services staff can't perform
  • Reference service IDs from other tenants
  • Leave skills outdated after training
  • Forget to update skills when services change

For Staff Updates

DO:

  • Validate email changes for uniqueness
  • Check outlet ownership when reassigning
  • Maintain audit trail for sensitive changes
  • Update position using templates when possible
  • Preserve historical data when changing status

DON'T:

  • Allow duplicate emails within tenant
  • Change tenant_id (security violation)
  • Delete staff with upcoming appointments
  • Skip validation when changing outlets

Common Workflows

Onboarding New Staff

# 1. Check current staff count and limits
GET /api/v1/staff/statistics/summary?outlet_id=68e4d035886b6f295471fd51

# 2. Get position templates
GET /api/v1/staff/positions/templates

# 3. Create staff member
POST /api/v1/staff
{
  "first_name": "Jessica",
  "last_name": "Smith",
  "email": "jessica@example.com",
  "position": "Senior Stylist",
  "employment_type": "full_time",
  "outlet_id": "68e4d035886b6f295471fd51",
  "hire_date": "2025-10-15",
  "is_bookable": true
}

# 4. Configure skills
PUT /api/v1/staff/68e60e6f53e90f232d4cb99e/skills
{
  "service_ids": ["507f1f77bcf86cd799439013", "507f1f77bcf86cd799439014"],
  "specialties": ["balayage", "color correction"],
  "years_experience": 5
}

# 5. Set commission (admin only)
PUT /api/v1/staff/68e60e6f53e90f232d4cb99e/commission
{
  "base_rate": 0.30,
  "service_overrides": {
    "507f1f77bcf86cd799439013": 0.35
  }
}

Managing Staff Schedule

# 1. View staff details with workload
GET /api/v1/staff/68e60e6f53e90f232d4cb99e?include_workload=true

# 2. Check upcoming appointments
GET /api/v1/staff/68e60e6f53e90f232d4cb99e/appointments?upcoming_only=true

# 3. View availability (pending implementation)
# GET /api/v1/staff/68e60e6f53e90f232d4cb99e/availability?start_date=2025-10-15&end_date=2025-10-22

Offboarding Staff

# 1. Check for upcoming appointments
GET /api/v1/staff/68e60e6f53e90f232d4cb99e/appointments?upcoming_only=true

# 2. Reassign or cancel upcoming appointments
PUT /api/v1/appointments/{appointment_id}
{
  "services": [
    {
      "service_id": "507f1f77bcf86cd799439013",
      "staff_id": "68e61599f4ae9d40e4d8a614"  // Different staff
    }
  ]
}

# 3. Delete staff member
DELETE /api/v1/staff/68e60e6f53e90f232d4cb99e

Troubleshooting

Staff Limit Reached

Symptom: Cannot create new staff member

Error:

{
  "detail": "Staff limit reached for this outlet. Maximum 5 staff per outlet allowed in FREE plan. Please upgrade your subscription."
}

Solution:

  1. Check current subscription: GET /api/v1/subscriptions/current
  2. Upgrade plan: Subscription Management
  3. Or delete inactive staff to free up slots

Duplicate Email Error

Symptom: Staff creation fails with 409 Conflict

Error:

{
  "detail": "Staff member with this email already exists"
}

Solution:

  1. Search for existing staff: GET /api/v1/staff?search=email@example.com
  2. Use different email or update existing staff
  3. Check if staff was soft-deleted and reactivate instead

Cannot Delete Staff

Symptom: Staff deletion fails with upcoming appointments

Error:

{
  "detail": "Cannot delete staff member with 5 upcoming appointments. Please reassign or cancel appointments first."
}

Solution:

  1. List upcoming appointments: GET /api/v1/staff/{staff_id}/appointments?upcoming_only=true
  2. Reassign appointments to other staff
  3. Or cancel appointments
  4. Retry deletion

Skills Not Affecting Bookings

Symptom: Staff not appearing for service assignments

Checks:

  1. Verify staff has service in skills: GET /api/v1/staff/{staff_id}
  2. Check staff is bookable: is_bookable: true
  3. Verify staff is active: is_active: true, status: "active"
  4. Confirm service belongs to same tenant

Fix:

PUT /api/v1/staff/{staff_id}/skills
{
  "service_ids": ["507f1f77bcf86cd799439013"]
}


API Reference Summary

Endpoint Method Purpose Access Level
/staff GET List staff members All staff
/staff POST Create staff member SUPER_ADMIN, TENANT_ADMIN, OUTLET_MANAGER
/staff/{staff_id} GET Get staff details All staff
/staff/{staff_id} PUT Update staff member SUPER_ADMIN, TENANT_ADMIN, OUTLET_MANAGER
/staff/{staff_id} DELETE Delete staff member SUPER_ADMIN, TENANT_ADMIN
/staff/{staff_id}/availability GET Get availability ⚠️ All staff
/staff/{staff_id}/appointments GET Get appointments All staff
/staff/{staff_id}/skills PUT Update skills SUPER_ADMIN, TENANT_ADMIN, OUTLET_MANAGER
/staff/{staff_id}/commission PUT Update commission SUPER_ADMIN, TENANT_ADMIN
/staff/statistics/summary GET Get statistics SUPER_ADMIN, TENANT_ADMIN, OUTLET_MANAGER
/staff/positions/templates GET Get position templates All staff

⚠️ Pending Implementation - Awaiting Availability Management (Phase 6)



Next Steps:

  1. Check subscription limits: GET /api/v1/subscriptions/current
  2. Get position templates: GET /api/v1/staff/positions/templates
  3. Create first staff member: POST /api/v1/staff
  4. Configure skills: PUT /api/v1/staff/{staff_id}/skills
  5. Monitor performance: GET /api/v1/staff/statistics/summary