POST
Public.AppointmentBuilder.Submit
Submit a public appointment booking from an appointment-builder UI. The route checks the account, builder, doctor, appointment type, date, working hours, and slot availability. It finds or creates the customer, creates doctor_appointment_for_cust, then returns the appointment id as JSON.
Required Choice
Send at least one complete option from the list below.
| Option | Accepted Fields | Explanation |
|---|---|---|
| 1 | account_user_id or public_user_id or owner_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. |
| 3 | cust_id or customer_id or hashed_id or hased_id or customer_hash or name with email or mobile | 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.
- The doctor and appointment type must be allowed by this appointment builder.
Action
- Validates that the selected slot is allowed and not already booked.
- Finds an existing customer by cust_id, hashed_id, email, mobile, or phone, or creates a new customer when no match exists.
- Creates a row in doctor_appointment_for_cust with the selected date, time, doctor, appointment type, patient data, notes, and totals.
- When group_for_cust_id and appointment_group_id are sent, links this appointment date to that customer appointment package.
- Stores the internal calendar event_id safely on the appointment row. Public clients do not need to send event_id.
Push Service
Pushes public.appointmentbuilder.submit.created to the account owner, selected doctor/team member, and submitted account user so open calendars can refresh.
Automation
Runs automation event add_appointment with appointment_id, customer_id, doctor_id, appointment_type_id, date, start_time, and end_time.
Special Instructions
- Call Public.AppointmentBuilder.Slots first and submit only a slot returned by that route.
- To book a date into a package/group: call Slots with customer hash/id, pick a customer_appointment_groups row, choose an unscheduled appointment_items row, then submit group_for_cust_id, appointment_group_id, and that item appointment_type_id with the chosen date/time.
- If you already have cust_id, customer_id, hashed_id, hased_id, or customer_hash, send it and the route will use that existing customer. In this case name, email, mobile, phone, and patient fields are optional.
- If no existing customer id/hash is sent, send name and at least one contact value: email or mobile/phone. The route will search by email/mobile/phone and create a customer only when no existing customer is found.
- Do not send event_id. It is an internal appointment/calendar field and the API fills it automatically.
- Do not send Authorization for this public route.
- Use Y-m-d for date values, for example 2026-07-22.
- Use H:i or H:i:s for time values, for example 09:00 or 09:00:00.
- If the route returns HTTP 409, the slot was booked by someone else and the UI should reload slots.
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. Aliases: public_user_id, user_id, owner_id. |
doctor_idpost | int | 22636 | Doctor/team-member id selected from Public.AppointmentBuilder.Slots. Alias: one_doctor. |
appointment_type_idpost | int | 8 | Appointment type id selected from Public.AppointmentBuilder.Slots. Aliases: appointments_type_id, appointments_type_data_id. |
datepost | date | 2026-07-22 | Appointment date in Y-m-d format. 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. |
start_timepost | time | 09:00 | Appointment start time in H:i or H:i:s format. Alias: time. Send time values as H:i:s. If the route also has a date field, send that date as UTC Y-m-d H:i:s. |
end_timepost | time | 09:30 | Appointment end time in H:i or H:i:s format. Alias: end. Send time values as H:i:s. If the route also has a date field, send that date as UTC Y-m-d H:i:s. |
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. |
group_for_cust_idpost | int | 2458 | Assigned customer package row id from Public.AppointmentBuilder.Slots customer_appointment_groups[].group_for_cust_id. Aliases: data_grp_for_cust_id, appointment_group_for_cust_id. Send with appointment_group_id to book this date into a package. |
appointment_group_idpost | int | 532 | Appointment package/group id from Public.AppointmentBuilder.Slots customer_appointment_groups[].appointment_group_id. Alias: appo_group_id. |
namepost | string | Daniel Cohen | Customer or patient name. Required only when cust_id/customer_id/hashed_id is not sent. Alias: patient_name. |
emailpost | [email protected] | Customer or patient email. Optional when cust_id/customer_id/hashed_id is sent. If no existing customer id/hash is sent, send email or mobile/phone. Alias: patient_email. | |
mobilepost | phone | 0500000000 | Customer or patient mobile. Optional when cust_id/customer_id/hashed_id is sent. If no existing customer id/hash is sent, send mobile/phone or email. Aliases: phone, patient_phone. |
cust_idpost | int | 123 | Existing customer id. When sent, all customer identity/contact fields are optional. If empty, the route searches by hashed_id, email, mobile, or phone and creates a customer if needed. Alias: customer_id. |
hashed_idpost | string | 7b | Public customer hash from customer links. When sent, all customer identity/contact fields are optional. Use this when the public page has a customer hash but not the numeric customer id. Aliases: hased_id, customer_hash. |
subjectpost | string | Initial consultation | Appointment subject. If empty, the appointment type name is used. |
notespost | string | Customer prefers morning | Appointment notes. |
sourcepost | string | website | Customer source saved when a new customer is created. Default: public_appointment. |
approved_by_customerpost | int | 1 | Use 1 when this is a customer-approved public booking. Default: 1. |
total_pricepost | number | 250 | Override total price. Defaults to the selected appointment type price. Alias: total_product_price. |
branch_idpost | int | 2 | Optional branch id. Alias: branch. |
room_idpost | int | 5 | Optional appointment room id. Alias: appointment_room_id. |
resourcespost | json | [] | Optional selected resource ids as JSON array. |
product_idspost | json | [] | Optional selected product ids as JSON array. |
Sample Request
{
"url": "\/app\/Public.AppointmentBuilder.Submit",
"method": "POST",
"headers": [],
"body": {
"account_user_id": "47",
"page_id": "3001",
"doctor_id": "22636",
"appointment_type_id": "8",
"group_for_cust_id": "2458",
"appointment_group_id": "532",
"date": "2026-07-22",
"start_time": "09:00",
"end_time": "09:30",
"name": "Daniel Cohen",
"mobile": "0500000000",
"notes": "Customer prefers morning"
},
"url_user": "https:\/\/{user}.bull36.com\/app\/Public.AppointmentBuilder.Submit",
"url_domain": "https:\/\/{domain}\/app\/Public.AppointmentBuilder.Submit"
}Endpoint
POST /app/Public.AppointmentBuilder.Submit
POST https://{user}.bull36.com/app/Public.AppointmentBuilder.Submit
POST https://{domain}/app/Public.AppointmentBuilder.SubmitSample Output
{
"success": 1,
"public": 1,
"message": "Appointment created",
"appointment_id": 456,
"doctor_appointment_for_cust_id": 456,
"customer_id": 123,
"cust_id": 123,
"hased_id": "7b",
"hashed_id": "7b",
"customer_created": 1,
"doctor_id": 22636,
"appointment_type_id": 8,
"appointment_group_id": 532,
"group_for_cust_id": 2458,
"appo_group_name": "3 meetings package",
"date": "2026-07-22",
"start_time": "09:00",
"end_time": "09:30",
"automation_event": "add_appointment",
"socket_event": "public.appointmentbuilder.submit.created"
}JavaScript Example
async function submitPublicAppointment({
domain = 'https://eli.bull36.com',
accountUserId,
pageId,
doctorId,
appointmentTypeId,
date,
startTime,
endTime,
name,
email,
mobile,
hashedId = '',
notes = ''
}) {
const body = new URLSearchParams({
account_user_id: String(accountUserId),
page_id: String(pageId),
doctor_id: String(doctorId),
appointment_type_id: String(appointmentTypeId),
date,
start_time: startTime,
end_time: endTime,
name,
email,
mobile,
notes
});
if (hashedId) body.set('hashed_id', hashedId);
const res = await fetch(`${domain}/app/Public.AppointmentBuilder.Submit`, {
method: 'POST',
body
});
const data = await res.json();
if (!data.success) throw new Error(data.message || 'Could not submit appointment');
return data;
}
const created = await submitPublicAppointment({
accountUserId: 47,
pageId: 3001,
doctorId: 22636,
appointmentTypeId: 8,
date: '2026-07-22',
startTime: '09:00',
endTime: '09:30',
name: 'Daniel Cohen',
email: '[email protected]',
mobile: '0500000000',
hashedId: '7b'
});
console.log(created.appointment_id);Error Example
{
"success": 0,
"message": "Selected appointment slot is no longer available"
}