Reference
Endpoint reference
Every endpoint in v1, organised by resource. All paths are relative to the base URL https://rest.setora.co.uk/v1.
Locations, services & staff
Read-only resources that describe what a shop sells, where, and who delivers it. These endpoints are the starting point for any booking flow.
/locationsList the locations belonging to the authenticated organisation. Returns active locations only.
Scope required · read
Response fields
idstring · UUIDUnique identifier for the location.
slugstringURL-safe identifier used in API paths (e.g. /locations/soho/…).
namestringDisplay name of the location.
timezonestring · IANAIANA timezone identifier. All availability slots for this location are returned in this timezone.
street_addressstringStreet-level address line.
citystringCity or town.
postal_codestringPostal or ZIP code.
countrystring · ISO 3166-1Two-letter country code.
{
"data": [
{
"id": "4f8d3a91-2b6c-4e7f-9a01-1c5d8e2f6b3a",
"slug": "soho",
"name": "Soho",
"timezone": "Europe/London",
"street_address": "12 Berwick Street",
"city": "London",
"postal_code": "W1F 0PT",
"country": "GB"
}
]
}/locations/{slug}/servicesList the services bookable at a location, including pricing, duration, deposit requirement, and which staff can deliver each service. Pricing and duration may differ from the org-wide default if a per-location override is set.
Scope required · read
Response fields
idstring · UUIDUnique identifier for the service.
namestringDisplay name of the service.
duration_minutesintegerLength of the service in minutes.
priceobjectContains amount (integer, minor units) and currency (ISO 4217). May differ from the org-wide default if a per-location override is set.
depositobject | nullDeposit required to confirm a booking. null when no deposit is needed. Contains amount and currency.
categorystringService category label set by the shop.
online_bookablebooleanWhether the service is available for online booking. Services with false can only be booked in-person.
staffarrayStaff members who can deliver this service. Each object contains id (UUID) and name.
{
"data": [
{
"id": "2a7c9e34-58b1-41f6-8d92-6e4a3b0c7d15",
"name": "Haircut",
"duration_minutes": 30,
"price": { "amount": 2500, "currency": "GBP" },
"deposit": { "amount": 500, "currency": "GBP" }, // null when no deposit
"category": "Hair",
"online_bookable": true,
"staff": [
{ "id": "9b3e7d2c-4a1f-48e6-bc52-7f0a9d3b1e84", "name": "Kai" },
{ "id": "c1d4f8a2-6e3b-49d7-a085-2b8c5f1e7d39", "name": "Jordan" }
]
}
]
}/locations/{slug}/staffList active staff at a location. Each staff member returns the services they can deliver, so callers can filter availability accordingly.
Scope required · read
Response fields
idstring · UUIDUnique identifier for the staff member.
namestringDisplay name of the staff member.
service_idsstring[]UUIDs of the services this staff member can deliver. Use these to filter availability.
{
"data": [
{
"id": "9b3e7d2c-4a1f-48e6-bc52-7f0a9d3b1e84",
"name": "Kai",
"service_ids": ["2a7c9e34-58b1-41f6-8d92-6e4a3b0c7d15", "e8b1d4f2-3a9c-47e5-bd06-4c7f2a1e8b39"]
}
]
}Availability
Real-time slot lookup. Backed by the same engine as the public booking portal, so deposit rules and lead-time windows are honoured automatically.
/locations/{slug}/availabilityReturn bookable slots for one or more services at a location. Slots are returned in the location's local timezone with a UTC offset.
Scope required · read
service_idsrequired
string · comma-separated UUIDsOne or more service IDs. Determines total slot length and which staff are eligible. For multi-service bookings, pass all service IDs.
daterequired
string · YYYY-MM-DDLocal date to start the search from, in the location's timezone.
daysinteger · 1 – 14Number of days to search forward from date. Defaults to 1.
staff_idstringRestrict results to a specific staff member. Omit for any-staff availability.
curl https://rest.setora.co.uk/v1/locations/soho/availability \
-G \
--data-urlencode "service_ids=2a7c9e34-58b1-41f6-8d92-6e4a3b0c7d15" \
--data-urlencode "date=2026-05-12" \
--data-urlencode "days=3" \
-H "Authorization: Bearer sk_live_..."Response fields
location_slugstringThe location these slots belong to.
timezonestring · IANAIANA timezone of the location. All slot times are expressed in this timezone.
service_idsstring[]The service IDs that were queried.
durationobjectTotal slot duration. Contains minutes (integer) and display (human-readable string).
slotsarrayAvailable time slots. Each contains starts_at, ends_at (ISO 8601 with UTC offset), and staff_id (UUID of the assigned staff member).
{
"data": {
"location_slug": "soho",
"timezone": "Europe/London",
"service_ids": ["2a7c9e34-58b1-41f6-8d92-6e4a3b0c7d15"],
"duration": { "minutes": 30, "display": "30 mins" },
"slots": [
{
"starts_at": "2026-05-12T09:00:00+01:00",
"ends_at": "2026-05-12T09:30:00+01:00",
"staff_id": "9b3e7d2c-4a1f-48e6-bc52-7f0a9d3b1e84"
},
{
"starts_at": "2026-05-12T09:30:00+01:00",
"ends_at": "2026-05-12T10:00:00+01:00",
"staff_id": "9b3e7d2c-4a1f-48e6-bc52-7f0a9d3b1e84"
},
{
"starts_at": "2026-05-13T11:00:00+01:00",
"ends_at": "2026-05-13T11:30:00+01:00",
"staff_id": "c1d4f8a2-6e3b-49d7-a085-2b8c5f1e7d39"
}
]
}
}Clients
Look up a returning client by phone or email, or create a new client record before booking.
/clientsLook up a client by phone or email. At least one parameter is required. Returns at most one client per match within an organisation.
Scope required · read
phonestring · E.164The full phone number including country code. UK numbers should be sent as +44…, not 0…
emailstringEmail address to search for. At least one of phone or email is required.
Response fields
idstring · UUIDUnique identifier for the client.
first_namestringClient's first name.
last_namestringClient's last name.
phonestring · E.164Phone number including country code.
emailstringEmail address.
marketing_consentbooleanWhether the client has opted in to marketing communications.
created_atstring · ISO 8601When the client record was created (UTC).
{
"data": {
"id": "5d9f2a18-7c4e-46b3-a821-3e0b4c8d1f72",
"first_name": "Alex",
"last_name": "Carter",
"phone": "+447700900123",
"email": "alex@example.com",
"marketing_consent": false,
"created_at": "2025-11-04T10:22:00Z"
}
}{
"error": {
"code": "not_found",
"message": "No client found matching the provided phone or email."
}
}/clientsCreate a new client. At least one of phone or email is required. If a matching phone or email already exists in the organisation, the existing client is returned rather than a duplicate created.
Scope required · read_write
first_namerequired
stringFirst name. 1 – 60 characters.
last_namerequired
stringLast name. 1 – 60 characters.
phonestring · E.164Phone number, used for SMS reminders. At least one of phone or email is required.
emailstringEmail address, used for email reminders and receipts. At least one of phone or email is required.
marketing_consentbooleanDefaults to false. Only set to true if the client has actively opted in.
curl https://rest.setora.co.uk/v1/clients \
-X POST \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"first_name": "Alex",
"last_name": "Carter",
"phone": "+447700900123",
"email": "alex@example.com"
}'{
"data": {
"id": "5d9f2a18-7c4e-46b3-a821-3e0b4c8d1f72",
"first_name": "Alex",
"last_name": "Carter",
"phone": "+447700900123",
"email": "alex@example.com",
"marketing_consent": false,
"created_at": "2026-05-01T12:00:00Z"
}
}Bookings
Create, fetch, reschedule and cancel bookings. POST /bookings supports an Idempotency-Key for safe retries.
pending_paymentBooking created but a deposit is required. The client should be directed to the payment_url. The booking will move to confirmed once the deposit is paid.
confirmedDeposit paid (or no deposit required). The booking is live and visible to staff in the Hub.
completedThe appointment has been fulfilled. Set by staff in the Hub after the service is delivered.
no_showThe client did not attend. Set by staff in the Hub. The deposit is not refunded.
cancelledThe booking was cancelled. Whether the deposit was refunded depends on the shop's cancellation policy window.
/bookingsCreate a booking. If the service requires a deposit, the response includes a hosted payment_url. The booking is held in pending state until the deposit is paid; pass an Idempotency-Key for safe retries.
Scope required · read_write
location_slugrequired
stringThe slug of the location the booking is for.
service_idsrequired
string[]One or more service IDs. Each must be bookable online at the location.
staff_idstringOptional. Omit to use any-staff assignment. Must be eligible for all requested services.
client_idrequired
stringAn existing client. Use POST /clients first if needed.
starts_atrequired
string · ISO 8601Slot start time. Must match a slot returned by /availability.
notesstringOptional. Free text shown to staff in the Hub.
Response fields
referencestringHuman-readable booking reference.
statusstringCurrent booking status. See the status table above for all possible values.
depositobjectPresent when a deposit is required. Contains amount (minor units) and currency.
payment_urlstring · URLPresent when a deposit is required. A hosted checkout page the client should be directed to in order to pay the deposit. The booking remains in pending_payment until payment completes.
curl https://rest.setora.co.uk/v1/bookings \
-X POST \
-H "Authorization: Bearer sk_live_..." \
-H "Idempotency-Key: 6d0e2f88-b7e5-4d6a-9f77-0b2bb2c4e9d1" \
-H "Content-Type: application/json" \
-d '{
"location_slug": "soho",
"service_ids": ["2a7c9e34-58b1-41f6-8d92-6e4a3b0c7d15"],
"client_id": "5d9f2a18-7c4e-46b3-a821-3e0b4c8d1f72",
"starts_at": "2026-05-12T09:30:00+01:00"
}'{
"data": {
"reference": "SET-A1B2C3",
"status": "pending_payment",
"location_slug": "soho",
"service_ids": ["2a7c9e34-58b1-41f6-8d92-6e4a3b0c7d15"],
"staff_id": "9b3e7d2c-4a1f-48e6-bc52-7f0a9d3b1e84",
"client_id": "5d9f2a18-7c4e-46b3-a821-3e0b4c8d1f72",
"starts_at": "2026-05-12T09:30:00+01:00",
"ends_at": "2026-05-12T10:00:00+01:00",
"deposit": { "amount": 500, "currency": "GBP" },
"payment_url": "https://pay.setora.co.uk/checkout/cs_live_..."
}
}/bookings/{reference}Fetch a single booking by reference, including current status and any associated payment URL.
Scope required · read
Response fields
referencestringHuman-readable booking reference (e.g. SET-A1B2C3).
statusstringCurrent booking status. See the status table above.
location_slugstringThe location the booking is at.
service_idsstring[]Services included in this booking.
staff_idstring · UUIDThe assigned staff member.
client_idstring · UUIDThe client who made the booking.
starts_atstring · ISO 8601Appointment start time in the location's local timezone.
ends_atstring · ISO 8601Appointment end time in the location's local timezone.
created_atstring · ISO 8601When the booking was created (UTC).
updated_atstring · ISO 8601When the booking was last modified (UTC).
{
"data": {
"reference": "SET-A1B2C3",
"status": "confirmed",
"location_slug": "soho",
"service_ids": ["2a7c9e34-58b1-41f6-8d92-6e4a3b0c7d15"],
"staff_id": "9b3e7d2c-4a1f-48e6-bc52-7f0a9d3b1e84",
"client_id": "5d9f2a18-7c4e-46b3-a821-3e0b4c8d1f72",
"starts_at": "2026-05-12T09:30:00+01:00",
"ends_at": "2026-05-12T10:00:00+01:00",
"created_at": "2026-04-30T15:01:22Z",
"updated_at": "2026-04-30T15:02:08Z"
}
}/bookings/{reference}Reschedule a booking. The new start must be a valid slot for the same service at the same location. Cancellation policy windows are enforced, and late changes return a 409.
Scope required · read_write
starts_atrequired
string · ISO 8601The new slot start time.
staff_idstringOptional. Reassign to a different eligible staff member.
/bookings/{reference}/cancelCancel a booking. The shop's cancellation policy controls whether a deposit is refunded. The endpoint never mutates the deposit on its own; it only triggers the policy.
Scope required · read_write
reasonstringOptional. Free text shown to staff. Useful when an AI agent records the client's stated reason.
Response fields
referencestringThe booking reference.
statusstringAlways "cancelled" on success.
cancelled_atstring · ISO 8601When the cancellation was processed (UTC).
deposit_refundedbooleanWhether the deposit was refunded, based on the shop's cancellation policy window.
{
"data": {
"reference": "SET-A1B2C3",
"status": "cancelled",
"cancelled_at": "2026-05-11T18:14:00Z",
"deposit_refunded": false
}
}