For developers and AI assistants

Bookr on your site and in your tools

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.

1 · Widget

Paste one line

Your live booking page inside your own site. No other code needed.

Embed guide →
2 · REST API

A key, thirteen scopes

Read the catalogue and free slots, or manage bookings, hours and customers from your own code.

Endpoints →
3 · Your AI / MCP

One address

Give your AI assistant mybookr.app/mcp and a key. It gets exactly the tools the key allows.

Connect your AI →
API keys and the MCP server are on every plan. The widget for your own website is Pro; every plan can link a “Book now” button to the Bookr page. Plans

Quick start

  1. Make a key. In the app: Business → Connect your AI. On the web: Developer settings. Name it after where it will live, tick what it may do and copy it. It is shown once.
  2. Check it works.
curl https://mybookr.app/api/v1/me \
  -H "Authorization: Bearer bk_live_…"
  1. Read something. Services, then the free slots for one of them on a date.
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.

What to tell your AI

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.
Only put a read-only key in a website. A key with read:customers, write:* or Full access belongs in a server, a tool, or an AI assistant on your own machine — never in page source.

Authentication

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.

Keep your key safe

A key is a password for your business. Whoever holds it can do everything its scopes allow, as you, until you revoke it.

Scopes

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.

ScopeLets a keyWhere it may live
read:catalogRead the business profile, services, hours, staff, locations, busy ranges, free slots and blocked time.Anywhere — this is already public on the booking page.
read:bookingsRead booked times, blocks and the walk-in queue — when, what, how long. No names, emails or phones.A site that shows availability.
read:customersNames, emails, phones, your private notes — on bookings, walk-ins and the client list.A server or a tool you trust. Never a website.
read:messagesMessage threads with customers.A server or a tool you trust. Never a website.
read:reviewsReviews, ratings and your replies.Anywhere.
read:insightsRevenue by period and the payout ledger.A server or a tool you trust. Never a website.
write:catalogCreate and change services, set hours, block time.A server or a tool.
write:bookingsCreate (unpaid), cancel, reschedule, no-show, arrived, undo; add and edit walk-ins.A server or a tool.
write:customersPrivate notes; block or unblock a customer.A server or a tool. Never a website.
write:messagesReply to a customer on a booking, as the business.A server or a tool. Never a website.
write:reviewsReply to a review.A server or a tool.
write:staffAdd, change or remove team members and their services.A server or a tool.
write:businessThe words and arrangement on the page; turn bookings on or off with a message.A server or a tool.

Plans

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.

Endpoints

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.

CallScopeWhat it does (* = required)
GET /meany keyWho am I
The key's name, scopes, business and plan. Use it to check a key works.
GET /businessread:catalogBusiness 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 /businesswrite:businessUpdate 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 /servicesread:catalogList services
Every service, active and inactive, with price in pence and duration in minutes.
active
POST /serviceswrite:catalogCreate 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:catalogGet a service
One service by id.
PATCH /services/{id}write:catalogUpdate a service
Change name, price, duration, description, buffer or active.
name · price_pence · duration_min · description · buffer_min · active
DELETE /services/{id}write:catalogDeactivate a service
Hides it from the booking page. Existing bookings keep it. Nothing is deleted — the same as the app.
GET /hoursread:catalogOpening hours
Seven rows, day_of_week 0 = Sunday. Times are HH:MM in the business timezone.
PUT /hourswrite:catalogSet 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 /staffread:catalogList staff
Team members who can be booked. Pass staff_id to slots and bookings.create to book one of them.
POST /staffwrite:staffAdd 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 /locationsread:catalogList locations
Branches, for multi-location businesses.
GET /availabilityread:catalogBusy ranges
BUSY time ranges from now for `days` days (bookings, blocks, time off, holiday, horizon). For free times use slots.
days · staff_id
GET /slotsread:catalogFree 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 /bookingsread:bookingsList bookings
Bookings in a window (default: from now, 30 days). Customer details need read:customers.
from · to · status · limit
POST /bookingswrite:bookingsCreate 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:bookingsGet a booking
One booking by id.
POST /bookings/{id}/cancelwrite:bookingsCancel a booking
Cancels as the business. A paid booking is refunded by Bookr's normal rules; the customer is told.
reason
POST /bookings/{id}/reschedulewrite:bookingsReschedule 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-showwrite:bookingsMark no-show
The customer did not turn up. Applies the business's no-show fee rule if one is set.
POST /bookings/{id}/arrivedwrite:bookingsMark arrived
Check the customer in (or undo with arrived=false).
arrived
POST /bookings/{id}/undowrite:bookingsUndo completed / no-show
Puts a completed or no-show booking back to confirmed.
GET /blocksread:bookingsList time blocks
Owner-blocked time (lunch, admin, days off) from now.
days
POST /blockswrite:catalogBlock time
Make a range unbookable.
start_at* · end_at* · reason
PATCH /blocks/{id}write:catalogChange a block
Move or rename a time block.
start_at* · end_at* · reason
DELETE /blocks/{id}write:catalogRemove a block
The time becomes bookable again.
GET /customersread:customersList 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:customersGet a customer
One customer with the owner's private notes and their bookings at this business.
PATCH /customers/{id}write:customersUpdate a customer
Set the owner's private notes, or block / unblock them from booking.
notes · blocked
GET /walkinsread:bookingsWalk-in queue
Who is waiting right now (walk-in businesses). Names need read:customers.
POST /walkinswrite:bookingsAdd 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:bookingsEdit a walk-in
Correct the name or phone of someone in the queue.
name* · phone
GET /messagesread:messagesList 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 /messageswrite:messagesSend 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 /reviewsread:reviewsList 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}/replywrite:reviewsReply 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:staffChange a team member
Name, role, active flag, and which services they offer.
name · role · active · service_ids
DELETE /staff/{id}write:staffRemove a team member
Removes them from the page and the rota. Their past bookings keep their name.
GET /insightsread:insightsEarnings 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/availabilitywrite:businessTurn 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

Slots, and handing the customer to Bookr

/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.

Connect your AI (MCP)

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 Code

claude mcp add --transport http bookr https://mybookr.app/mcp \
  --header "Authorization: Bearer bk_live_…"

Cursor, and other clients that take a URL + headers

{
  "mcpServers": {
    "bookr": {
      "url": "https://mybookr.app/mcp",
      "headers": { "Authorization": "Bearer bk_live_…" }
    }
  }
}

Claude Desktop (via mcp-remote)

{
  "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.

Errors and limits

StatusMeaning
400A parameter is missing or malformed. The message names it.
401No key, an unknown key, or a revoked key.
402The business’s plan has no API access (no current plan).
403The key lacks the scope (named in the response), or the record is not this business's.
404No such record, or no such endpoint.
409The slot is taken, blocked, or the staff member is booked.
422A business rule refused it — the message is written for a person and safe to show.
429Too 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.

What a key can never do

Terms

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.

Get a key   Ask us something