Paste one line to put the booking flow on your site, call the REST API with keys you scope yourself, or give your AI assistant an MCP address to manage the business. All three use the same bookings, calendar and payouts as the app.
Get a key See it on a real site ↗
The demo is a barbershop's own website: services and the next free times come through a read-only key, the booking flow is the embed, and tapping a time opens Bookr at that exact slot. The site is a starter kit you can copy.
Your live booking page inside your own site. No other code needed.
Embed guide →Read the catalogue and free slots, or manage bookings, hours and customers from your own code.
Endpoints →Give your AI assistant mybookr.app/mcp and a key. It gets exactly the tools the key allows.
curl https://mybookr.app/api/v1/me \
-H "Authorization: Bearer bk_live_…"
curl "https://mybookr.app/api/v1/services" -H "Authorization: Bearer bk_live_…"
curl "https://mybookr.app/api/v1/slots?service_id=SERVICE-ID&date=2026-10-06" \
-H "Authorization: Bearer bk_live_…"
Everything is JSON. Times are ISO 8601, prices are pence, ids are UUIDs. The full contract is openapi.json; a plain-text version for assistants is llms-full.txt.
If an AI is building your site, paste this. It tells the assistant what to use and the one rule that matters.
I run [business name] and my Bookr handle is [handle]. Add a Book page to my website using Bookr.
Read https://mybookr.app/llms-full.txt first. In short:
- For the customer-facing booking, use Bookr's hosted embed (one <script> tag, instructions under
"Embedding Bookr on your own website" in https://mybookr.app/llms.txt). Do not build your own
checkout — the pay-and-confirm step stays inside Bookr's frame.
- You MAY build my own slot picker around it: list services and free times from the REST API
(https://mybookr.app/api/v1, key below, read:catalog scope), then hand the chosen time to Bookr with
window.Bookr.open({ service, start }). If the slot is free the customer lands on the details step.
- Match my site's fonts, colours and layout. The widget accepts data-accent and data-theme.
- Fire a thank-you from the bookr:booked event.
API key (read-only, safe for a site): bk_live_…
My site's domain is registered in Bookr, so the embed will render there.
read:customers, write:* or Full access belongs in a server, a tool, or an AI assistant on your own machine — never in page source.Send the key as a Bearer token on every request. Keys start with bk_live_. Bookr stores only a SHA-256 fingerprint, so a key cannot be shown twice; revoke and replace if lost. Unknown and revoked keys get the same 401.
Authorization: Bearer bk_live_…
Base URL: https://mybookr.app/api/v1. One key belongs to one business; there is no cross-business access of any kind.
A key is a password for your business. Whoever holds it can do everything its scopes allow, as you, until you revoke it.
read:catalog and read:bookings may live in a website’s source; anything with customer details or a write scope must stay server-side or inside your own tools.401 from the next call. Then make a new one. Every call a key makes is listed under Activity on /developer, so you can see what happened.Chosen when the key is made; enforced on every call. A key without the scope for something gets a 403 that names the scope it needs.
| Scope | Lets a key | Where it may live |
|---|---|---|
| read:catalog | Read the business profile, services, hours, staff, locations, busy ranges, free slots and blocked time. | Anywhere — this is already public on the booking page. |
| read:bookings | Read booked times, blocks and the walk-in queue — when, what, how long. No names, emails or phones. | A site that shows availability. |
| read:customers | Names, emails, phones, your private notes — on bookings, walk-ins and the client list. | A server or a tool you trust. Never a website. |
| read:messages | Message threads with customers. | A server or a tool you trust. Never a website. |
| read:reviews | Reviews, ratings and your replies. | Anywhere. |
| read:insights | Revenue by period and the payout ledger. | A server or a tool you trust. Never a website. |
| write:catalog | Create and change services, set hours, block time. | A server or a tool. |
| write:bookings | Create (unpaid), cancel, reschedule, no-show, arrived, undo; add and edit walk-ins. | A server or a tool. |
| write:customers | Private notes; block or unblock a customer. | A server or a tool. Never a website. |
| write:messages | Reply to a customer on a booking, as the business. | A server or a tool. Never a website. |
| write:reviews | Reply to a review. | A server or a tool. |
| write:staff | Add, change or remove team members and their services. | A server or a tool. |
| write:business | The words and arrangement on the page; turn bookings on or off with a message. | A server or a tool. |
API keys and the MCP server are on every plan. The embed, and the embed without the “Powered by Bookr” line, are part of Bookr Pro. A 402 means the business’s plan has no API access — no current plan does that.
Generated from openapi.json, which is generated from the code that runs — the three cannot disagree. Path parameters are UUIDs; GET options go in the query string, everything else takes a JSON body.
| Call | Scope | What it does (* = required) |
|---|---|---|
GET /me | any key | Who am I The key's name, scopes, business and plan. Use it to check a key works. |
GET /business | read:catalog | Business profile Public profile, booking rules (notice, horizon, cancellation window), timezone and format. works_at says where the business works: premises (address and map shown to customers), mobile (customers see the town only and give THEIR address when booking) or both. address/postcode are the owner's own record and are never shown to customers for a mobile business. |
PATCH /business | write:business | Update the page The words and arrangement on the booking page: description (about), announcement, arrival_instructions, confirmation_note, faqs, amenities (badge keys), page_layout, social_links, service_area. Plan gates apply on the page as they do in the app. Nothing here touches money, hours or the address. description · announcement · arrival_instructions · confirmation_note · faqs · amenities · page_layout · social_links · service_area |
GET /services | read:catalog | List services Every service, active and inactive, with price in pence and duration in minutes. active |
POST /services | write:catalog | Create a service Add a bookable service. Price is in pence; duration in minutes (5–480). Plan service limits apply. name* · price_pence* · duration_min* · description · buffer_min · active |
GET /services/{id} | read:catalog | Get a service One service by id. |
PATCH /services/{id} | write:catalog | Update a service Change name, price, duration, description, buffer or active. name · price_pence · duration_min · description · buffer_min · active |
DELETE /services/{id} | write:catalog | Deactivate a service Hides it from the booking page. Existing bookings keep it. Nothing is deleted — the same as the app. |
GET /hours | read:catalog | Opening hours Seven rows, day_of_week 0 = Sunday. Times are HH:MM in the business timezone. |
PUT /hours | write:catalog | Set opening hours Upsert any subset of days. Each item: day_of_week (0–6, 0 = Sunday), is_open, open_time, close_time (HH:MM). hours* |
GET /staff | read:catalog | List staff Team members who can be booked. Pass staff_id to slots and bookings.create to book one of them. |
POST /staff | write:staff | Add a team member Creates a staff member customers can pick. Plan staff caps are enforced by the database (409 when full). Optionally assign services. name* · role · service_ids |
GET /locations | read:catalog | List locations Branches, for multi-location businesses. |
GET /availability | read:catalog | Busy ranges BUSY time ranges from now for `days` days (bookings, blocks, time off, holiday, horizon). For free times use slots. days · staff_id |
GET /slots | read:catalog | Free slots for a day Free start times for a service on one date, computed with the booking page's own rules (hours, duration, notice, horizon, busy ranges). `starts_at` are the same times as ISO instants — pass one to bookings.create, or open the booking frame at it with Bookr.open({service, start}). service_id* · date* · staff_id |
GET /bookings | read:bookings | List bookings Bookings in a window (default: from now, 30 days). Customer details need read:customers. from · to · status · limit |
POST /bookings | write:bookings | Create a booking (unpaid) Adds a confirmed booking the way the owner does by hand in the app: no card is taken. 409 when the business is at capacity for that time (an appointment business's capacity is its number of active staff), the named staff member is already booked, or the time is blocked. end_at defaults to start_at + service duration; total_pence to the service price. service_id* · start_at* · customer_address · end_at · customer_name · customer_email · customer_phone · notes · staff_id · total_pence · party_size |
GET /bookings/{id} | read:bookings | Get a booking One booking by id. |
POST /bookings/{id}/cancel | write:bookings | Cancel a booking Cancels as the business. A paid booking is refunded by Bookr's normal rules; the customer is told. reason |
POST /bookings/{id}/reschedule | write:bookings | Reschedule a booking Move it to a new start (end defaults to keep the same length). The new slot must be free. start_at* · end_at |
POST /bookings/{id}/no-show | write:bookings | Mark no-show The customer did not turn up. Applies the business's no-show fee rule if one is set. |
POST /bookings/{id}/arrived | write:bookings | Mark arrived Check the customer in (or undo with arrived=false). arrived |
POST /bookings/{id}/undo | write:bookings | Undo completed / no-show Puts a completed or no-show booking back to confirmed. |
GET /blocks | read:bookings | List time blocks Owner-blocked time (lunch, admin, days off) from now. days |
POST /blocks | write:catalog | Block time Make a range unbookable. start_at* · end_at* · reason |
PATCH /blocks/{id} | write:catalog | Change a block Move or rename a time block. start_at* · end_at* · reason |
DELETE /blocks/{id} | write:catalog | Remove a block The time becomes bookable again. |
GET /customers | read:customers | List customers Everyone who has booked here or is on the client list: visit counts, first and last visit, lifetime spend, blocked flag, private notes. Optional q filters by name, email or phone. q · limit |
GET /customers/{id} | read:customers | Get a customer One customer with the owner's private notes and their bookings at this business. |
PATCH /customers/{id} | write:customers | Update a customer Set the owner's private notes, or block / unblock them from booking. notes · blocked |
GET /walkins | read:bookings | Walk-in queue Who is waiting right now (walk-in businesses). Names need read:customers. |
POST /walkins | write:bookings | Add to the walk-in queue Join someone to the queue at the counter. customer_name* · customer_phone · customer_email · service_id |
PATCH /walkins/{id} | write:bookings | Edit a walk-in Correct the name or phone of someone in the queue. name* · phone |
GET /messages | read:messages | List messages The business's message threads with customers, newest first: every message carries its booking id, who sent it (business or customer) and when. Filter by booking_id for one thread. booking_id · limit |
POST /messages | write:messages | Send a message Replies to a customer on one booking, as the business. Bookr delivers it (email and, where enabled, push) and applies the daily cap the app has. booking_id* · body* |
GET /reviews | read:reviews | List reviews Every review of the business with its rating, text, the owner's reply and dates. Hidden reviews are included with hidden_at set. limit |
POST /reviews/{id}/reply | write:reviews | Reply to a review Sets or replaces the owner's public reply on a review. Shown on the booking page under the review. reply* |
PATCH /staff/{id} | write:staff | Change a team member Name, role, active flag, and which services they offer. name · role · active · service_ids |
DELETE /staff/{id} | write:staff | Remove a team member Removes them from the page and the rota. Their past bookings keep their name. |
GET /insights | read:insights | Earnings summary Revenue for a period from completed and confirmed bookings (pence), booking counts by status, and the payout ledger totals: paid out, and held/still to come. from · to |
POST /business/availability | write:business | Turn bookings on or off The same switch as the app's "Taking bookings". taking_bookings=false stops every booking path (waitlists stay open). Give a message customers will read and, optionally, back_on (ISO date) so it resumes by itself. taking_bookings=true clears both. taking_bookings* · message · back_on |
/availability returns busy ranges (bookings at capacity, blocks, time off, holiday, the booking horizon). /slots does the arithmetic for you with the booking page's own rules — hours, duration, notice period, horizon, busy ranges — and returns free start times for one service on one date, as HH:MM in the business timezone and as ISO instants.
When the customer picks one, hand it to Bookr. The booking page (and the embed) accept start beside service: if that slot is still free the customer lands on the details step and pays inside Bookr; if it was just taken, they see the calendar as normal. The database is the final arbiter, so a stale slot can never double-book.
// on your site, with the embed script on the page
window.Bookr.open({ service: 'SERVICE-ID', start: '2026-10-06T08:00:00Z' });
// or as a link
https://mybookr.app/HANDLE?service=SERVICE-ID&start=2026-10-06T08:00:00Z
See it working: bookr-demo-site.vercel.app — the “Next free times” chips are /slots, and each one calls Bookr.open({ service, start }).
Need a booking that is not paid by card — a regular, a phone booking, a walk-up? POST /bookings creates a confirmed, unpaid booking the way the owner does by hand in the app. It refuses with 409 when the business is at capacity for that time, the named staff member is already booked, or the time is blocked.
Bookr runs an MCP server at https://mybookr.app/mcp — Streamable HTTP, stateless, authenticated with the same key. Your AI sees only the tools the key's scopes allow, so a read-only key gives a read-only assistant.
claude mcp add --transport http bookr https://mybookr.app/mcp \
--header "Authorization: Bearer bk_live_…"
{
"mcpServers": {
"bookr": {
"url": "https://mybookr.app/mcp",
"headers": { "Authorization": "Bearer bk_live_…" }
}
}
}
{
"mcpServers": {
"bookr": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://mybookr.app/mcp", "--header", "Authorization: Bearer bk_live_…"]
}
}
}
Then ask, in your own words: “What's free on Tuesday afternoon?” · “Block Friday 1–2 for lunch every week” · “Who hasn't been in for three months?” · “Move Leah's 3pm to 4pm and tell her.” Tool names match the endpoints (slots_list, bookings_cancel…). The server also exposes the OpenAPI document as a resource.
| Status | Meaning |
|---|---|
400 | A parameter is missing or malformed. The message names it. |
401 | No key, an unknown key, or a revoked key. |
402 | The business’s plan has no API access (no current plan). |
403 | The key lacks the scope (named in the response), or the record is not this business's. |
404 | No such record, or no such endpoint. |
409 | The slot is taken, blocked, or the staff member is booked. |
422 | A business rule refused it — the message is written for a person and safe to show. |
429 | Too many requests: 120 a minute per IP before authentication, 600 a minute per key after. |
Every call a key makes — reads, refusals and 402s included — is listed under the key in Developer settings. A key doing things you do not recognise is a key to revoke; revocation is immediate and cannot be undone.
Use of the API, the MCP server and the embed is covered by the API terms, in addition to the business terms. In one line: your key is yours to protect, customer data you read through read:customers is yours to look after under UK GDPR, and we may rate-limit or revoke a key that harms the service.