POST
Public.AppointmentBuilder.Slots
Get appointment-builder settings and available slots for a public booking page. This method is used by customer-facing UI before submitting an appointment. It does not require login; the UI must send account_user_id and either the builder page id or builder id.
Required Choice
Send at least one complete option from the list below.
| Option | Accepted Fields | Explanation |
|---|---|---|
| 1 | account_user_id | One of these values is required to create the record. |
| 2 | page_id or doctor_data_id or builder_page_id or builder_id or appointment_builder_id or id | One of these values is required to create the record. |
Permissions
- This function is public and can be called without login or bearer token.
- The builder id or page id must belong to the account user sent in account_user_id.
Action
- Loads appointment-builder settings for the public booking page.
- Returns visible appointment types, visible doctors/team members, the requested date, and available slots as JSON.
- When cust_id, customer_id, hashed_id, hased_id, or customer_hash is sent, also returns that customer details, existing appointments, and assigned appointment groups (packages).
- Use the selected doctor_id, appointment_type_id, date, and time from this response when calling the public submit appointment route.
Push Service
No socket push is sent because this function only reads public booking data.
Automation
No automation is run because this function only reads slots and builder settings.
Special Instructions
- Do not send Authorization for this public route.
- Use Y-m-d for date values, for example 2026-07-22.
- If the response has settings.allowed_day = 0, the builder is not open for the requested day and slots will be empty.
- UI flow: call this route when the public booking page opens, render appointment_types as the service selector, render doctors as the team-member selector, and render slots as the available time buttons.
- When the customer changes date, appointment_type_id, or doctor_id, call this route again with the new values and replace the visible slots.
- Store the selected doctor_id, appointment_type_id, date, time, and end time from the chosen slot. These values are needed by the public appointment submit route.
- If the page already knows the customer, send cust_id/customer_id or hashed_id/hased_id/customer_hash. The response will include customer, customer_appointments, and customer_appointment_groups so the UI can show existing bookings and assigned packages before the customer submits another appointment.
- Each customer_appointment_groups row includes appointments_in_group_count, appointments_scheduled_count, appointments_remaining_count, appointments_have_dates, appointment_items, and appointment_dates so the UI can show package size and which meetings already have dates.
- If slots is empty, show an empty state and let the customer choose another date, appointment type, or doctor.
Required Parameters
| Name | Type | Sample | Explanation |
|---|---|---|---|
account_user_idpost | int | 47 | Account or team-member user id from the public appointment page link. The route resolves the organization owner from this user. |
Optional Parameters
| Name | Type | Sample | What it gives |
|---|---|---|---|
page_idpost | string|int | 3001 | Builder page id. You may also send doctor_data_id or builder_page_id. Required when builder_id is not sent. |
builder_idpost | int | 12 | Appointment-builder row id. You may also send appointment_builder_id or id. Required when page_id is not sent. |
datepost | date | 2026-07-22 | Date to return slots for in Y-m-d format. If empty, today is used. Send date filters and date values as UTC Y-m-d H:i:s when the route accepts date/time; date-only table columns store the Y-m-d date part. |
add_daypost | int | 1 | Move the requested date one day forward or backward. Allowed values are 1 and -1. |
doctor_idpost | int | 22636 | Return slots only for one team member/doctor. You may also send one_doctor. |
appointment_type_idpost | int | 8 | Use this appointment type to calculate slot duration. You may also send appointments_type_id. If empty, the builder default type is used, then the first visible type. |
durationpost | int | 30 | Override slot duration in minutes. Normally the route uses the selected appointment type duration. |
step_minutespost | int | 30 | Controls how often a new slot starts. If empty, it uses the slot duration. |
cust_idpost | int | 123 | Optional existing customer id. When sent, response includes customer and customer_appointments. Alias: customer_id. |
hashed_idpost | string | 7b | Optional public customer hash from customer links. When sent, response includes customer and customer_appointments. Aliases: hased_id, customer_hash. |
appointments_from_datepost | date | 2026-07-01 | Optional filter for returned customer appointments. Alias: from_date. Send date filters and date values as UTC Y-m-d H:i:s when the route accepts date/time; date-only table columns store the Y-m-d date part. |
appointments_to_datepost | date | 2026-07-31 | Optional filter for returned customer appointments. Alias: to_date. Send date filters and date values as UTC Y-m-d H:i:s when the route accepts date/time; date-only table columns store the Y-m-d date part. |
appointments_statuspost | int | 1 | Optional status filter for returned customer appointments. Alias: status. |
appointments_startpost | int | 0 | Offset for returned customer appointments. Alias: start or offset. |
appointments_limitpost | int | 25 | Max returned customer appointments. The maximum is 25. Alias: limit or length. |
Sample Request
{
"url": "\/app\/Public.AppointmentBuilder.Slots",
"method": "POST",
"headers": [],
"body": {
"account_user_id": "47",
"page_id": "3001",
"date": "2026-07-22",
"appointment_type_id": "8",
"hased_id": "7b"
},
"url_user": "https:\/\/{user}.bull36.com\/app\/Public.AppointmentBuilder.Slots",
"url_domain": "https:\/\/{domain}\/app\/Public.AppointmentBuilder.Slots"
}Endpoint
POST /app/Public.AppointmentBuilder.Slots
POST https://{user}.bull36.com/app/Public.AppointmentBuilder.Slots
POST https://{domain}/app/Public.AppointmentBuilder.SlotsSample Output
{
"success": 1,
"public": 1,
"date": "2026-07-22",
"settings": {
"duration_minutes": 30,
"step_minutes": 30,
"allowed_day": 1
},
"builder": {
"id": 12,
"page_id": "3001",
"page_name": "Book appointment",
"appointment_type_ids": [
8,
9
],
"doctor_ids": [
22636
],
"default_appointment_type_id": 8,
"default_doctor_id": 22636
},
"appointment_types": [
{
"id": 8,
"name": "Consultation",
"duration_minutes": 30,
"price": 250
}
],
"doctors": [
{
"id": 22636,
"name": "Team member",
"slots": [
{
"time": "09:00",
"end": "09:30",
"available": 1
}
]
}
],
"slots": [
{
"doctor_id": 22636,
"time": "09:00",
"end": "09:30",
"available": 1
}
],
"count": 1,
"customer": {
"id": 123,
"customer_id": 123,
"hased_id": "7b",
"hashed_id": "7b",
"name": "Daniel Cohen",
"phone": "0500000000",
"mobile": "0500000000"
},
"customer_appointments": [
{
"id": 456,
"appointment_id": 456,
"doctor_appointment_for_cust_id": 456,
"customer_id": 123,
"doctor_id": 22636,
"doctor_name": "Team member",
"appointment_type_id": 8,
"appointment_type_name": "Consultation",
"appointment_group_id": 12,
"group_for_cust_id": 55,
"group_name": "Skin package",
"date": "2026-07-22",
"start_time": "09:00",
"end_time": "09:30",
"subject": "Consultation",
"status": 1
}
],
"customer_appointments_count": 1,
"customer_appointments_start": 0,
"customer_appointments_limit": 25,
"customer_appointment_groups": [
{
"id": 55,
"assigned_id": 55,
"group_for_cust_id": 55,
"appointment_group_id": 12,
"appo_group_id": 12,
"appo_group_name": "Skin package",
"group_name": "Skin package",
"price": 1200,
"group_price": 1200,
"days": 30,
"appointment_seller_id": 47,
"seller_name": "Seller",
"appointments_in_group_count": 3,
"appointments_scheduled_count": 1,
"appointments_remaining_count": 2,
"appointments_have_dates": true,
"appointment_items": [
{
"appointment_type_id": 8,
"appointment_type_name": "Consultation",
"appointment_id": 456,
"has_date": true,
"date": "2026-07-22",
"start_time": "09:00",
"end_time": "09:30",
"doctor_id": 22636,
"doctor_name": "Team member"
},
{
"appointment_type_id": 8,
"appointment_type_name": "Consultation",
"appointment_id": 0,
"has_date": false,
"date": "",
"start_time": "",
"end_time": "",
"doctor_id": 0,
"doctor_name": ""
}
],
"appointment_dates": [
{
"appointment_id": 456,
"appointment_type_id": 8,
"appointment_type_name": "Consultation",
"date": "2026-07-22",
"start_time": "09:00",
"end_time": "09:30",
"doctor_id": 22636,
"doctor_name": "Team member"
}
]
}
],
"customer_appointment_groups_count": 1
}JavaScript Example
async function loadAppointmentBuilderSlots({
domain = 'https://eli.bull36.com',
accountUserId,
pageId,
date,
appointmentTypeId = '',
doctorId = ''
}) {
const body = new URLSearchParams({
account_user_id: String(accountUserId),
page_id: String(pageId),
date
});
if (appointmentTypeId) body.set('appointment_type_id', String(appointmentTypeId));
if (doctorId) body.set('doctor_id', String(doctorId));
const res = await fetch(`${domain}/app/Public.AppointmentBuilder.Slots`, {
method: 'POST',
body
});
const data = await res.json();
if (!data.success) throw new Error(data.message || 'Could not load appointment slots');
// Render these in the public UI and keep ids in state for submit appointment.
return {
builder: data.builder,
appointmentTypes: data.appointment_types,
doctors: data.doctors,
slots: data.slots,
selectedForSubmit: data.slots[0] ? {
doctor_id: data.slots[0].doctor_id,
appointment_type_id: appointmentTypeId || data.builder.default_appointment_type_id,
date: data.date,
time: data.slots[0].time,
end: data.slots[0].end
} : null
};
}
const result = await loadAppointmentBuilderSlots({
accountUserId: 47,
pageId: 3001,
date: '2026-07-22'
});
console.log(result);Error Example
{
"success": 0,
"message": "Appointment builder not found"
}