Skip to content

Service Management

Complete guide to managing service catalogs, categories, pricing, and availability in the Reserva platform.


Overview

The service management system provides comprehensive catalog management with support for:

  • Service CRUD - Create, read, update, and delete services
  • Category Organization - Template-based category management for consistent organization
  • Multi-Portal Access - Staff (full management) and customer (read-only) access
  • Outlet-Specific Pricing - Location-based pricing flexibility
  • Advanced Filtering - Search by category, price range, duration, and outlet
  • Status Management - Control service availability and lifecycle

Key Concepts:

  • Category Templates = Tenant-specific category suggestions for consistency
  • Outlet Pricing = Location-based price overrides with base price fallback
  • Service Status = Active, inactive, or archived lifecycle management
  • Dual Portal = Staff (management) and customer (browsing) access modes

Subscription Plan Limits

Service catalog features are restricted by subscription plan tier:

Plan Max Services Outlet Pricing Custom Categories
FREE 10 services ❌ No ✅ Default templates
PRO 50 services ✅ Yes ✅ Custom templates
ENTERPRISE Unlimited ✅ Yes ✅ Custom templates

Limit Enforcement:

  • Creating a service on FREE plan will fail if tenant already has 10 services
  • Check current usage: GET /api/v1/subscriptions/usage
  • Upgrade required for unlimited services: See Subscription Management

Related Limits:

Quick Navigation - Pricing

Topic Link
Pricing hierarchy (Promo → Outlet → Base) Pricing Management - Pricing Hierarchy
Set promotional pricing Pricing Management - Set Promotional Pricing
Promotional pricing scenarios Pricing Management - Pricing Scenarios
Pricing best practices Pricing Management - Best Practices
Test pricing logic Pricing Management - Testing
Troubleshoot pricing issues Pricing Management - Troubleshooting

Available Endpoints

Endpoint Method Purpose Access
/services GET List services with filtering Staff + Customers
/services POST Create new service Staff only
/services/categories GET List categories with counts Staff + Customers
/services/categories/templates GET Get category templates Staff + Customers
/services/{service_id} GET Get service details Staff + Customers
/services/{service_id} PUT Update service Staff only
/services/{service_id} DELETE Delete service (soft) TENANT_ADMIN only
/services/{service_id}/pricing POST Set outlet-specific pricing Staff only

List Services

Retrieve a paginated list of services with advanced filtering options.

Endpoint

GET /api/v1/services?page=1&size=20&category=facial&search=premium&min_price=50&max_price=150

Authentication: Required (JWT token - Staff or Customer)

Query Parameters

  • page (optional) - Page number (default: 1)
  • size (optional) - Page size (default: 20, max: 100)
  • category (optional) - Filter by service category
  • search (optional) - Search in name, description, or tags
  • outlet_id (optional) - Filter by outlet availability
  • min_price (optional) - Minimum price filter (≥ 0)
  • max_price (optional) - Maximum price filter (≥ 0)
  • min_duration (optional) - Minimum duration in minutes (≥ 5)
  • max_duration (optional) - Maximum duration in minutes (≤ 480)
  • status (optional) - Filter by status (staff only): active, inactive, archived

Response

{
  "items": [
    {
      "id": "68e63f26241da4ebe30521c8",
      "tenant_id": "68e4cfe3886b6f295471fd4c",
      "name": "Premium Facial Treatment",
      "slug": "premium-facial",
      "description": "Luxurious 90-minute facial with premium products",
      "category": "facial",
      "duration_minutes": 90,
      "preparation_minutes": 15,
      "cleanup_minutes": 10,
      "max_advance_booking_days": 30,
      "min_advance_booking_hours": 2,
      "requires_staff": true,
      "required_staff_count": 1,
      "allow_parallel_bookings": false,
      "max_parallel_bookings": 1,
      "pricing": {
        "base_price": "75.00",
        "currency": "USD",
        "outlet_prices": {
          "68e4f07e1245f30b04760bd5": "85.00"
        },
        "promotional_price": null,
        "promotional_valid_until": null
      },
      "tags": ["luxury", "facial", "skincare"],
      "image_url": "https://example.com/images/premium-facial.jpg",
      "is_active": true,
      "status": "active",
      "average_rating": 4.8,
      "rating_count": 24,
      "created_at": "2025-10-08T10:38:30.619000",
      "updated_at": "2025-10-08T10:44:55.679000"
    }
  ],
  "total": 45,
  "page": 1,
  "size": 20,
  "pages": 3
}

