Online booking for digital assistants

Use these public lookup endpoints to find treatments, employees and available appointments. Then give the customer a prefilled booking link. The customer selects a time, enters their personal details and confirms the booking on the booking page.

Download the OpenAPI description (JSON)

Recommended workflow

  1. Load treatments and packages using gettreatments. Match the customer's requested treatment to NameHomepage and check its category and description.
  2. Load employees using getcontacts. If the customer requests Sarah, find Sarah in this response and use her current Id. If several entries match, ask which employee they mean.
  3. Call gettimes with the selected treatment or package, the earliest search date and the chosen employee's ID.
  4. Describe the returned times to the customer and provide a prefilled booking link with the same treatment, date and employee.
  5. The customer chooses a time and completes the booking. A lookup or a prefilled link does not reserve a time or create a booking.

Always use IDs returned by the current API responses. Example IDs below are illustrative; employee 216 is not asserted to be Sarah. If no times are found for the requested employee, report that result and ask before searching with a different employee.

API endpoints

The API base is the same origin as the booking page. For FACE & BODY Day Spa it is https://www.dayspa.faceandbody.de. All three lookup endpoints use POST, even though they only retrieve information. They do not require a booking login or Bearer token. Send Accept: application/json.

1. Treatments and packages

POST /module/booksystem/calendaritems/gettreatments/ — no request parameters.

curl --request POST \
  --header 'Accept: application/json' \
  'https://www.dayspa.faceandbody.de/module/booksystem/calendaritems/gettreatments/'

The response is a JSON array. Abbreviated, illustrative example:

[
  {
    "Id": 22,
    "Mode": 1,
    "Category": "Facial treatments",
    "NameHomepage": "Example facial treatment",
    "PriceGross": 95.00,
    "AttributeItems": "",
    "DescriptionHomepage": "Example description",
    "CategoryDescriptionHomepage": ""
  }
]

Mode = 1 means a service; Mode = 2 means a package. For availability, construct each item as Mode_Id: service 22 becomes 1_22, package 22 becomes 2_22. For booking links, these become t=22 and t=p22, respectively.

2. Employees

POST /module/booksystem/calendaritems/getcontacts/ — no request parameters.

curl --request POST \
  --header 'Accept: application/json' \
  'https://www.dayspa.faceandbody.de/module/booksystem/calendaritems/getcontacts/'

The response is a JSON array. Use Id for filtering and Name as the display name. Names may include a surname or initial to distinguish employees with the same first name. An abbreviated, illustrative response is:

[
  { "Id": 216, "Name": "Example employee", "Firstname": "Example", "Lastname": "Employee" }
]

Being listed here does not guarantee availability for every treatment. Query gettimes with the chosen treatment and employee together.

3. Available appointments

POST /module/booksystem/calendaritems/gettimes/ — send a JSON object with Content-Type: application/json:

FieldValue
ItemsA nonempty array of Mode_Id strings, such as ["1_22"] or ["2_22"]. Multiple items are supported for the availability search.
DateTimeEarliest search date. Use dd.MM.yyyy on this German booking installation, for example 09.12.2026. This API field differs from the ISO date used in booking links.
PersonIdThe employee's integer Id. Omit it or send null for any employee. Keep the specific ID when the customer requested an employee.
curl --request POST \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{"Items":["1_22"],"DateTime":"09.12.2026","PersonId":216}' \
  'https://www.dayspa.faceandbody.de/module/booksystem/calendaritems/gettimes/'

This endpoint returns a JSON string containing a JSON array. Parse the HTTP response as JSON, then parse that string again. Illustrative response body as sent over HTTP:

"[{\"DateString\":\"09.12.2026\",\"DayString\":\"Mi\",\"TimeString\":\"10:00\"}]"

After the second parse:

[
  { "DateString": "09.12.2026", "DayString": "Mi", "TimeString": "10:00" }
]

These are local business dates and times, without a UTC offset. The response does not contain an employee ID; retain the employee filter from your request. An empty result is the JSON string "[]". Availability can change before the customer finishes booking.

Append the following query parameters to the actual booking page URL:

ParameterMeaning
tOne service ID, for example 22, or a package ID prefixed with p, for example p22. This differs from the API's Items format.
dateEarliest search date in YYYY-MM-DD format. It starts the search on or after this date; it does not select an appointment.
employeeOptional employee ID from getcontacts. Include it when the customer wants a specific employee.

FACE & BODY example (replace the illustrative IDs with current results):

https://www.dayspa.faceandbody.de/de/online-buchen/?t=22&date=2026-12-09&employee=216

For a package, use ?t=p22&date=2026-12-09&employee=216. A link prefills a single service or package. There is no supported time-selection parameter and no multi-service link format. The customer selects a time and completes the booking in a JavaScript-enabled browser. Other installations can have a different booking page path.

Response handling

Check HTTP status codes and validate the response shape. In particular, gettimes can return an error message inside a JSON string even with HTTP status 200. A parsing error or an unexpected response is a failed lookup, not evidence that no appointments exist.

async function findAppointments(baseUrl, serviceId, employeeId, earliestDate) {
  const response = await fetch(new URL('/module/booksystem/calendaritems/gettimes/', baseUrl), {
    method: 'POST',
    headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      Items: ['1_' + serviceId],
      DateTime: earliestDate, // dd.MM.yyyy, for example '09.12.2026'
      PersonId: employeeId
    })
  });
  if (!response.ok) throw new Error('Availability lookup failed');
  const encoded = await response.json();
  if (typeof encoded !== 'string') throw new Error('Unexpected availability response');
  const times = JSON.parse(encoded);
  if (!Array.isArray(times) || !times.every(time =>
    time && typeof time.DateString === 'string' &&
    typeof time.DayString === 'string' && typeof time.TimeString === 'string'
  )) throw new Error('Unexpected appointment data');
  return times;
}

Field names are case-sensitive for clients reading the returned JSON: use Id, Name, DateString, DayString and TimeString as shown. Query the booking site's own origin. Browser integrations on other origins depend on that site's CORS policy.