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.

OptionAccepted FieldsExplanation
1account_user_id or public_user_id or owner_idOne of these values is required to create the record.
2page_id or doctor_data_id or builder_page_id or builder_id or appointment_builder_id or idOne of these values is required to create the record.
3cust_id or customer_id or hashed_id or hased_id or customer_hash or name with email or mobileOne 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

NameTypeSampleExplanation
account_user_id
post
int47Account 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_id
post
int22636Doctor/team-member id selected from Public.AppointmentBuilder.Slots. Alias: one_doctor.
appointment_type_id
post
int8Appointment type id selected from Public.AppointmentBuilder.Slots. Aliases: appointments_type_id, appointments_type_data_id.
date
post
date2026-07-22Appointment 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_time
post
time09:00Appointment 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_time
post
time09:30Appointment 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

NameTypeSampleWhat it gives
page_id
post
string|int3001Builder page id. You may also send doctor_data_id or builder_page_id. Required when builder_id is not sent.
builder_id
post
int12Appointment-builder row id. You may also send appointment_builder_id or id. Required when page_id is not sent.
group_for_cust_id
post
int2458Assigned 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_id
post
int532Appointment package/group id from Public.AppointmentBuilder.Slots customer_appointment_groups[].appointment_group_id. Alias: appo_group_id.
name
post
stringDaniel CohenCustomer or patient name. Required only when cust_id/customer_id/hashed_id is not sent. Alias: patient_name.
email
post
email[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.
mobile
post
phone0500000000Customer 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_id
post
int123Existing 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_id
post
string7bPublic 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.
subject
post
stringInitial consultationAppointment subject. If empty, the appointment type name is used.
notes
post
stringCustomer prefers morningAppointment notes.
source
post
stringwebsiteCustomer source saved when a new customer is created. Default: public_appointment.
approved_by_customer
post
int1Use 1 when this is a customer-approved public booking. Default: 1.
total_price
post
number250Override total price. Defaults to the selected appointment type price. Alias: total_product_price.
branch_id
post
int2Optional branch id. Alias: branch.
room_id
post
int5Optional appointment room id. Alias: appointment_room_id.
resources
post
json[]Optional selected resource ids as JSON array.
product_ids
post
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.Submit

Sample 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"
}