Access Control

Staff Users:

  • See all services regardless of status
  • Can filter by status parameter
  • View complete service details including pricing

Customer Users:

  • See only active services (status: active, is_active: true)
  • Status filter is ignored
  • View public service information

Business Rules

  • Search is case-insensitive across name, description, and tags
  • Price filtering applies to base_price (not outlet-specific prices)
  • Outlet filtering shows services available at all outlets OR specific outlet
  • Results are sorted alphabetically by name
  • Empty search returns all services (with filters applied)

Create Service

Create a new service in the catalog with comprehensive configuration.

Endpoint

POST /api/v1/services

Authentication: Required (TENANT_ADMIN or OUTLET_MANAGER)

Request Body

{
  "name": "Premium Facial Treatment",
  "slug": "premium-facial",
  "description": "Luxurious 90-minute facial with premium products",
  "category": "facial",
  "duration_minutes": 90,
  "preparation_minutes": 15,
  "cleanup_minutes": 10,
  "max_advance_booking_days": 30,
  "min_advance_booking_hours": 2,
  "requires_staff": true,
  "required_staff_count": 1,
  "allow_parallel_bookings": false,
  "max_parallel_bookings": 1,
  "pricing": {
    "base_price": 75.00,
    "currency": "USD"
  },
  "tags": ["luxury", "facial", "skincare"],
  "image_url": "https://example.com/images/premium-facial.jpg",
  "is_active": true,
  "status": "active"
}

Parameters

Field Type Required Description
name string ✅ Yes Service name (max 200 chars)
slug string ✅ Yes URL-friendly identifier (unique per tenant)
description string ❌ No Detailed service description
category string ✅ Yes Service category (use templates)
duration_minutes integer ✅ Yes Service duration (5-480 minutes)
preparation_minutes integer ❌ No Setup time before service (default: 0)
cleanup_minutes integer ❌ No Cleanup time after service (default: 0)
max_advance_booking_days integer ❌ No Max days in advance for booking (default: 90)
min_advance_booking_hours integer ❌ No Min hours notice required (default: 1)
requires_staff boolean ❌ No Whether staff is required (default: true)
required_staff_count integer ❌ No Number of staff needed (default: 1)
allow_parallel_bookings boolean ❌ No Allow multiple bookings simultaneously (default: false) - See Parallel Booking
max_parallel_bookings integer ❌ No Max parallel bookings if allowed (default: 1) - See Parallel Booking
pricing.base_price decimal ✅ Yes Base price for service - See Pricing Management
pricing.currency string ✅ Yes Currency code (e.g., USD, IDR)
pricing.promotional_price decimal ❌ No Time-limited promotional price - See Promotional Pricing
pricing.promotional_valid_until datetime ❌ No Promotion expiration date (UTC) - See Promotional Pricing
tags array[string] ❌ No Searchable tags for service
image_url string ❌ No Service image URL
is_active boolean ❌ No Service availability (default: true)
status string ❌ No Status: active, inactive, archived (default: active)

Response

{
  "id": "68e63f26241da4ebe30521c8",
  "tenant_id": "68e4cfe3886b6f295471fd4c",
  "name": "Premium Facial Treatment",
  "slug": "premium-facial",
  "description": "Luxurious 90-minute facial with premium products",
  "category": "facial",
  "duration_minutes": 90,
  "pricing": {
    "base_price": "75.00",
    "currency": "USD",
    "outlet_prices": {},
    "promotional_price": null,
    "promotional_valid_until": null
  },
  "is_active": true,
  "status": "active",
  "average_rating": null,
  "rating_count": 0,
  "created_at": "2025-10-08T10:38:30.619000",
  "updated_at": "2025-10-08T10:38:30.619000"
}

Service Category Configuration

Category Templates:

The category field accepts any string, but tenants can configure templates for consistency.

Get available templates:

GET /api/v1/services/categories/templates

