Service APIs
API documentation for service-related endpoints
Services
Services represent bookable offerings provided by an organization. Each service has properties like name, availability settings, pricing, and more.
Service Availability
The service's availability
object includes:
daysIntoFuture
: How many days in advance bookings can be madelengthMinutes
: Default duration of each booking slotbufferMinutes
: Buffer time between consecutive bookingsmode
: How resources are assigned to bookings:roundrobin_random
: Randomly distribute bookings among chosen resourcesmutual
: All chosen resources must be available for a bookingroundrobin_prioritized
: Distribute bookings with priority orderexclusive
: Only one resource can be booked at a time
regularAvailability
: Array of weekly recurring availability patterns (SeeavailabilityModel.ts
)specificAvailability
: Array of one-time availability slots (SeeavailabilityModel.ts
)
Service Types
Services can be either:
one_to_one
: One customer per booking slotgroup
: Multiple customers can book the same slot (limited bymaxAttendeesPerSlot
)
Custom Customer Fields
Services can define custom fields (customerFields
) to collect specific information from customers during the booking process. This is defined as a map where the key is a unique slug for the field and the value is an object describing the field:
label
: (string, required) Display name for the field (e.g., "Your Full Name").type
: (string, required) Input type (e.g., 'text', 'email', 'phone', 'textarea', 'number', 'date', 'checkbox', 'select').required
: (boolean, required) Is the field mandatory?prefilled
: (string, optional) Default value.readonly
: (boolean, optional) Can the customer edit this field? (defaults to false).options
: (string[], optional) Array of options for 'select' type fields.
Example customerFields
object:
{
"customer_name": {
"label": "Full Name",
"type": "text",
"required": true
},
"contact_preference": {
"label": "Preferred Contact Method",
"type": "select",
"required": false,
"options": ["Email", "Phone"]
}
}
1. Create Service
- URL:
/services
- Method:
POST
- Description: Creates a new service.
- Request Body:
{ "name": "Hair Cut Appointment", "status": "active", "serviceType": "one_to_one", "availability": { "daysIntoFuture": 30, "lengthMinutes": 60, "bufferMinutes": 0, "mode": "roundrobin_random", "specificAvailability": null, "regularAvailability": null }, "description": "Hair Cut Appointment", "imageUrl": "https://www.example.com/images/haircut.jpg", "assetId": "", "resourceIds": [], "location": { "lat": 0, "lon": 0, "name": "The Saloon, Dubai", "address": { "street": "123 Main St", "city": "Dubai", "state": "", "country": "UAE", "postalCode": "" } }, "categories": ["haircuts", "beauty"], "tags": ["short-hair", "long-hair"], "price": { "amount": 30, "currency": "USD", "taxes": [{ "name": "GST", "rate": 0.18, "included": false }] }, "customerFields": { "customerName": { "label": "Name", "type": "text", "required": true }, "customerEmail": { "label": "Email Address", "type": "email", "required": true } } }
- Response:
- Success:
201 Created
{ "id": "string", "name": "Hair Cut Appointment", "orgId": "org123", "status": "active", "availability": { "daysIntoFuture": 30, "lengthMinutes": 60, "bufferMinutes": 0 }, "description": "Hair Cut Appointment", "imageUrl": "https://www.example.com/images/haircut.jpg", "assetId": "", "resourceIds": [], "location": { "lat": 0, "lon": 0, "name": "The Saloon, Dubai", "address": { "street": "123 Main St", "city": "Dubai", "state": "", "country": "UAE", "postalCode": "" } }, "categories": ["haircuts", "beauty"], "tags": ["short-hair", "long-hair"], "price": { "amount": 30, "currency": "USD", "taxes": [{ "name": "GST", "rate": 0.18, "included": false }] } }
- Error:
400 Bad Request
{ "message": "Invalid input", "errors": ["name is required and must be a non-empty string"] }
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Detailed error message" }
- Success:
2. Get Service by ID
- URL:
/services/:id
- Method:
GET
- Description: Retrieves a specific service by its ID.
- Response:
- Success:
200 OK
{ "id": "string", "name": "Hair Cut Appointment", "orgId": "org123", "status": "active", "availability": { "daysIntoFuture": 30, "lengthMinutes": 60, "bufferMinutes": 0 }, "description": "Hair Cut Appointment", "imageUrl": "https://www.example.com/images/haircut.jpg", "assetId": "", "resourceIds": [], "location": { "lat": 0, "lon": 0, "name": "The Saloon, Dubai", "address": { "street": "123 Main St", "city": "Dubai", "state": "", "country": "UAE", "postalCode": "" } }, "categories": ["haircuts", "beauty"], "tags": ["short-hair", "long-hair"], "price": { "amount": 30, "currency": "USD", "taxes": [{ "name": "GST", "rate": 0.18, "included": false }] } }
- Error:
404 Not Found
{ "message": "Service not found" }
- Error:
403 Forbidden
{ "message": "Service does not belong to the specified organization" }
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Detailed error message" }
- Success:
3. Update Service
- URL:
/services/:id
- Method:
PUT
- Description: Updates an existing service.
- Request Body:
{ "id": "string", "name": "Hair Cut Appointment", "orgId": "org123", "status": "active", "availability": { "daysIntoFuture": 30, "lengthMinutes": 60, "bufferMinutes": 0 }, "description": "Hair Cut Appointment", "imageUrl": "https://www.example.com/images/haircut.jpg", "assetId": "", "resourceIds": [], "location": { "lat": 0, "lon": 0, "name": "The Saloon, Dubai", "address": { "street": "123 Main St", "city": "Dubai", "state": "", "country": "UAE", "postalCode": "" } }, "categories": ["haircuts", "beauty"], "tags": ["short-hair", "long-hair"], "price": { "amount": 30, "currency": "USD", "taxes": [{ "name": "GST", "rate": 0.18, "included": false }] } }
- Response:
- Success:
200 OK
(Returns the updated service object)// Example: Returns the full updated service object { "id": "string", "name": "Hair Cut Appointment", "orgId": "org123", "status": "active", "availability": { "daysIntoFuture": 30, "lengthMinutes": 60, "bufferMinutes": 0 }, "description": "Hair Cut Appointment", "imageUrl": "https://www.example.com/images/haircut.jpg", "assetId": "", "resourceIds": [], "location": { "lat": 0, "lon": 0, "name": "The Saloon, Dubai", "address": { "street": "123 Main St", "city": "Dubai", "state": "", "country": "UAE", "postalCode": "" } }, "categories": ["haircuts", "beauty"], "tags": ["short-hair", "long-hair"], "price": { "amount": 30, "currency": "USD", "taxes": [{ "name": "GST", "rate": 0.18, "included": false }] } }
- Error:
404 Not Found
{ "message": "Service not found" }
- Error:
403 Forbidden
{ "message": "Service does not belong to the specified organization" }
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Detailed error message" }
- Success:
4. Delete Service
- URL:
/services/:id
- Method:
DELETE
- Description: Deletes a service.
- Response:
- Success:
200 OK
{ "message": "Service deleted successfully" }
- Error:
404 Not Found
{ "message": "Service not found" }
- Error:
403 Forbidden
{ "message": "Service does not belong to the specified organization" }
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Detailed error message" }
- Success:
5. Get Services
- URL:
/services
- Method:
GET
- Description: Retrieves all services.
- Response:
- Success:
200 OK
[ { "id": "string", "name": "Hair Cut Appointment", "orgId": "org123", "status": "active", "availability": { "daysIntoFuture": 30, "lengthMinutes": 60, "bufferMinutes": 0 }, "description": "Hair Cut Appointment", "imageUrl": "https://www.example.com/images/haircut.jpg", "assetId": "", "resourceIds": [], "serviceType": "one_to_one", "location": { "lat": 0, "lon": 0, "name": "The Saloon, Dubai" }, "categories": ["haircuts", "beauty"], "tags": ["short-hair", "long-hair"], "price": { "amount": 30, "currency": "USD", "taxes": [{ "name": "GST", "rate": 0.18, "included": false }] }, "customerFields": null }, { "id": "string", "name": "Hair Coloring", "orgId": "org123", "status": "active", "serviceType": "one_to_one", "availability": { "daysIntoFuture": 30, "lengthMinutes": 120, "bufferMinutes": 15, "mode": "mutual", "regularAvailability": null, "specificAvailability": null }, "price": { "amount": 80, "currency": "USD" }, "customerFields": null } ]
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Detailed error message" }
- Success: