Your public booking page
A page anyone can open to book with you: browse times without signing in, confirm a mobile number with a texted code, and book. It follows the same rules as your AI agent.
Turning it on
Your company needs an sms channel (the number codes are texted from). Then choose the page's address and switch it on:
PUT /api/v1/company
{ "public_slug": "peak-heating", "public_booking_enabled": true }
The slug is 3 to 60 lowercase letters, digits and hyphens, and must be unique. The response's public_booking_url is the page's address (it needs BOOKING_APP_URL set on Booker). public_booking_enabled: false takes the page down at once; the link then shows "not found". Changing the slug frees the old one immediately: links with the old slug stop working, and another company could claim it. On a self-hosted Booker, the host also needs a TURNSTILE_SECRET_KEY (a Cloudflare Turnstile secret): without one the page's endpoints answer 503. Local setup fills in Cloudflare's test secret; production needs a real one, and Booker refuses to start in production with a test secret.
Which appointment types appear
Only active, open types you mark with "public_booking": true (PUT /api/v1/appointment-types/:id). by_request types can't be public; changing a type to by_request takes it off the page. A customer who verifies also sees their own open scheduling requests and can book those.
When a type is matched to locations by address, the page asks for the visitor's address before showing times. An address typed to browse times before verifying is used for that search only and is not stored. Once a customer has verified, the address you have on file is used if there is one. Registering, or booking a type matched by address when there is no address on file, saves the address the visitor gives (geocoded, and marked as given on the public page); for other types an address sent with a booking is ignored.
Public slot search answers with providers, each carrying only providerId, providerName, locationId, locationName, timezone and slots, plus an in_area flag.
Verification
Booking needs a mobile number in the US or Canada, confirmed with a 6-digit code texted from your number. A Cloudflare Turnstile check runs before any code is sent. The page never reveals whether a number belongs to one of your customers. A known customer books straight away; a new number registers first when your new_customers setting is allowed, and is asked to call you otherwise. When registering, an email that already belongs to another of your customers isn't saved, and the answer carries a warning saying so (as when your agent creates a customer).
If the carrier reports that a number has opted out of your texts (Twilio error 21610), Booker records that as your company's SMS opt-out for the number, since codes are sent from your own number.
Limits
- 3 codes an hour and 10 a day per number; 10 an hour per network address.
- Your company's daily total,
public_daily_code_cap(default 200, up to 10,000; 0 stops all codes). - A code lasts 10 minutes and allows 5 tries; a verified visit lasts 30 minutes.
- Address searches (which are geocoded) are limited to 10 a minute per network address and 500 a day per company. A search counts against the company's day only while its network address is under its own limit.
- 60 requests a minute per network address across public pages, and 30 registrations and bookings an hour per verified visit (searches don't count).
- Searches from visitors who haven't verified share a budget of 120 a minute per company; a verified visit's searches don't count against it.
- A request body is at most 16 KB (413 over that).
- An IPv6 visitor's network address is counted as its /64 block, since one connection can usually use any address in it.
The per-address limits depend on Booker seeing each visitor's real address. Behind a proxy or load balancer, set TRUST_PROXY to the number of proxies in front of Booker (a hop count such as 1), not true: true trusts every hop and lets a visitor forge their address, so Booker refuses to start in production with it.
Texts and consent
Confirming a phone number is not consent to texts. Only the page's "Text me updates" checkbox, unticked by default, records SMS consent (source public_page), on the number the visitor verified (not necessarily the customer's primary phone), which you can see under a customer's consent history. Bookings from the page show booked_by: "public".
Reference
The page's endpoints are under Public booking in the API reference. They take no API key and are called only from the booking page itself.