Common Templates by Business Type:

  • Salon: hair_cut, hair_color, hair_treatment, hair_styling, makeup, manicure, pedicure
  • Spa: massage, body_treatment, facial, spa, therapy, waxing, consultation
  • Fitness: personal_training, yoga, pilates, cardio, strength_training
  • Clinic: consultation, therapy, physiotherapy, assessment, treatment

Category Format:

  • Lowercase with underscores (e.g., hair_cut, body_treatment)
  • Configurable via tenant settings: settings.service_category_templates
  • See Tenant Management for template configuration

Business Rules

  • Service slug must be unique within tenant
  • Category is required for proper classification
  • Duration should be in 5-minute increments for scheduling efficiency
  • Created services are active by default and immediately available for booking
  • Base price is required; outlet-specific pricing can be added later
  • Tenant isolation is automatically enforced

Subscription Limits

⚠️ FREE Plan Restriction: Maximum 10 services per tenant

Check before creating:

curl -X GET https://api.example.com/api/v1/subscriptions/usage \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Error Response (Limit Exceeded):

{
  "detail": "Service limit reached (10/10). Upgrade your plan to add more services."
}

Upgrade Required: See Subscription Management - Upgrade


Get Service Categories

Retrieve all service categories with service counts and descriptions.

Endpoint

GET /api/v1/services/categories?active_only=true

Authentication: Required (JWT token - Staff or Customer)

Query Parameters

  • active_only (optional) - Count only active services (default: true)

Response

[
  {
    "category": "facial",
    "display_name": "Facial",
    "count": 12,
    "description": "Facial treatments and skincare"
  },
  {
    "category": "massage",
    "display_name": "Massage",
    "count": 8,
    "description": "Relaxation and therapeutic massage"
  },
  {
    "category": "hair_cut",
    "display_name": "Hair Cut",
    "count": 15,
    "description": "Professional hair cutting and trimming services"
  }
]

Access Control

Staff Users:

  • See all categories regardless of service count
  • Can include inactive services in counts

Customer Users:

  • See only categories with active services (count > 0)
  • Empty categories are hidden

Business Rules

  • Categories are sourced from tenant's service_category_templates
  • Service counts respect tenant isolation
  • Categories are sorted alphabetically
  • Descriptions provide context for service selection

Get Service Category Templates

Retrieve tenant-specific category templates for consistent service organization.

Endpoint

GET /api/v1/services/categories/templates

Authentication: Required (JWT token - Staff or Customer)

Response

[
  "hair_cut",
  "hair_color",
  "hair_treatment",
  "hair_styling",
  "facial",
  "makeup",
  "eyebrows",
  "eyelashes",
  "manicure",
  "pedicure",
  "nail_art",
  "massage",
  "body_treatment",
  "waxing",
  "spa",
  "therapy",
  "consultation",
  "other"
]

Business Value

  • Consistency - Standardized category naming across organization
  • UI Integration - Used for autocomplete/dropdown in forms
  • Customizable - Configured per business type and services offered
  • Filtering - Enables better reporting and service discovery

Configuration

Customize Templates:

Update tenant settings via Tenant Management API:

curl -X PUT https://api.example.com/api/v1/tenants/{tenant_id} \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "settings": {
      "service_category_templates": [
        "massage",
        "body_treatment",
        "facial",
        "spa",
        "therapy",
        "waxing",
        "consultation"
      ]
    }
  }'

Default Templates:

If not configured, system returns default salon/spa categories.

Note

Templates are suggestions - staff can create services with any category value if needed.


Get Service Details

Retrieve detailed information about a specific service.

Endpoint

GET /api/v1/services/{service_id}

Authentication: Required (JWT token - Staff or Customer)

Path Parameters

  • service_id (required) - Service ID (ObjectId format)

Response

