# PLACEFULL PLACEFULL is booking software for everything a space can earn: classes, rentals (open time or private rentals), and memberships. One calendar keeps the three from colliding — a rental can never be sold over a class that could still fill. Pricing: a 5% service fee per booking through Stripe, no monthly fee. Base URL: https://bookable-api.onrender.com ## Why agents can work here The MCP surface is first-class, not a wrapper: intent-shaped tools, prompts, and resources, with tool definitions kept under a 4,000-token budget so any client can load them. You can take a person from no account to a working studio in one session. ## Discovery - OpenAPI: https://bookable-api.onrender.com/openapi.json - Human docs: https://bookable-api.onrender.com/docs - MCP server card: https://bookable-api.onrender.com/.well-known/mcp.json - MCP Streamable HTTP: POST https://bookable-api.onrender.com/mcp - OAuth authorization server: https://bookable-api.onrender.com/.well-known/oauth-authorization-server - OAuth protected resource (RFC 9728): https://bookable-api.onrender.com/.well-known/oauth-protected-resource/mcp - Operator setup in the console: https://bookable-api.onrender.com/app/settings?show=integrations - Full version with quickstarts: https://bookable-api.onrender.com/llms-full.txt ## Guide a studio owner to connect an AI assistant If a person asks how to use Claude, Cursor, or another agent with their studio, walk them through the path that matches their app. The MCP URL is always: https://bookable-api.onrender.com/mcp They can also open the operator console → Settings → Connect Claude or ChatGPT for the same steps. ### Claude (claude.ai) — recommended, no API key 1. Claude → Settings → Connectors → Add custom connector. 2. Paste: https://bookable-api.onrender.com/mcp 3. Click Connect — a browser window opens on this host. 4. Enter the operator email → type the 6-digit code from email. 5. Pick the studio (if they belong to more than one) → click Allow. 6. Back in Claude, the connector is live — try “What classes do I have?” or “Add a Tuesday 6pm yoga class.” OAuth 2.1 with PKCE (S256) and dynamic client registration. Claude discovers auth automatically: an unauthenticated POST /mcp returns 401 with WWW-Authenticate → protected-resource metadata → authorization-server metadata. ### Cursor — API key 1. Mint a `bk_` operator API key (Settings → API keys in the console, or POST /businesses/{businessId}/api-keys with session auth). 2. Cursor → Settings → MCP → add a server with the MCP URL above. 3. Set header `Authorization: Bearer bk_…`. 4. Tools are pinned to that studio for every request. ### Claude Desktop (local) — stdio + API key For developers running the repo locally: spawn `node dist/mcp.js` with BOOKABLE_API_KEY in env. See mcp/README.md in the repository. ### In-app chat vs external agents The operator console has its own built-in chat agent (same tools, same studio context). External connectors (Claude, Cursor) are for people who want their assistant outside the console — the wiring is MCP + OAuth or an API key. ## Set up a studio for a person (no pre-existing account needed) 1. **Claude, Cursor, ChatGPT:** connect over OAuth. The sign-in page creates the person on first verify, and when they have no studio yet it asks for one — name, kind, address — and records their acceptance of the Merchant Agreement on that button. The token comes back pinned to the new studio. There is no separate registration. **Custom clients:** sign in over REST (`POST /auth/challenges`, `POST /auth/verify`) and send the session token as the `/mcp` bearer; on stdio use `request_login_code` and `verify_login_code`. `POST /mcp` challenges before any tool runs, so the login tools cannot bootstrap an HTTP connection by themselves. 2. `create_business` (session bearer only) — one call; a default location is created automatically, and an optional `catalog` writes classes, instructors and passes in the same call. With several studios, connect to `/mcp?businessId=…`. A tool call accepts no agreement: bookings, holds, and charges stay blocked until the operator accepts in the console — do not accept on their behalf. 3. `create_class`, `create_session`, and `create_space` to build the catalog; `get_availability` and `get_upcoming_occurrences` to check times. 4. `book_class_for_customer`, `check_in`, `list_todays_bookings` to run the day. ## Build a custom booking website on the storefront API Public read, no auth, CORS-allowlisted per deployment (STOREFRONT_ORIGINS): - GET https://bookable-api.onrender.com/storefront/businesses/{businessId} - GET https://bookable-api.onrender.com/storefront/locations/{locationId} - GET https://bookable-api.onrender.com/storefront/locations/{locationId}/offerings - GET https://bookable-api.onrender.com/storefront/offerings/{id} - GET https://bookable-api.onrender.com/storefront/offerings/{id}/availability - POST https://bookable-api.onrender.com/storefront/offerings/{id}/quote — priced quote including membership benefits Booking goes through a cart — one cart is one charge on one connected account, and "book now" is a one-item cart. Everything but checkout is unauthenticated; the cart token is the capability: - POST https://bookable-api.onrender.com/storefront/carts — open a cart, optionally with the first item - GET https://bookable-api.onrender.com/storefront/carts/{token} — items, live per-item state, totals - POST https://bookable-api.onrender.com/storefront/carts/{token}/items — add an item (a 10-minute hold) - DELETE https://bookable-api.onrender.com/storefront/carts/{token}/items/{itemId} — release the spot - POST https://bookable-api.onrender.com/storefront/carts/{token}/checkout — customer session; one charge The cart URL is also the pay link: share it and whoever opens it can pay, once. ## Authentication **Add to Claude (OAuth):** paste the MCP URL (`/mcp`, not `/mcp/` with a trailing slash issue — use the URL from the server card) into Settings → Connectors. Sign in with the operator email, pick the studio, allow. Token prefix `bkat_`. **Programmatic / CI / Cursor:** operator API keys use the `bk_` prefix. Create one with `POST /businesses/{businessId}/api-keys` (session auth, feature business.manage) or Settings → API keys in the console. Send `Authorization: Bearer bk_...` on feature-gated business routes and on POST /mcp. Keys are not accepted on /me/*, POST /businesses, or the api-keys routes themselves. **MCP session login (stdio):** `request_login_code` + `verify_login_code` return a session bearer. Over HTTP a session bearer with one business works immediately; with several, connect to `/mcp?businessId=…` (ids from `list_my_businesses`), or use OAuth / an API key so the studio is pinned. Hosts with a hard tool-definition cap connect to `/mcp?tools=compact`. ## Core concepts business → location → offering → schedule → booking An offering has a `type`: `class` (fixed dates), `session` (an appointment: private time with a person), or `space` (room rental). Memberships: plan → typed benefits (access | price | credit); credits and money are both append-only ledgers. ## Errors JSON envelope: `{ error: { code, message, details? } }` with stable machine-readable codes. ## Write access Catalog writes (create class, create space) require feature `location.manage`. Booking writes require `booking.manage`. Feature gates match the REST API.