HLAI Experts

Guide · HighLevel API

Cloning a HighLevel calendar through the API loses its look: how to keep it

When you copy a GoHighLevel (GHL) calendar by reading it with GET and creating a new one from the response, the booking rules come across but parts of the booking page's look can go missing. In our tests the GET response left out the widget styling, custom CSS, logo and the guest and staff toggles, and a PUT carrying the full calendar body accepted them back. Find what the response is missing, send it yourself, and check the live booking page.

Rob EasonPublished

The clone books fine but looks wrong

The copy works. People can book it, the availability matches, and the API returned success. Then you open the booking page and it's wearing default styling instead of the colors, layout, CSS and logo the original had.

A success response only says the request was accepted. It tells you nothing about whether the copy looks like the original, and that's the part your clients see.

What the API gives back, and what it doesn't

HighLevel documents the read as GET /calendars/{calendarId}, which needs the calendars.readonly scope, and the update as PUT /calendars/{calendarId}, which needs calendars.write. The documented response does carry some presentation data: widgetType, which sets the calendar layout, along with widgetSlug and the cover image.

What we've found missing are the settings behind most of the look. In our tests these did not come back on GET:

  • widgetConfig, the widget's styling
  • codeBlock, the custom CSS
  • widgetLogo, the logo on the booking page
  • the guest and staff toggles on the booking page

Why the copy falls back to defaults

A clone built only from the GET response can't carry settings the response never had. The new calendar gets the rules it was given and defaults for everything else.

Two more things before you script this. Those fields aren't in HighLevel's documentation, so treat their names and shape as something that can change without notice, and read them fresh on every run. And the API marks meetingLocation as deprecated in favor of locationConfigurations, so copy the location from locationConfigurations.

Clone it with the look intact

This is the procedure that has held up in our own builds. Run it on one calendar and check the result by eye before you run it on many.

  1. Read the original with GET /calendars/{calendarId} and list the presentation settings missing from the response.
  2. Compare that response with what the original's public booking page actually shows, and note every difference.
  3. Give the copy its own booking URL. In the app this is the Custom URL, and HighLevel checks that it's available. In our tests it had to be unique within the sub-account.
  4. Send the missing look settings with PUT /calendars/{calendarId}, carrying the whole calendar body rather than only the fields you changed.
  5. Open the copy's booking page next to the original's and compare them.
  6. Check every website or funnel page that embeds a booking iframe. In our tests a hard-coded iframe stayed bound to the original calendar, so swap the embed wherever the copy should appear.
A success response means accepted, not identical. Open the booking page.

What trips up a clone script

Each of these can send a copy live with the wrong look, or leave a site booking into the old calendar.

  • Building the clone from GET alone and calling it done
  • Sending a partial body on the PUT; the full body is what worked for us
  • Reusing the original's URL instead of giving the copy its own
  • Hard-coding undocumented field names with no check that they're still there
  • Forgetting the booking embeds on your website and funnels

Rather have it set up for you?

We'll clone your calendars with their look carried over and compare every copy's booking page to the original. Your first step is a 30-minute 1:1 with Rob.

Book a 1:1 with Rob

Questions

Calendar clone questions

Does the HighLevel API return a calendar's custom CSS?
Not in our tests. The documented GET response includes widgetType, widgetSlug and the cover image, but the custom CSS, widget styling, logo and guest and staff toggles came back missing. Check it on your own account, since these fields aren't documented.
Will a PUT accept the missing styling fields?
In our tests, yes, when the request carried the full calendar body. HighLevel doesn't document those fields, so confirm the result on the booking page rather than trusting the response.
Why does my website still show the old calendar?
A booking iframe hard-coded to a calendar stays bound to it. The copy is a new calendar with its own URL, so update the embed anywhere the copy should appear.
Which scopes does a calendar clone need?
calendars.readonly to read the original and calendars.write to update the copy. Check that your private integration or app has both before the first run.
Can two calendars share a booking URL?
No. The copy needs its own available Custom URL, which HighLevel checks when you set it. In our builds it also had to be unique within the sub-account.
Rob Eason

Who you talk to

Rob Eason

Rob runs HLAI Experts and takes the 1:1 calls himself.

He is a HighLevel Certified Admin with the second-most reviews in HighLevel's Certified Admin Directory worldwide, all of them 5 out of 5.

He won HighLevel's Top New Subaccounts via AI Employee award in its 2025 Summer of AI Awards and taught HighLevel's official masterclass on its AI Employee.

Before HighLevel, he co-owned a 60-employee financial services firm and sold his share.

On the call he looks at your account, not a script.

5/5 across 83 reviews in HighLevel's Certified Admin Directory