{
  "id": "68e63f26241da4ebe30521c8",
  "tenant_id": "68e4cfe3886b6f295471fd4c",
  "name": "Premium Facial Treatment",
  "slug": "premium-facial",
  "description": "Luxurious 90-minute facial with premium products",
  "category": "facial",
  "duration_minutes": 90,
  "preparation_minutes": 15,
  "cleanup_minutes": 10,
  "max_advance_booking_days": 30,
  "min_advance_booking_hours": 2,
  "requires_staff": true,
  "required_staff_count": 1,
  "allow_parallel_bookings": false,
  "max_parallel_bookings": 1,
  "pricing": {
    "base_price": "75.00",
    "currency": "USD",
    "outlet_prices": {
      "68e4f07e1245f30b04760bd5": "85.00",
      "68e4f07e1245f30b04760bd6": "80.00"
    },
    "promotional_price": "65.00",
    "promotional_valid_until": "2025-12-31T23:59:59Z"
  },
  "tags": ["luxury", "facial", "skincare"],
  "image_url": "https://example.com/images/premium-facial.jpg",
  "is_active": true,
  "status": "active",
  "average_rating": 4.8,
  "rating_count": 24,
  "created_at": "2025-10-08T10:38:30.619000",
  "updated_at": "2025-10-08T10:44:55.679000"
}

Pricing Information

The pricing object contains comprehensive pricing configuration:

  • base_price - Default price across all outlets
  • outlet_prices - Location-specific price overrides
  • promotional_price - Time-limited promotional discount
  • promotional_valid_until - Promotion expiration date

Pricing Hierarchy: Promotional → Outlet-Specific → Base

📖 See: Pricing Management for complete pricing hierarchy, promotional campaigns, and pricing strategies.

Access Control

Staff Users:

  • View any service regardless of status
  • See complete pricing information including outlet overrides

Customer Users:

  • View only active services (status: active, is_active: true)
  • Inactive services return 404 Not Found

Business Rules

  • Service must belong to current tenant
  • Service ID must be valid ObjectId format
  • Pricing includes base price and all outlet-specific overrides
  • Rating data includes average and count of reviews

Update Service

Update an existing service with partial or complete modifications.

Endpoint

PUT /api/v1/services/{service_id}

Authentication: Required (TENANT_ADMIN or OUTLET_MANAGER)

Path Parameters

  • service_id (required) - Service ID (ObjectId format)

Request Body

Supports partial updates - only include fields to change:

{
  "name": "Premium Luxury Facial Treatment",
  "description": "Enhanced 90-minute facial with exclusive premium products",
  "pricing": {
    "base_price": 85.00,
    "promotional_price": 70.00,
    "promotional_valid_until": "2025-12-31T23:59:59Z"
  },
  "tags": ["luxury", "facial", "skincare", "premium"],
  "is_active": true,
  "status": "active"
}

Response

Returns complete updated service (same format as GET response).

Business Rules

  • Service must exist and belong to current tenant
  • Slug must remain unique within tenant if changed
  • Status changes affect immediate service availability
  • Pricing changes apply to new bookings only (existing bookings unaffected)
  • Cannot update deleted services (status: archived)
  • Changes take effect immediately

Important Notes

⚠️ Active Bookings: Changes to duration, pricing, or requirements do not affect existing appointments

⚠️ Slug Changes: Changing slug may break existing deep links or bookmarks

Recommendation: Create new service version instead of modifying heavily-booked services


Delete Service

Soft delete a service by marking it as archived and unavailable.

Endpoint

DELETE /api/v1/services/{service_id}

Authentication: Required (TENANT_ADMIN only)

Path Parameters

  • service_id (required) - Service ID (ObjectId format)

Response

{
  "message": "Service has been deleted successfully"
}

Business Rules

  • Soft Deletion: Service is marked as deleted, not removed from database
  • Service becomes immediately unavailable for new bookings
  • Existing appointments remain unaffected
  • Historical booking data and revenue records preserved
  • Service disappears from customer-facing lists immediately
  • Only TENANT_ADMIN can delete services (higher permission than updates)

What Happens on Deletion

  1. is_active set to false
  2. is_deleted set to true
  3. status changed to ARCHIVED
  4. deleted_at timestamp recorded
  5. Service removed from active listings

Data Preservation

Preserved:

  • All service configuration
  • Historical appointments
  • Revenue data
  • Customer reviews
  • Booking statistics

Removed:

  • Visibility in service catalog
  • Availability for new bookings
  • Customer-facing listings

Note

Restoration: Contact system administrator to restore deleted services (not exposed via API)

Permanent Deletion: Data retention policies apply after 90 days of soft deletion


Set Outlet-Specific Pricing

Configure location-based pricing for a service across different outlets.

📖 See: Pricing Management - Outlet-Specific Pricing for detailed pricing hierarchy and best practices.

