// SIMPLYBOOK API
Replacing the SimplyBook widget with your own booking page
The architecture that keeps your API keys safe, the calls that power the flow, and the details that decide whether people finish booking or give up.
- ● Credentials stay server-side
- ● No iframe
- ● Live example
Why replace the widget at all
SimplyBook’s embeddable widget is a reasonable starting point — it works, and it costs nothing to paste in. But once a booking page becomes a real part of how you win work, an iframe starts to cost you in ways that are hard to see on a screenshot.
- Branding. The widget looks like the widget. Your fonts, spacing, tone of voice and buttons stop at the iframe boundary, right at the moment a customer is deciding whether to trust you.
- Page speed. You are loading a third-party bundle, its styles and its own network round-trips inside your page. You have no control over what it pulls in or when.
- Cookies and consent. Third-party frames drag third-party storage into your consent story. If you have worked to keep your cookie banner honest and minimal, an embedded booking tool undoes some of that.
- Accessibility. You are responsible for how your site behaves with a keyboard and a screen reader, but you cannot fix markup that lives inside someone else’s frame.
- Conversion control. You cannot re-order steps, change wording, pre-select a service from the page the visitor arrived on, or run your own analytics on the drop-off points. An iframe is also at the mercy of the provider’s frame policy — if it declines to render, your booking page is simply blank.
Replacing it does not mean leaving SimplyBook. In our own setup, SimplyBook.me is the diary engine only. Customers never see it, and never know it is there. It keeps the calendar, the staff, the working hours and the notifications; the booking journey is ours.
The architecture that keeps it safe
The single most important rule: the browser never sees an API key. Everything goes through one small server-side proxy — in our case a PHP file, api/pcm-booking.php, on ordinary shared hosting. Credentials live in a server-only file outside the public repo. The front end talks only to the proxy, and the proxy decides what is allowed.
browser → /api/pcm-booking.php?action=... (rate-limited per IP, cached ~90s)
→ https://user-api.simplybook.me/ (tokens cached ~20 min server-side)
Read-only actions — the service list and availability — are public, because a booking page has to work before anyone identifies themselves. Anything that writes requires proof of identity first. We use our own passwordless emailed-code sign-in for that, because SimplyBook client accounts are self-registerable with any email address: a SimplyBook client login proves someone controls that booking account, nothing more.
Which calls power the flow
- Token. The public API token comes from
getToken(company, apiKey)posted as JSON-RPC tohttps://user-api.simplybook.me/login. The admin token comes fromgetUserToken(company, user, userKey); admin calls then go tohttps://user-api.simplybook.me/admin/withX-Company-LoginandX-User-Tokenheaders. Cache both server-side (about twenty minutes) so you are not fetching a token per page view. - Service list. Pull the services — names, durations and descriptions — from SimplyBook rather than hard-coding them in your HTML. This matters more than it sounds; see below.
- Availability.
getStartTimeMatrixreturns the bookable start times for a service over a date range. This is what you render as your slot picker. - Unit (staff) selection.
getAvailableUnitstells you who can actually take the chosen service at the chosen time. - The booking itself — made with the admin
bookcall, against a real client id.
Why the admin book call, with a real client id
If your account requires client authorisation, a booking attempted through the public path comes back with a client-authorisation error, because there is no logged-in SimplyBook client behind the request. Booking as admin with a client id you already hold sidesteps that entirely: you find or create the client server-side, then book on their behalf.
Creating that client is where most integrations stall. addClient can fail permanently with “Value is required and can’t be empty” even when every documented field is present. The live JSON-RPC error is code -32070, and its payload carries data.field naming the exact missing field as client_fields/<32-character hex id> — a required custom client field. Supplying client_fields: { "<32-hex id>": "value" } inside the client-data object makes the create succeed. Note that getCompanyParam('require_fields') only reports required built-in fields; it says nothing about custom ones. Many client libraries truncate error.data, which is why this looks unsolvable until you log the raw response.
Rate limiting and short caching, because it is not your API
Your public endpoints are a thin skin over a third party you do not control. Anyone can hit them, in a loop, from anywhere. We rate-limit per IP and cache the read-only responses for about ninety seconds — long enough that a burst of traffic or a bot costs one upstream call, short enough that a slot booked a minute ago disappears quickly. Cache the token separately and for longer; cache availability briefly and per service/date key.
The UX decisions that mattered
- Plain-English times. Show “2:30pm”, not “14:30”. Keep the 24-hour value in the data attribute; put the human one on the button.
- Descriptions from SimplyBook. Pull service names and descriptions from the API so the owner can edit them in one place without touching the site. It also stops the page and the diary drifting apart.
- The slot-taken race. Availability you fetched ninety seconds ago may be gone. Assume the booking can fail on submit: catch it, re-fetch the matrix, show the nearest alternatives with an honest message, and keep the customer’s details filled in.
- Never fail silently. A booking page that quietly does nothing is worse than one that says “something went wrong — please ring us on 01202 775566”. Log every failure server-side and make failures announce themselves somewhere a human looks. Silence is the one failure mode you will not notice.
- Watch for recurring services. A service configured as recurring returns the whole series from a single
book()call — the response’sbookingsarray contains every occurrence. Read the whole array. We booked one appointment and quietly created twelve, running out to November 2027, because we only looked atbookings[0].
Accessibility, briefly
Slots and services should be real <button> elements, reachable and operable by keyboard, with aria-pressed on the selected one. Resist the temptation to build fake tabs out of <div>s. Announce step changes, keep focus somewhere sensible after each step, and make sure error text is associated with the field it belongs to.
We built this for our own booking system in 2026, because the widget was not good enough for how we wanted our customers treated. Everything above is what it cost us to learn. If you are looking at the same problem, we are happy to talk it through — or to build it.
// GOOD QUESTIONS
Frequently asked
Can I call the SimplyBook API straight from the browser?
No — not safely. Anything in the browser is readable by anyone, so your API key would be public. Put a small server-side proxy in between: the browser talks only to your own domain, and the credentials never leave your server.
Why book through the admin method rather than the public one?
On accounts configured to require client authorisation, unauthenticated public booking is rejected outright. Resolving or creating the client first and booking with a real client id sidesteps that entirely.
Do I need to rate-limit my own booking page?
Yes, if the endpoints are public. Service lists and availability hit a third-party API you don’t control, so a scraper hammering them can burn the quota your real bookings depend on. Rate-limit per IP and cache briefly.
What breaks conversions most?
Silent failures and jargon. Show times as “2:30pm” rather than “14:30”, handle the slot-just-taken race gracefully, and never let an error end in a dead screen with no phone number on it.
Thinking about your own booking experience?
We built ours on SimplyBook and it is live on this site — have a look, then tell us what you are trying to do. Quoted per project, honestly, after a proper look.
01202 775566 · help@365techies.co.uk · MON–FRI 9AM–5PM