Public API¶
Public endpoints for accessing business information without authentication. These endpoints enable customers to discover businesses, browse outlets, and register new businesses on the platform.
Overview¶
The public API provides unauthenticated access to:
- Business Discovery - Find and view business information by slug
- Outlet Browsing - Search and filter business locations
- Service Catalog - Browse available services with pricing
- Package Browsing - View available packages with discounts and pricing
- Self-Service Registration - Create new business accounts instantly
Key Concepts:
- No Authentication Required - All endpoints are publicly accessible
- Rate Limited - 30% of authenticated limits to prevent abuse
- Read-Only Access - Except for registration endpoint
- Cached Responses - 5-minute cache TTL for performance
- Active Records Only - Only active businesses and outlets are returned
Get Business Information¶
Retrieve public business information by slug identifier.
Endpoint¶
Authentication: None required (rate limited)
Path Parameters¶
slug(required) - Business slug identifier (e.g.,beauty-salon-downtown)
Response¶
{
"name": "Bella Vista Spa & Salon",
"slug": "bella-vista-spa",
"description": "Luxury spa and salon offering premium beauty services",
"website": "https://bellavista.com",
"business_type": "spa",
"outlets_count": 3,
"support_email": "contact@bellavista.com",
"support_phone": "+1-555-123-4567"
}
Response Fields:
name- Business nameslug- URL-friendly identifierdescription- Business descriptionwebsite- Business website URLbusiness_type- Type of business (e.g.,spa,salon,barbershop)outlets_count- Total number of active outletssupport_email- Contact emailsupport_phone- Contact phone number
Business Rules¶
- Only active tenants are returned
- Sensitive data (subscription details, settings) excluded
- Response cached for 5 minutes
- Returns 404 if business not found or inactive
Example Request¶
Error Responses¶
404 Not Found:
429 Rate Limit Exceeded:
List Public Outlets¶
Browse and search business outlet locations with filtering options.
Endpoint¶
Authentication: None required (rate limited)
Query Parameters¶
tenant_slug(optional) - Filter by business slug (e.g.,beauty-salon-downtown)city(optional) - Filter by city (case-insensitive, e.g.,New York)is_active(optional) - Filter active outlets only (default:true)page(optional) - Page number, 1-based (default:1, min:1)size(optional) - Items per page (default:10, min:1, max:50)
Response¶
{
"items": [
{
"name": "Bella Vista - Downtown",
"slug": "bella-vista-downtown",
"address": {
"street": "123 Main Street",
"city": "New York",
"state": "NY",
"postal_code": "10001",
"country": "USA"
},
"phone": "+1-555-987-6543",
"email": "downtown@bellavista.com",
"business_hours": [
{
"day": 0,
"is_open": true,
"open_time": "09:00",
"close_time": "18:00",
"break_start": null,
"break_end": null
},
{
"day": 1,
"is_open": true,
"open_time": "09:00",
"close_time": "18:00",
"break_start": null,
"break_end": null
}
],
"status": "active",
"services_count": 15,
"accepts_online_booking": true,
"images": [
"https://cdn.myreserva.id/outlets/bella-vista-downtown-1.jpg"
],
"description": "Our flagship downtown location featuring premium spa services",
"amenities": [
"WiFi",
"Parking Available",
"Wheelchair Accessible",
"Air Conditioning"
]
}
],
"total": 3,
"page": 1,
"size": 10,
"pages": 1
}
Business Hours Day Mapping:
0= Monday1= Tuesday2= Wednesday3= Thursday4= Friday5= Saturday6= Sunday
Business Rules¶
- Only active outlets are shown (unless
is_active=falsespecified) - City filter is case-insensitive
- Results include business hours for each outlet
- Maximum 50 items per page
- Empty results if tenant not found
Example Requests¶
List all active outlets:
Filter by business:
curl -X GET "https://api.myreserva.id/api/v1/public/outlets?tenant_slug=bella-vista-spa&page=1&size=10"
Filter by city:
Combine filters:
curl -X GET "https://api.myreserva.id/api/v1/public/outlets?tenant_slug=bella-vista-spa&city=New+York&page=1&size=10"
Error Responses¶
400 Bad Request:
429 Rate Limit Exceeded:
Get Outlet Details¶
Get detailed public information for a specific outlet by slug.
Endpoint¶
Authentication: None required (rate limited)
Path Parameters¶
outlet_slug(required) - Outlet slug identifier (e.g.,downtown-spa)
Response¶
{
"name": "Bella Vista - Downtown",
"slug": "bella-vista-downtown",
"address": {
"street": "123 Main Street",
"city": "New York",
"state": "NY",
"postal_code": "10001",
"country": "USA"
},
"phone": "+1-555-987-6543",
"email": "downtown@bellavista.com",
"business_hours": [
{
"day": 0,
"is_open": true,
"open_time": "09:00",
"close_time": "18:00",
"break_start": null,
"break_end": null
},
{
"day": 1,
"is_open": true,
"open_time": "09:00",
"close_time": "18:00",
"break_start": null,
"break_end": null
}
],
"status": "active",
"services_count": 15,
"accepts_online_booking": true,
"images": [
"https://cdn.myreserva.id/outlets/bella-vista-downtown-1.jpg",
"https://cdn.myreserva.id/outlets/bella-vista-downtown-2.jpg"
],
"description": "Our flagship downtown location featuring premium spa services",
"amenities": [
"WiFi",
"Parking Available",
"Wheelchair Accessible",
"Air Conditioning"
]
}
Response Fields:
name- Outlet nameslug- URL-friendly identifieraddress- Complete address detailsphone- Contact phone numberemail- Contact emailbusiness_hours- Operating hours for each day (0=Monday, 6=Sunday)status- Outlet status (e.g.,active)services_count- Number of services availableaccepts_online_booking- Whether online booking is enabledimages- Array of image URLsdescription- Outlet descriptionamenities- List of available amenities
Business Rules¶
- Only active outlets are accessible
- Returns amenities and parking information
- Images and descriptions included
- Uses slug for SEO-friendly URLs
Example Request¶
Error Responses¶
404 Not Found:
429 Rate Limit Exceeded:
Browse Service Catalog¶
Browse public service catalog with comprehensive filtering and enhanced pricing.
Endpoint¶
Authentication: None required (rate limited)
Query Parameters¶
tenant_slug(optional) - Filter by business identifier (e.g.,beauty-salon-downtown)outlet_id(optional) - Filter by outlet ID for outlet-specific pricing (e.g.,507f1f77bcf86cd799439011)category(optional) - Filter by service category (e.g.,facial,nails,massage)min_price(optional) - Minimum display_price filter after discounts (e.g.,25.00, min:0)max_price(optional) - Maximum display_price filter after discounts (e.g.,150.00, min:0)page(optional) - Page number, 1-based (default:1, min:1)size(optional) - Items per page (default:20, min:1, max:100)
Response¶
{
"items": [
{
"name": "Premium Facial Treatment",
"description": "Deep cleansing facial with hydration",
"category": "facial",
"duration_minutes": 60,
"pricing": {
"base_price": "350000.00",
"display_price": "280000.00",
"strikethrough_price": "350000.00",
"discount_type": "promotional",
"promotional_valid_until": "2025-12-31T23:59:59Z",
"price_varies_by_outlet": true
},
"currency": "IDR",
"image_url": "https://cdn.myreserva.id/services/premium-facial.jpg",
"popular": true,
"available": true,
"tags": ["facial", "hydration", "skincare"]
},
{
"name": "Classic Manicure",
"description": "Traditional nail care and polish",
"category": "nails",
"duration_minutes": 45,
"pricing": {
"base_price": "150000.00",
"display_price": "150000.00",
"strikethrough_price": null,
"discount_type": null,
"promotional_valid_until": null,
"price_varies_by_outlet": false
},
"currency": "IDR",
"image_url": "https://cdn.myreserva.id/services/manicure.jpg",
"popular": false,
"available": true,
"tags": ["nails", "manicure"]
}
],
"total": 45,
"page": 1,
"size": 20,
"pages": 3
}
Pricing Object Fields:
| Field | Type | Description |
|---|---|---|
base_price |
Decimal | Always the service's base price (for reference) |
display_price |
Decimal | The actual price to charge (calculated using pricing hierarchy) |
strikethrough_price |
Decimal or null | The "was" price - only set when display_price < regular price |
discount_type |
string or null | Type of discount applied: "promotional" or null |
promotional_valid_until |
datetime or null | Promo expiry date for urgency UI (e.g., "Ends in 3 days!") |
price_varies_by_outlet |
boolean | Hint that price may change after outlet selection |
Pricing Hierarchy:
Prices are calculated using the following priority (highest to lowest):
- Promotional Price - Global promotional pricing (applies to all outlets)
- Outlet-Specific Price - Location-specific pricing when
outlet_idis provided - Base Price - Default fallback price
Frontend Display Examples:
┌─────────────────────────────────────────────┐
│ Premium Facial Treatment │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ IDR 350,000 → IDR 280,000 │ ← strikethrough_price + display_price
│ 🏷️ PROMO - Ends Dec 31! │ ← discount_type + promotional_valid_until
│ ⚠️ Price may vary by outlet │ ← price_varies_by_outlet
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ Classic Manicure │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ IDR 150,000 │ ← display_price only (no strikethrough)
└─────────────────────────────────────────────┘
Service Categories (Common):
hair- Haircuts, styling, coloringnails- Manicure, pedicure, nail artspa- Massage, facials, body treatmentsfacial- Facial treatments and skincaremakeup- Makeup application serviceswaxing- Hair removal servicestherapy- Wellness treatments, therapy sessions
Business Rules¶
- Only active services are shown
- Services must have ACTIVE status
- Price filtering based on
display_price(after promotional discounts) - Results sorted by popularity and name
- Maximum 100 items per page
- When
outlet_idis provided, pricing considers outlet-specific prices
Example Requests¶
List all services:
Filter by business:
curl -X GET "https://api.myreserva.id/api/v1/public/services?tenant_slug=bella-vista-spa&page=1&size=20"
Filter by category:
Filter by price range (filters by display_price after discounts):
curl -X GET "https://api.myreserva.id/api/v1/public/services?min_price=50000&max_price=200000&page=1&size=20"
Get outlet-specific pricing:
curl -X GET "https://api.myreserva.id/api/v1/public/services?outlet_id=507f1f77bcf86cd799439011&page=1&size=20"
Combine filters:
curl -X GET "https://api.myreserva.id/api/v1/public/services?tenant_slug=bella-vista-spa&category=facial&min_price=50000&max_price=200000&page=1&size=20"
Error Responses¶
400 Bad Request:
429 Rate Limit Exceeded:
Browse Available Packages¶
Browse all active packages available for purchase at a business with pricing and discount information.
Endpoint¶
Authentication: None required (rate limited)
Query Parameters¶
tenant_slug(required) - Business slug identifier (e.g.,beauty-salon-downtown)outlet_id(optional) - Filter packages available at specific outlet (e.g.,507f1f77bcf86cd799439012)page(optional) - Page number, 1-based (default:1, min:1)size(optional) - Items per page (default:10, min:1, max:50)
Response¶
{
"items": [
{
"name": "Luxury Spa Package",
"description": "Premium spa treatments bundle",
"package_items": [
{
"service_name": "Full Body Massage",
"quantity": 3,
"unit_price": "150000.0"
},
{
"service_name": "Facial Treatment",
"quantity": 2,
"unit_price": "150000.0"
}
],
"package_price": "500000.0",
"currency": "IDR",
"total_individual_price": "750000.0",
"discount_percentage": 33.33,
"validity_days": 90
}
],
"total": 5,
"page": 1,
"size": 10,
"pages": 1
}
Response Fields:
| Field | Type | Description |
|---|---|---|
name |
string | Package display name |
description |
string or null | Package description and terms |
package_items |
array | Services included in the package |
package_items[].service_name |
string | Service display name |
package_items[].quantity |
integer | Number of sessions/credits for this service |
package_items[].unit_price |
Decimal or null | Individual service price (for value comparison) |
package_price |
Decimal | Total package price (final price to pay) |
currency |
string | Currency code (e.g., IDR, USD) |
total_individual_price |
Decimal or null | Sum of individual service prices (strikethrough "was" price) |
discount_percentage |
float or null | Discount percentage (e.g., 33.33 for "Save 33%!") |
validity_days |
integer or null | Days until credits expire after purchase (null = never expires) |
Intentionally Hidden (requires authentication):
id- Package internal identifierservice_id- Service internal identifiers within package_items
Frontend Display Example:
┌─────────────────────────────────────────────┐
│ 🏆 Luxury Spa Package │
│ Premium spa treatments bundle │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ ~~IDR 750,000~~ → IDR 500,000 │ ← strikethrough + package_price
│ Save 33%! │ ← discount_percentage
│ │
│ What's included: │
│ • 3x Full Body Massage (@ 150,000) │ ← package_items
│ • 2x Facial Treatment (@ 150,000) │
│ │
│ Valid for 90 days │ ← validity_days
│ [Login to Purchase] │
└─────────────────────────────────────────────┘
Business Rules¶
- Only active packages are shown (
is_active=true,status=active) - Packages with empty
outlet_idsare available at all outlets - Discount percentage calculated from individual service prices
tenant_slugis required to filter by business- Internal IDs (package_id, service_id) are hidden from public response
- Results filtered by tenant automatically
Example Requests¶
List all packages for a business:
curl -X GET "https://api.myreserva.id/api/v1/public/packages?tenant_slug=bella-vista-spa&page=1&size=10"
Filter by outlet:
curl -X GET "https://api.myreserva.id/api/v1/public/packages?tenant_slug=bella-vista-spa&outlet_id=507f1f77bcf86cd799439012&page=1&size=10"
Error Responses¶
400 Bad Request:
404 Not Found:
429 Rate Limit Exceeded:
Use Cases¶
- Public Website Package Browsing - Display available packages on marketing pages
- Embedded Booking Widgets - Show packages in third-party booking integrations
- Package Discovery - Allow customers to explore package options before signing up
- Price Comparison - Display strikethrough pricing to show package value/savings
Next Steps After Browsing¶
To purchase a package, customers must:
- Register/Login - Authenticate via customer portal
- Purchase Package - Use
POST /api/v1/customer/packages/purchase - Complete Payment - Via Paper.id, bank transfer, or pay on visit
See Customer Package Management for purchase flow details.
Get Business Hours¶
Get complete business hours schedule for an outlet by slug.
Endpoint¶
Authentication: None required (rate limited)
Path Parameters¶
outlet_slug(required) - Outlet slug identifier (e.g.,downtown-spa)
Response¶
{
"outlet_slug": "bella-vista-downtown",
"outlet_name": "Bella Vista - Downtown",
"timezone": "America/New_York",
"regular_hours": [
{
"day": "Monday",
"day_number": 0,
"is_open": true,
"open_time": "09:00",
"close_time": "18:00",
"break_start": null,
"break_end": null
},
{
"day": "Tuesday",
"day_number": 1,
"is_open": true,
"open_time": "09:00",
"close_time": "18:00",
"break_start": null,
"break_end": null
},
{
"day": "Wednesday",
"day_number": 2,
"is_open": true,
"open_time": "09:00",
"close_time": "18:00",
"break_start": null,
"break_end": null
},
{
"day": "Thursday",
"day_number": 3,
"is_open": true,
"open_time": "09:00",
"close_time": "18:00",
"break_start": "13:00",
"break_end": "14:00"
},
{
"day": "Friday",
"day_number": 4,
"is_open": true,
"open_time": "09:00",
"close_time": "18:00",
"break_start": null,
"break_end": null
},
{
"day": "Saturday",
"day_number": 5,
"is_open": true,
"open_time": "10:00",
"close_time": "16:00",
"break_start": null,
"break_end": null
},
{
"day": "Sunday",
"day_number": 6,
"is_open": false,
"open_time": null,
"close_time": null,
"break_start": null,
"break_end": null
}
],
"special_dates": [
{
"date": "2025-12-25",
"is_open": false,
"reason": "Christmas Day"
},
{
"date": "2025-01-01",
"is_open": false,
"reason": "New Year's Day"
}
],
"accepts_online_booking": true
}
Response Fields:
outlet_slug- Outlet slug identifieroutlet_name- Outlet display nametimezone- Timezone identifier (e.g.,America/New_York,UTC)regular_hours- Array of business hours for each day of weekday- Day name (e.g.,Monday,Tuesday)day_number- Day number (0=Monday, 6=Sunday)is_open- Whether outlet is open on this dayopen_time- Opening time in HH:MM format (null if closed)close_time- Closing time in HH:MM format (null if closed)break_start- Break start time in HH:MM format (null if no break)break_end- Break end time in HH:MM format (null if no break)special_dates- Array of special dates (holidays, closures)date- Date in YYYY-MM-DD formatis_open- Whether outlet is open on this datereason- Reason for special hours (e.g.,Christmas Day)accepts_online_booking- Whether online booking is enabled
Business Rules¶
- Only active outlets return business hours
- Day numbering: 0=Monday, 6=Sunday
- Times returned in HH:MM format
- Closed days show
is_open=false - Uses slug for SEO-friendly URLs
- Break times are optional and only included when configured
Example Request¶
Error Responses¶
404 Not Found:
429 Rate Limit Exceeded:
Register New Business (Self-Service)¶
Self-service tenant registration for new businesses. Creates a fully-functional account with FREE subscription plan.
Endpoint¶
Authentication: None required (rate limited)
Request Body¶
{
"business_name": "Bella Vista Spa",
"business_email": "contact@bellavista.com",
"business_phone": "+1-555-987-6543",
"business_type": "spa",
"description": "Luxury spa and wellness center",
"website": "https://bellavista.com",
"admin_first_name": "Maria",
"admin_last_name": "Rodriguez",
"admin_email": "maria@bellavista.com",
"admin_password": "SecurePass123!",
"preferred_slug": "bella-vista-spa",
"terms_accepted": true,
"privacy_accepted": true
}
Required Fields:
business_name- Business name (must be unique, case-insensitive)business_email- Business contact email (must be unique)business_phone- Business phone number (must be unique)business_type- Type of business (e.g.,spa,salon,barbershop,clinic)admin_first_name- Administrator first nameadmin_last_name- Administrator last nameadmin_email- Administrator email (must be unique, different from business_email)admin_password- Administrator password (min 8 chars, must include uppercase, lowercase, number)terms_accepted- Must betrueprivacy_accepted- Must betrue
Optional Fields:
description- Business descriptionwebsite- Business website URL (auto-prependshttps://if missing)preferred_slug- Desired URL slug (auto-generated from business_name if omitted)
Response¶
{
"registration_id": "67890fedcba09876543210ab",
"tenant_id": "12345abcdef67890abcdef12",
"slug": "bella-vista-spa",
"client_partner_id": "CP-20250116-ABC123",
"client_partner_number": "BVS-001",
"status": "active",
"message": "Registration successful! Your account is now active and ready to use.",
"next_steps": [
"1. Log in with your admin credentials",
"2. Complete your business profile and upload a logo",
"3. Add your first outlet location with address and business hours",
"4. Configure your services, pricing, and duration",
"5. Add staff members and assign them to services",
"6. Start accepting customer bookings!"
]
}
Response Fields:
registration_id- Registration tracking IDtenant_id- New tenant identifierslug- Generated or preferred slugclient_partner_id- Paper.id payment integration ID (may benullif integration fails non-blocking)client_partner_number- Business partner numberstatus- Account status (active- ready to use)message- Success messagenext_steps- Onboarding checklist
Registration Flow¶
The registration process follows these steps:
- Duplicate Detection - Check for existing business name, email, phone, and admin email
- Slug Generation - Auto-generate slug from business name or use preferred_slug
- Slug Uniqueness - Auto-increment slug if duplicate exists (e.g.,
salon→salon-1) - Tenant Creation - Create tenant with
is_active=True - FREE Subscription - Create subscription with FREE plan and ACTIVE status
- Admin User - Create admin user with TENANT_ADMIN role
- Paper.id Integration - Create payment partner (non-blocking, optional)
- Response - Return registration details for immediate login
Subscription Plan Assignment¶
Automatic FREE Plan Assignment:
All new registrations receive the FREE plan with the following limits:
| Resource | FREE Plan Limit |
|---|---|
| Max Outlets | 1 |
| Max Staff per Outlet | 5 |
| Max Appointments/Month | 100 |
| Max Services | 20 |
| Price | IDR 0 (Free) |
Upgrading After Registration:
To upgrade to PRO or ENTERPRISE plans, see Subscription Management.
Business Rules¶
Duplicate Detection (409 Conflict)¶
The following fields must be unique:
business_name(case-insensitive)business_emailbusiness_phoneadmin_email(must differ from business_email)
Password Requirements¶
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
- Special characters allowed but not required
Slug Generation¶
- Auto-generated from
business_nameifpreferred_slugnot provided - Converted to lowercase, spaces replaced with hyphens
- Special characters removed
- Duplicate slugs auto-incremented (e.g.,
salon,salon-1,salon-2)
Website URL Formatting¶
- Auto-prepends
https://if protocol missing - Validates URL format
- Stores normalized URL
Immediate Activation¶
- Account activated immediately (
is_active=True) - No email verification required (deferred to GTM phase)
- No admin approval required
- Can login immediately after registration
Example Request¶
curl -X POST "https://api.myreserva.id/api/v1/public/register" \
-H "Content-Type: application/json" \
-d '{
"business_name": "Bella Vista Spa",
"business_email": "contact@bellavista.com",
"business_phone": "+1-555-987-6543",
"business_type": "spa",
"description": "Luxury spa and wellness center",
"website": "https://bellavista.com",
"admin_first_name": "Maria",
"admin_last_name": "Rodriguez",
"admin_email": "maria@bellavista.com",
"admin_password": "SecurePass123!",
"preferred_slug": "bella-vista-spa",
"terms_accepted": true,
"privacy_accepted": true
}'
Error Responses¶
400 Bad Request - Validation Error:
409 Conflict - Duplicate Business Name:
409 Conflict - Duplicate Email:
409 Conflict - Duplicate Phone:
409 Conflict - Admin Email Already Used:
422 Unprocessable Entity - Terms Not Accepted:
429 Rate Limit Exceeded:
500 Internal Server Error:
Post-Registration Steps¶
After successful registration, the admin should:
- Login - Use admin credentials at
/api/v1/auth/login - Complete Profile - Add logo, update business description
- Create First Outlet - Add address, business hours, contact info
- Add Services - Configure service catalog with pricing and duration
- Add Staff - Create staff profiles and assign to outlets
- Configure Availability - Set staff working hours and availability
- Test Booking - Create a test appointment to verify setup
- Go Live - Share booking link with customers
Next Steps Reference¶
For detailed guides on post-registration setup:
- Outlet Setup: Outlet Management
- Service Configuration: Service Management
- Staff Management: Staff Management
- Subscription Upgrade: Subscription Management
- Availability Setup: Availability Management
Rate Limiting¶
All public endpoints are rate limited to prevent abuse.
Rate Limit Configuration¶
| Endpoint Type | Rate Limit |
|---|---|
| Public Endpoints | 30% of authenticated limits |
| Registration Endpoint | Stricter limits (10 requests/hour per IP) |
| Business Information | Cached (5-minute TTL) |
Rate Limit Headers¶
Rate Limit Exceeded Response¶
Status Code: 429 Too Many Requests
Caching Strategy¶
Cached Endpoints¶
GET /api/v1/public/tenants/{slug}- 5-minute cache TTL
Cache Headers¶
Cache Invalidation¶
- Cache automatically expires after 5 minutes
- Manual invalidation on tenant update (staff portal)
- ETag-based conditional requests supported
Best Practices¶
For Business Discovery¶
✅ DO:
- Use slugs for SEO-friendly URLs
- Cache business information client-side
- Handle 404 gracefully (business not found or inactive)
- Display outlet count for multi-location businesses
❌ DON'T:
- Expose tenant IDs in public URLs (use slugs instead)
- Make excessive requests (respect rate limits)
- Cache for longer than 5 minutes (data may become stale)
For Outlet Browsing¶
✅ DO:
- Use city filter for location-based search
- Implement pagination for better UX
- Display business hours prominently
- Show amenities and images
- Filter by
is_active=true(default behavior)
❌ DON'T:
- Request all outlets at once (use pagination)
- Ignore
accepts_online_bookingflag - Display inactive outlets to customers
For Business Registration¶
✅ DO:
- Validate password strength client-side before submission
- Check for duplicate business names before submitting
- Display clear password requirements
- Show terms of service and privacy policy links
- Guide users through next steps after registration
- Use preferred_slug for SEO-friendly URLs
❌ DON'T:
- Submit weak passwords (will be rejected)
- Skip terms acceptance validation
- Use admin_email same as business_email
- Cache registration responses
- Auto-fill passwords in forms
Security Considerations¶
Public Access¶
- No authentication required
- Rate limiting enforced
- IP-based rate limiting for registration
- No sensitive data exposed (subscription details, settings excluded)
Registration Security¶
- Password hashed with bcrypt (12 rounds)
- Email format validated
- Phone format validated
- Duplicate detection prevents data pollution
- Terms acceptance required for legal compliance
Data Privacy¶
- Only active businesses/outlets returned
- Sensitive fields excluded from public responses:
- Subscription details
- Payment information
- Internal settings
- Staff salaries
- Customer PII
API Reference Summary¶
| Endpoint | Method | Purpose | Authentication | Rate Limited |
|---|---|---|---|---|
/public/tenants/{slug} |
GET | Get business info by slug | None | Yes (cached) |
/public/outlets |
GET | List and search outlets | None | Yes |
/public/outlets/{outlet_slug} |
GET | Get outlet details by slug | None | Yes |
/public/services |
GET | Browse service catalog | None | Yes |
/public/packages |
GET | Browse available packages | None | Yes |
/public/business-hours/{outlet_slug} |
GET | Get outlet business hours | None | Yes |
/public/register |
POST | Register new business | None | Yes (strict) |
Related Documentation¶
- Tenant Management: Tenant Management (Staff Portal)
- Outlet Details: Outlet Management
- Service Catalog: Service Management
- Package Management: Package Management (Staff Portal)
- Customer Packages: Customer Package Management (Purchase Flow)
- Subscription Plans: Subscription Management
- Authentication: Staff Authentication
- Customer Booking: Customer Booking & Appointments
Troubleshooting¶
Business Not Found (404)¶
Symptoms: GET /public/tenants/{slug} returns 404
Possible Causes:
- Incorrect slug (typo in URL)
- Business is inactive (
is_active=false) - Business deleted
Solution:
- Verify slug spelling
- Check business status in admin panel
- Contact support if business should be active
Registration Failed (409 Conflict)¶
Symptoms: Registration returns 409 with duplicate error
Possible Causes:
- Business name already exists (case-insensitive match)
- Business email already registered
- Business phone already registered
- Admin email already in use
Solution:
- Use different business name
- Use different contact email
- Use different phone number
- Use different admin email
Registration Failed (400 Bad Request)¶
Symptoms: Registration returns 400 with validation error
Possible Causes:
- Weak password (doesn't meet requirements)
- Invalid email format
- Invalid phone format
- Missing required fields
- Terms not accepted
Solution:
- Ensure password has 8+ characters with uppercase, lowercase, and number
- Validate email format client-side
- Use international phone format (+1-555-123-4567)
- Include all required fields
- Set
terms_acceptedandprivacy_acceptedtotrue
Rate Limit Exceeded (429)¶
Symptoms: Requests return 429 Too Many Requests
Possible Causes:
- Too many requests in short period
- Shared IP with high traffic
- Automated scraping detected
Solution:
- Wait for rate limit reset (check
X-RateLimit-Resetheader) - Implement client-side caching
- Use pagination instead of bulk requests
- Contact support if legitimate use case requires higher limits
Next Steps:
- Browse public business information:
GET /public/tenants/{slug} - Search outlets by location:
GET /public/outlets?city=New+York - Register new business:
POST /public/register - Login with admin credentials: Staff Authentication
- Complete business setup: Tenant Management
For customer-facing booking endpoints, see Customer Booking & Appointments.