Endpoint

POST /api/v1/services/{service_id}/pricing

Authentication: Required (TENANT_ADMIN or OUTLET_MANAGER)

Path Parameters

  • service_id (required) - Service ID (ObjectId format)

Request Body

{
  "outlet_prices": {
    "68e4f07e1245f30b04760bd5": 85.00,
    "68e4f07e1245f30b04760bd6": 80.00,
    "68e4f07e1245f30b04760bd7": 90.00
  }
}

Parameters

  • outlet_prices (required) - Dictionary mapping outlet IDs to prices
  • Keys: Valid ObjectId strings for outlets
  • Values: Positive decimal prices

Response

Returns complete updated service with new pricing structure (same format as GET response).

Example pricing in response:

{
  "pricing": {
    "base_price": "75.00",
    "currency": "USD",
    "outlet_prices": {
      "68e4f07e1245f30b04760bd5": "85.00",
      "68e4f07e1245f30b04760bd6": "80.00",
      "68e4f07e1245f30b04760bd7": "90.00"
    },
    "promotional_price": null,
    "promotional_valid_until": null
  }
}

Access Control

TENANT_ADMIN:

  • Can set prices for any outlet in tenant
  • Full pricing management access

OUTLET_MANAGER:

  • Can only set prices for outlets they manage
  • Restricted by outlet_ids in user profile
  • Returns 403 Forbidden if attempting to price unmanaged outlets

Business Rules

  • Service must exist and belong to current tenant
  • All outlet IDs must be valid ObjectId format
  • All prices must be positive values
  • Outlet IDs must belong to current tenant
  • Base price remains unchanged (acts as fallback)
  • New prices merge with existing outlet pricing (non-destructive)
  • Changes affect new bookings immediately

Pricing Resolution

When booking at a specific outlet, the system follows this hierarchy:

  1. Promotional Price (if valid and not expired) - Highest priority
  2. Outlet-Specific Price (if outlet has custom price in outlet_prices)
  3. Base Price (final fallback)

📖 See: Pricing Management - Pricing Hierarchy for complete resolution logic and examples.

Subscription Requirements

⚠️ FREE Plan Restriction: Outlet-specific pricing not available

Plans with Outlet Pricing:

  • ✅ PRO - Outlet pricing enabled
  • ✅ ENTERPRISE - Outlet pricing enabled

Upgrade Required: See Subscription Management - Upgrade

Example Use Cases

Location-Based Pricing:

  • Premium locations charge more
  • Downtown outlets vs suburban outlets
  • High-rent areas vs standard locations

Promotional Pricing:

  • New outlet launch pricing
  • Seasonal outlet-specific promotions
  • Traffic-driving discounts for specific locations

Service Status Lifecycle

Services follow a defined lifecycle with status management:

Status Values

Status Description Customer Visible Bookable
active Service is live and available ✅ Yes ✅ Yes
inactive Temporarily unavailable ❌ No ❌ No
archived Deleted or discontinued ❌ No ❌ No

Status Transitions

graph LR
    A[Create Service] --> B[active]
    B --> C[inactive]
    C --> B
    B --> D[archived]
    C --> D
    D -.restore.-> B

Allowed Transitions:

  • activeinactive - Temporarily disable service
  • inactiveactive - Re-enable service
  • activearchived - Delete service
  • inactivearchived - Delete inactive service
  • archivedactive - Restore deleted service (admin only)

is_active vs status

Two-Level Control:

  • is_active (boolean) - Quick availability toggle
  • status (enum) - Detailed lifecycle state

Relationship:

  • Active service: is_active=true AND status=active
  • Customer visibility requires BOTH conditions

Use Cases:

  • is_active=false, status=active - Temporarily hidden
  • is_active=true, status=inactive - Invalid state (corrected on save)

Integration Examples

Complete Service Creation Flow

# 1. Get category templates
curl -X GET https://api.example.com/api/v1/services/categories/templates \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

# 2. Check subscription limits
curl -X GET https://api.example.com/api/v1/subscriptions/usage \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

# 3. Create service
curl -X POST https://api.example.com/api/v1/services \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Premium Facial Treatment",
    "slug": "premium-facial",
    "description": "Luxurious 90-minute facial",
    "category": "facial",
    "duration_minutes": 90,
    "pricing": {
      "base_price": 75.00,
      "currency": "USD"
    },
    "is_active": true
  }'

