Services
The service catalog powers Advanced Booking. Each service is a bookable template (duration, price, color, team members). Public booking widgets, calendar integrations and the tenant admin UI all read this list.
Endpoints
| Path | Required scope |
|---|---|
| GET /services | bookings.services.read |
| GET /services/:id | bookings.services.read |
| POST /services | bookings.services.write |
| PATCH /services/:id | bookings.services.write |
| DELETE /services/:id | bookings.services.write |
DELETE performs a soft-deactivate (sets active=false). Hard delete is blocked because existing bookings reference the service. To restore a service, PATCH it with { "active": true }.
List filters
active=trueoractive=false— hide/show inactive serviceslimit— 1-100, default 50starting_after— cursor fromnext_cursorof previous page
Create a service
Required: name + duration_minutes. Everything else is optional with sensible defaults.
curl -X POST https://app.staffifyai.com/api/workspace/v1/services \
-H "Authorization: Bearer $STAFFIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Standard installation",
"duration_minutes": 60,
"buffer_minutes": 15,
"price": "149.00",
"price_includes_vat": true,
"color": "#F97316",
"team_member_ids": [12, 15]
}'Fields
| Field | Type | Description |
|---|---|---|
| id | integer | Primary key |
| name | string | Display name shown in booking flows |
| description | string | Optional long description |
| duration_minutes | integer | Slot length. 5-480 minutes. |
| buffer_minutes | integer | Post-service buffer (0-240 min) |
| price | string | Decimal string, e.g. "49.95". Null = free. |
| price_is_from | boolean | If true, UI shows "from €49.95" (indicative pricing) |
| price_includes_vat | boolean | true = gross price. false = net (VAT added on top). Default false. |
| currency | string | ISO-4217 code (default EUR) |
| color | string | Hex color used in calendars/widgets |
| active | boolean | false = hidden from booking flows. DELETE sets this to false. |
| sort_order | integer | Lower = earlier in catalog |
| require_photos | boolean | Prompt for photos on booking |
| require_postcode_check | boolean | Prompt for postcode gating |
| custom_fields | object | Free-form JSON for integration metadata |
| payment_mode | enum('inherit','none','deposit','full') | Per-service override of tenant-default payment behavior |
| deposit_amount_override | string | Decimal string. Interpreted per deposit_type_override. |
| deposit_type_override | enum('fixed','percentage') | How deposit_amount_override is interpreted |
| team_member_ids | integer[] | Which team members can be booked for this service |
| created_at | string(ISO) | When the service was created |
| updated_at | string(ISO) | Last modification |
Webhook events
service.created— new service addedservice.updated— any field changeservice.deactivated— DELETE call completed