# 4. Set outlet pricing
curl -X POST https://api.example.com/api/v1/services/68e63f26241da4ebe30521c8/pricing \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "outlet_prices": {
      "68e4f07e1245f30b04760bd5": 85.00
    }
  }'

Customer Service Discovery Flow

# 1. Browse categories
curl -X GET https://api.example.com/api/v1/services/categories \
  -H "Authorization: Bearer CUSTOMER_JWT_TOKEN"

# 2. Search services in category
curl -X GET "https://api.example.com/api/v1/services?category=facial&min_price=50&max_price=100" \
  -H "Authorization: Bearer CUSTOMER_JWT_TOKEN"

# 3. Get service details
curl -X GET https://api.example.com/api/v1/services/68e63f26241da4ebe30521c8 \
  -H "Authorization: Bearer CUSTOMER_JWT_TOKEN"

Best Practices

Service Creation

DO:

  • Use category templates for consistency
  • Set realistic duration with preparation/cleanup time
  • Provide clear descriptions and tags
  • Use high-quality images (recommended: 1200x800px)
  • Set appropriate advance booking windows
  • Check subscription limits before creation

DON'T:

  • Create duplicate services with different slugs
  • Use ambiguous category names
  • Skip description or image URLs
  • Set unrealistic durations
  • Create services without checking limits

Category Management

DO:

  • Configure tenant-specific category templates
  • Use lowercase with underscores format
  • Keep categories broad enough for grouping
  • Provide category descriptions
  • Review and update templates as business evolves

DON'T:

  • Use too many granular categories
  • Mix different naming conventions
  • Create categories for single services
  • Change categories on heavily-booked services

Pricing Strategy

DO:

  • Set competitive base prices
  • Use outlet pricing for location premiums
  • Test promotional pricing before major campaigns
  • Document pricing strategy in internal docs
  • Review pricing regularly against competition

DON'T:

  • Set prices too high without market research
  • Change prices frequently (confuses customers)
  • Use outlet pricing on FREE plan (will fail)
  • Forget to update promotional end dates

Service Lifecycle

DO:

  • Use inactive status for temporary unavailability
  • Archive outdated or discontinued services
  • Keep historical data for reporting
  • Communicate status changes to staff
  • Monitor service performance before archiving

DON'T:

  • Delete services with active bookings (use inactive)
  • Archive popular services without replacement
  • Change status without team notification
  • Reactivate archived services without review

Error Handling

Common Errors

Error Code Cause Solution
400 Bad Request Invalid input data Check field formats and required fields
401 Unauthorized Missing/invalid token Verify JWT token is valid
403 Forbidden Insufficient permissions Check user role and outlet access
404 Not Found Service doesn't exist Verify service ID is correct
409 Conflict Slug already exists Use different slug or update existing service
422 Unprocessable Entity Validation failed Review validation error details

Subscription Limit Errors

FREE Plan Service Limit:

{
  "detail": "Service limit reached (10/10). Upgrade your plan to add more services."
}

Solution: Upgrade to PRO or ENTERPRISE plan

Outlet Pricing on FREE Plan:

{
  "detail": "Outlet-specific pricing requires PRO or ENTERPRISE plan. Current plan: FREE."
}

Solution: Upgrade to PRO or ENTERPRISE plan



API Reference Summary

Endpoint Method Purpose Access Subscription Limit
/services GET List services Staff + Customers None
/services POST Create service Staff FREE: 10 max, PRO: 50 max
/services/categories GET List categories Staff + Customers None
/services/categories/templates GET Get templates Staff + Customers None
/services/{id} GET Get details Staff + Customers None
/services/{id} PUT Update service Staff None
/services/{id} DELETE Delete service TENANT_ADMIN None
/services/{id}/pricing POST Set outlet pricing Staff PRO+ required

Next Steps:

  1. Get category templates: GET /services/categories/templates
  2. Check subscription limits: GET /subscriptions/usage
  3. Create your first service: POST /services
  4. Configure outlet pricing (PRO+): POST /services/{id}/pricing
  5. Test customer discovery: GET /services?category=...

For complete API testing, see Swagger UI or ReDoc.