# PlaceFull API

PlaceFull is a booking platform for studios and service businesses. Use the REST API to manage catalog, availability, bookings, payments, memberships, and customer records — or embed the public **storefront** surface for self-serve booking.

All successful responses use a `{ "data": … }` envelope. Money amounts are **integer minor units** (cents). Timestamps are **ISO-8601** strings in UTC.

## Base URLs

| Environment | URL |
| --- | --- |
| **Production** | `https://placefull.ai` |
| **Local** | `http://localhost:3000` |

Use the **Production** or **Local** server selector above when trying requests in this reference.

## Authentication

PlaceFull accepts two credential types:

1. **Session bearer** — passwordless login for operators and customers.
2. **API key** — machine access for integrations and MCP (`bk_…` prefix).

### Passwordless session

**Step 1 — request a verification code**

```bash
curl -sS -X POST https://placefull.ai/auth/challenges \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","channel":"email_code"}'
```

Response `data.challengeId` identifies the challenge. The code is delivered by email (or SMS when enabled).

**Step 2 — verify and receive a session token**

```bash
curl -sS -X POST https://placefull.ai/auth/verify \
  -H 'Content-Type: application/json' \
  -d '{"challengeId":"<challenge-id>","code":"123456"}'
```

**Step 3 — send the token on authenticated requests**

```bash
curl -sS https://placefull.ai/me/profile \
  -H 'Authorization: Bearer <sessionToken>'
```

Session tokens expire. Repeat the flow when you receive `401 unauthorized`.

### API key

Create a key with `POST /businesses/{businessId}/api-keys` (session auth, `business.manage`). The plaintext `bk_` key is returned once. Send it as a Bearer token on feature-gated `/businesses/*` routes:

```bash
curl -sS https://placefull.ai/businesses/<business-id>/customers \
  -H 'Authorization: Bearer bk_your_api_key_here'
```

That example needs feature `crm.view`. API keys are not accepted on `/me/*`, `POST /businesses`, or the api-keys routes themselves — a key cannot mint its own successor. Gated operator routes also require the **feature** named in each operation's description (for example `booking.manage`).

### Agents

Point an agent host at this base URL.

| What | URL |
| --- | --- |
| **MCP (Streamable HTTP)** | `POST https://placefull.ai/mcp` |
| **Server card** | `https://placefull.ai/.well-known/mcp.json` |
| **Agent guide** | `https://placefull.ai/llms.txt` |
| **OAuth metadata** | `https://placefull.ai/.well-known/oauth-authorization-server` |
| **Operator setup (console)** | `https://placefull.ai/app/settings?show=integrations` |

**Claude (recommended):** paste `https://placefull.ai/mcp` into Settings → Connectors → Add custom connector → Connect → sign in with the operator email. OAuth 2.1 + PKCE — no API key.

**Cursor / CI:** create a `bk_` API key and send `Authorization: Bearer bk_…` on `POST /mcp`.

Unauthenticated `POST /mcp` returns `401` with `WWW-Authenticate` pointing at protected-resource metadata so clients discover OAuth automatically.

## API surfaces

| Surface | Prefix | Audience |
| --- | --- | --- |
| **Operator API** | `/businesses/…`, `/offerings/…`, `/locations/…`, … | Operators and integrations managing a business |
| **Storefront API** | `/storefront/…` | Public embeddable booking widgets |
| **Customer self-service** | `/me/…` | Signed-in customers managing their profile and bookings |

Storefront routes are **public read** (no auth) except booking hold and confirm, which require a customer session. Storefront routes are **rate limited** — see below.

## Errors

Errors return a **non-2xx** status with this envelope:

```json
{
  "error": {
    "code": "validation",
    "message": "email is required",
    "details": {}
  }
}
```

| Code | HTTP | Meaning |
| --- | --- | --- |
| `validation` | 400 | Invalid input |
| `unauthorized` | 401 | Missing or invalid credentials |
| `forbidden` | 403 | Authenticated but not permitted (missing feature or role) |
| `not_found` | 404 | Resource does not exist |
| `conflict` | 409 | State conflict (capacity, duplicate, or concurrent hold lost) |
| `too_many_requests` | 429 | Rate limit exceeded |
| `internal_error` | 500 | Unexpected server error |

## Rate limits

**Storefront** routes (`/storefront/…`) are limited to **480 requests per minute per visitor** by default (`STOREFRONT_RATE_LIMIT_MAX` / `STOREFRONT_RATE_LIMIT_WINDOW_MS`). The visitor is the `cf-connecting-ip` header when it is a single IP, otherwise the connection address. Cart and other unauthenticated storefront writes have a separate limit of **60 per minute** (`STOREFRONT_WRITE_RATE_LIMIT_MAX`). When exceeded, the API returns **429** `too_many_requests` with a `Retry-After` header (seconds until the window resets). Operator routes are not globally rate limited in v1.

## Pagination

**Offset pagination** — CRM customer list (`GET /businesses/:id/customers`):

- Query: `limit` (default 50), `offset` (default 0)
- Response `data`: `{ customers, total, limit, offset }`

**Cursor pagination** — storefront offering lists (`GET /storefront/locations/:id/offerings`), the Products list (`GET /businesses/:id/products`), and one option's stock ledger (`GET /products/:productId/variants/:variantId/stock`):

- Query: `limit`, `cursor` (opaque; omit on first page)
- Response `data`: `{ items, nextCursor }` — pass `nextCursor` as `cursor` for the next page; `null` means end.

## Versioning

`info.version` tracks the REST contract. **Breaking** changes (removed fields, renamed paths, semantic changes) bump the major version. Additive changes (new optional fields, new endpoints) are minor. The MCP surface is versioned separately via tool schemas.

Download this spec from [`/openapi.json`](https://placefull.ai/openapi.json) to generate clients or import into Postman.

## Endpoints

Every operation, grouped as the interactive reference groups them. Exact request and response schemas, examples and the required feature for each gated operation are in the OpenAPI document: https://placefull.ai/openapi.json. Interactive reference with "try it": https://placefull.ai/docs.

### Platform

#### system — Process health and platform status

- `GET /app-config` — Public client configuration
- `GET /health` — Health check
- `GET /health/worker` — Worker health check
- `GET /platform/memberships/report` — The daily membership report, as facts
- `POST /platform/memberships/report/send` — Send a day’s membership report again
- `GET /platform/overview` — Every live location, and who is waiting to join
- `GET /platform/legacy-mirrors` — Legacy mirrors
- `POST /platform/legacy-mirrors` — Start a legacy mirror
- `POST /platform/legacy-mirrors/{mirrorId}/run` — Run a legacy mirror now
- `POST /platform/legacy-mirrors/{mirrorId}/stop` — Stop a legacy mirror
- `POST /platform/legacy-mirrors/{mirrorId}/start` — Start a stopped legacy mirror
- `POST /platform/legacy-mirrors/{mirrorId}/cutover` — Cut a legacy mirror over to live
- `POST /platform/legacy-mirrors/{mirrorId}/preview` — A short link to a mirror’s shadow page
- `GET /platform/calls` — Calls to the support line
- `GET /platform/calls/{callId}` — One call, with its transcript
- `GET /platform/calls/{callId}/recording` — A call’s recording
- `GET /platform/threads` — Texts to the support line, one conversation per number
- `GET /platform/threads/{threadId}` — One text conversation, with its messages
- `POST /platform/threads/{threadId}/take` — Take a text conversation
- `POST /platform/threads/{threadId}/messages` — Reply in a text conversation
- `POST /platform/threads/{threadId}/complete` — Complete a text conversation
- `POST /platform/threads/{threadId}/assign` — Put an unknown number with a location
- `POST /platform/threads/{threadId}/draft` — Draft a reply
- `GET /platform/texts/{textId}` — The conversation a text belongs to
- `GET /platform/texts/{textId}/media/{index}` — One photo from a text
- `GET /platform/feedback` — How customers rated booking online, every studio
- `POST /places/autocomplete` — Autocomplete an address
- `POST /places/details` — Resolve a place to an address and coordinates
- `POST /places/resolve` — Qualify a free-text address
- `POST /waitlist` — Join the coming-soon waitlist

#### auth — Passwordless authentication

- `POST /auth/challenges` — Request a passwordless verification challenge
- `POST /auth/verify` — Verify a challenge and receive a session token
- `GET /auth/verify` — Open a magic link: a page that posts it back to verify
- `GET /auth/me` — Get the authenticated person (auth namespace)
- `POST /auth/sign-out` — Revoke the current session
- `POST /auth/sign-out-all` — Revoke every session the signed-in person holds

#### person — Person identities

- `GET /persons/{id}` — Get a person
- `PATCH /persons/{id}` — Update a person

#### access — Team roles and feature gates

- `GET /businesses/{businessId}/team` — List team members (feature `team.view`)
- `GET /businesses/{businessId}/team/me` — The caller’s own team row (feature `location.view`)
- `POST /businesses/{businessId}/team` — Add a team member (feature `team.manage`)
- `GET /businesses/{businessId}/user-roles` — List user roles for a business (feature `team.view`)
- `POST /businesses/{businessId}/user-roles` — Grant a user role (feature `team.manage`)
- `GET /businesses/{businessId}/features` — List enabled business features (feature `business.view`)
- `PUT /businesses/{businessId}/features` — Set enabled business features (feature `business.manage`)
- `PATCH /user-roles/{id}` — Update a user role (feature `team.manage`)
- `POST /user-roles/{id}/invite` — Email a team member their invite again (feature `team.manage`)
- `POST /user-roles/{id}/archive` — Archive a user role (feature `team.manage`)
- `GET /businesses/{businessId}/terminals` — List terminals (feature `team.manage`)
- `POST /businesses/{businessId}/terminals` — Add a terminal (feature `team.manage`)
- `PATCH /businesses/{businessId}/terminals/{terminalId}` — Rename a terminal (feature `team.manage`)
- `POST /businesses/{businessId}/terminals/{terminalId}/pairing-code` — A fresh pairing code (feature `team.manage`)
- `POST /businesses/{businessId}/terminals/{terminalId}/revoke` — Revoke a terminal (feature `team.manage`)
- `POST /businesses/{businessId}/team/{personId}/pin` — Give a team member a terminal PIN (feature `team.manage`)
- `DELETE /businesses/{businessId}/team/{personId}/pin` — Remove a team member’s terminal PIN (feature `team.manage`)
- `POST /terminal/pair` — Pair this device as a terminal
- `GET /terminal/me` — Where this terminal is paired
- `POST /terminal/sign-in` — Sign in on a terminal with a PIN

### Operator API

#### business — Business profiles and settings

- `POST /businesses` — Create a business and its first location
- `POST /businesses/{businessId}/legal/merchant-agreement/accept` — Accept the current Merchant Agreement and Privacy Policy (feature `business.manage`)
- `GET /businesses` — List businesses
- `GET /businesses/{id}` — Get a business by ID
- `PATCH /businesses/{id}` — Update a business (feature `business.manage`)
- `POST /businesses/{id}/archive` — Archive a business (feature `business.manage`)
- `PATCH /businesses/{id}/slug` — Override the business slug (feature `business.manage`)
- `POST /businesses/{id}/slug/revert` — Revert a business slug to auto-generated from the current name (feature `business.manage`)
- `POST /businesses/{id}/message-preview` — Preview unsaved customer-facing words (feature `business.manage`)
- `GET /businesses/{id}/message-changes` — Who last changed each customer-facing line (feature `business.manage`)
- `POST /businesses/{businessId}/api-keys` — Create an API key (feature `business.manage`)
- `GET /businesses/{businessId}/api-keys` — List API keys (feature `business.manage`)
- `DELETE /businesses/{businessId}/api-keys/{id}` — Revoke an API key (feature `business.manage`)
- `POST /businesses/{businessId}/locations/{locationId}/page-preview` — Render the location page with unsaved edits (feature `location.manage`)
- `POST /businesses/{businessId}/locations/{locationId}/listing-preview` — Render an offering’s booking page from an unsaved editor form (feature `catalog.manage`)
- `POST /businesses/{businessId}/locations/{locationId}/passes-preview` — Render the passes page with an unsaved plan (feature `catalog.manage`)
- `GET /businesses/{businessId}/tax-rates` — List active tax rates (feature `business.view`)
- `GET /businesses/{businessId}/tax-setup` — Tax setup for the Payments panel (feature `business.manage`)
- `PUT /businesses/{businessId}/tax-rates` — Replace active tax rates (feature `business.manage`)
- `PATCH /businesses/{businessId}/tax-rates/{id}` — Update a tax rate (feature `business.manage`)
- `POST /businesses/{businessId}/tax-rates/{id}/archive` — Archive a tax rate (feature `business.manage`)
- `GET /businesses/{businessId}/revenue-categories` — List revenue categories (feature `business.view`)
- `POST /businesses/{businessId}/revenue-categories` — Create a revenue category (feature `business.manage`)
- `PATCH /businesses/{businessId}/revenue-categories/{id}` — Update a revenue category (feature `business.manage`)
- `POST /businesses/{businessId}/revenue-categories/{id}/archive` — Archive a revenue category (feature `business.manage`)
- `GET /businesses/{businessId}/discounts` — List discounts (feature `catalog.manage or booking.manage`)
- `POST /businesses/{businessId}/discounts` — Create a discount (feature `catalog.manage`)
- `GET /businesses/{businessId}/discounts/{id}` — Read a discount (feature `catalog.manage or booking.manage`)
- `PATCH /businesses/{businessId}/discounts/{id}` — Update a discount (feature `catalog.manage`)
- `POST /businesses/{businessId}/discounts/{id}/archive` — Archive a discount (feature `catalog.manage`)
- `GET /businesses/{businessId}/calendar-connections` — Google Calendar for a person or a location’s spaces (feature `location.view`)
- `POST /businesses/{businessId}/calendar-connections/start` — Start connecting a Google Calendar (feature `location.view`)
- `GET /businesses/{businessId}/calendar-connections/{connectionId}/calendars` — The calendars on a Google account (feature `location.view`)
- `PATCH /businesses/{businessId}/calendar-connections/{connectionId}` — Save which calendars a connection uses (feature `location.view`)
- `DELETE /businesses/{businessId}/calendar-connections/{connectionId}` — Disconnect a Google Calendar (feature `location.view`)
- `GET /businesses/{businessId}/calendar/busy` — Google busy time for the calendar’s lanes (feature `location.view`)
- `GET /businesses/{businessId}/changes` — Console freshness marker (feature `booking.view`)
- `GET /businesses/{businessId}/home` — Today — the operator console's first tab (feature `location.view`)
- `GET /businesses/{businessId}/home/activity` — Today's Activity — booked, added, cancelled and moved (feature `location.view`)
- `POST /businesses/{businessId}/home/activity/seen` — Mark Activity read (feature `location.view`)
- `POST /businesses/{businessId}/home/needs-you/dismiss` — Dismiss Needs-you rows (feature `location.view`)
- `GET /businesses/{businessId}/locations/{locationId}/readiness` — Can a customer book this location, and what is first if not (feature `location.view`)
- `GET /businesses/{businessId}/my-day` — Day view of the schedule and roster (feature `booking.view`)
- `GET /businesses/{businessId}/calendar` — Ops calendar range for the Calendar tab (feature `location.view`)
- `GET /businesses/{businessId}/calendar/items` — Posts and scheduled messages on the Calendar’s days (feature `location.view`)
- `GET /businesses/{businessId}/journey-sends` — One day’s scheduled messages, with each recipient (feature `catalog.manage`)
- `GET /businesses/{businessId}/journey` — List the studio journey (feature `business.view`)
- `POST /businesses/{businessId}/journey/steps` — Add a studio journey step (feature `catalog.manage`)
- `PATCH /businesses/{businessId}/journey/steps/{stepId}` — Update a studio journey step (feature `catalog.manage`)
- `DELETE /businesses/{businessId}/journey/steps/{stepId}` — Archive a studio journey step (feature `catalog.manage`)
- `PUT /businesses/{businessId}/journey/order` — Reorder studio journey steps (feature `catalog.manage`)
- `GET /businesses/{businessId}/journey/arrive-and-leave` — Read the business's Arrive and leave (feature `business.view`)
- `PUT /businesses/{businessId}/journey/arrive-and-leave` — Set the business's Arrive and leave (feature `catalog.manage`)
- `GET /businesses/{businessId}/social-connections` — A location’s Instagram and Facebook connection (feature `catalog.manage`)
- `GET /businesses/{businessId}/social-connections/bio-link` — Instagram’s bio link (feature `catalog.manage`)
- `POST /businesses/{businessId}/social-connections/start` — Start connecting Instagram and Facebook (feature `catalog.manage`)
- `POST /businesses/{businessId}/social-connections` — Keep the Page the owner picked (feature `catalog.manage`)
- `DELETE /businesses/{businessId}/social-connections/{connectionId}` — Disconnect Instagram and Facebook (feature `catalog.manage`)
- `GET /businesses/{businessId}/social-voice` — How the studio writes its posts (feature `catalog.manage`)
- `PUT /businesses/{businessId}/social-voice` — Rewrite the studio’s voice (feature `catalog.manage`)
- `POST /businesses/{businessId}/social-connections/{connectionId}/learn-voice` — Learn the studio’s voice again (feature `catalog.manage`)
- `POST /businesses/{businessId}/social-posts/preview` — Preview a social post (feature `catalog.manage`)
- `POST /businesses/{businessId}/social-posts/words` — Write the words of a social post again (feature `catalog.manage`)
- `GET /businesses/{businessId}/social-posts/frame.jpg` — One typeset frame of a social post, drawn now (feature `catalog.manage`)
- `GET /businesses/{businessId}/social-posts/card.jpg` — The Facebook card a class date’s post will show (feature `catalog.manage`)
- `GET /businesses/{businessId}/social-posts/suggestions` — Up next: what is worth posting today (feature `catalog.manage`)
- `POST /businesses/{businessId}/social-posts` — Post to Instagram and Facebook (feature `catalog.manage`)
- `GET /businesses/{businessId}/social-posts` — Scheduled and recent social posts (feature `catalog.manage`)
- `GET /businesses/{businessId}/social-posts/{postId}` — One social post (feature `catalog.manage`)
- `PATCH /businesses/{businessId}/social-posts/{postId}` — Edit a scheduled social post (feature `catalog.manage`)
- `POST /businesses/{businessId}/social-posts/{postId}/cancel` — Cancel a social post that has not gone out (feature `catalog.manage`)
- `POST /businesses/{businessId}/social-posts/{postId}/targets/{targetId}/retry` — Retry a social post that failed (feature `catalog.manage`)
- `GET /businesses/{businessId}/social-results` — What a month of social posts brought (feature `catalog.manage`)

#### location — Physical locations

- `GET /locations/{id}/agreements` — List a location's waivers & terms (feature `location.view`)
- `POST /locations/{id}/agreements` — Add a waiver or terms document (feature `catalog.manage`)
- `PATCH /locations/{id}/agreements/{documentId}` — Change a waiver or terms document (feature `catalog.manage`)
- `POST /locations/{id}/agreements/{documentId}/archive` — Remove a waiver or terms document (feature `catalog.manage`)
- `GET /businesses/{businessId}/locations` — List locations for a business
- `POST /businesses/{businessId}/locations` — Create a location (feature `location.manage`)
- `GET /locations/{id}` — Get a location
- `PATCH /locations/{id}` — Update a location (feature `location.manage`)
- `POST /locations/{id}/archive` — Archive a location (feature `location.manage`)
- `PATCH /locations/{id}/slug` — Override a location slug (feature `location.manage`)
- `POST /locations/{id}/slug/revert` — Revert a location slug to auto-generated from the current name (feature `location.manage`)
- `GET /locations/{id}/closures` — List a location's upcoming blocked time (feature `location.view`)
- `GET /locations/{id}/closures/holiday-suggestions` — US federal holidays for the location year (feature `location.view`)
- `POST /locations/{id}/closures` — Block time or add a holiday (feature `location.manage`)
- `GET /locations/{id}/calendar-feeds` — List subscribe calendars for a location (feature `location.view`)
- `POST /locations/{id}/calendar-feeds` — Create a subscribe calendar (feature `location.view`)
- `POST /locations/{id}/calendar-feeds/{feedId}/rotate` — Replace a subscribe calendar link (feature `location.view`)
- `POST /locations/{id}/calendar-feeds/{feedId}/revoke` — Stop a subscribe calendar (feature `location.view`)
- `DELETE /locations/closures/{closureId}` — Remove blocked time (feature `location.manage`)

#### catalog — Spaces, team, and offerings

- `GET /businesses/{businessId}/assets` — List photos (feature `location.view`)
- `POST /businesses/{businessId}/assets` — Upload a photo (feature `catalog.manage`)
- `GET /assets/{id}` — Get a photo (feature `location.view`)
- `PATCH /assets/{id}` — Update a photo’s title, alt text or tags (feature `catalog.manage`)
- `POST /assets/{id}/archive` — Archive a photo (feature `catalog.manage`)
- `POST /assets/{id}/replace` — Replace a photo’s file (feature `catalog.manage`)
- `DELETE /assets/{id}` — Delete a photo (feature `catalog.manage`)
- `POST /offerings/{id}/images/attach` — Attach a photo to an offering (feature `catalog.manage`)
- `POST /resources/{id}/images/attach` — Attach a photo to a space (feature `catalog.manage`)
- `POST /instructor-profiles/{id}/images/attach` — Attach a photo as an instructor headshot (feature `team.manage`)
- `POST /locations/{id}/images/attach` — Attach a photo to a location (feature `location.manage`)
- `POST /locations/{id}/logo/attach` — Attach a photo as the location logo (feature `location.manage`)
- `POST /locations/{id}/header/attach` — Attach a photo as the location header image (feature `location.manage`)
- `POST /businesses/{businessId}/locations/{locationId}/resources` — Create a space (feature `catalog.manage`)
- `GET /businesses/{businessId}/locations/{locationId}/resources` — List spaces at a location (feature `location.view`)
- `GET /resources/{id}` — Get a space (feature `location.view`)
- `GET /resources/{id}/floor` — Seating chart for one day (feature `booking.view`)
- `PATCH /resources/{id}` — Update a space (feature `catalog.manage`)
- `POST /resources/{id}/archive` — Archive a space (feature `catalog.manage`)
- `POST /businesses/{businessId}/instructor-profiles` — Create an instructor profile (feature `team.manage`)
- `GET /businesses/{businessId}/instructor-profiles` — List instructor profiles (feature `location.view`)
- `GET /instructor-profiles/{id}` — Get an instructor profile (feature `location.view`)
- `GET /instructor-profiles/{id}/time-off` — List a team member's upcoming time off (feature `location.view`)
- `POST /instructor-profiles/{id}/time-off` — Add time off for a team member (feature `team.manage`)
- `PATCH /instructor-profiles/{id}` — Update an instructor profile (feature `team.manage`)
- `POST /instructor-profiles/{id}/archive` — Archive an instructor profile (feature `team.manage`)
- `POST /businesses/{businessId}/locations/{locationId}/offerings` — Create an offering (feature `catalog.manage`)
- `GET /businesses/{businessId}/locations/{locationId}/offerings/slug-availability` — Check whether an offering slug is available at a location (feature `catalog.manage`)
- `GET /businesses/{businessId}/locations/{locationId}/offerings` — List offerings at a location (feature `location.view`)
- `PATCH /businesses/{businessId}/locations/{locationId}/offerings/order` — Reorder offerings of one type (feature `catalog.manage`)
- `GET /offerings/{id}` — Get an offering (feature `location.view`)
- `GET /offerings/{id}/overview` — Get an offering’s upcoming dates (feature `location.view`)
- `GET /offerings/{id}/share` — Get an offering as a post to share (feature `location.view`)
- `PATCH /offerings/{id}` — Update an offering (feature `catalog.manage`)
- `PATCH /offerings/{id}/slug` — Override an offering slug (unique per location) (feature `catalog.manage`)
- `POST /offerings/{id}/slug/revert` — Revert an offering slug to auto-generated from the current name (feature `catalog.manage`)
- `POST /offerings/{id}/duplicate` — Copy an offering as a new draft (feature `catalog.manage`)
- `POST /offerings/{id}/publish` — Show an offering for booking (feature `catalog.manage`)
- `POST /offerings/{id}/hide` — Hide an offering from booking (feature `catalog.manage`)
- `POST /offerings/{id}/archive` — Archive an offering (feature `catalog.manage`)
- `DELETE /offerings/{id}` — Delete a draft (feature `catalog.manage`)
- `GET /businesses/{businessId}/locations/{locationId}/series` — List series at a location (feature `location.view`)
- `GET /businesses/{businessId}/offerings/{id}/series/preview` — Preview series dates (feature `location.view`)
- `GET /businesses/{businessId}/offerings/{id}/series` — List series on an offering (feature `location.view`)
- `POST /businesses/{businessId}/offerings/{id}/series` — Create a series (feature `catalog.manage`)
- `GET /businesses/{businessId}/series/{id}` — Get a series (feature `location.view`)
- `PATCH /businesses/{businessId}/series/{id}` — Update a series (feature `catalog.manage`)
- `DELETE /businesses/{businessId}/series/{id}` — Archive a series (feature `catalog.manage`)
- `POST /businesses/{businessId}/series/{id}/publish` — Publish a series (feature `catalog.manage`)
- `POST /businesses/{businessId}/series/{id}/hide` — Hide a series (feature `catalog.manage`)
- `GET /businesses/{businessId}/series/{id}/overview` — Series overview — roster, dates, money collected (feature `booking.view`)
- `PATCH /businesses/{businessId}/occurrences/{occurrenceId}` — Change one class date: who teaches it, which room, how many spots (feature `catalog.manage`)
- `POST /businesses/{businessId}/occurrences/{occurrenceId}/cancel` — Cancel one class date — a series date keeps the series, a drop-in date refunds its bookings (feature `booking.manage`)
- `DELETE /businesses/{businessId}/occurrences/{occurrenceId}` — Take back a class date added by mistake — a one-off nobody has booked (feature `catalog.manage`)
- `GET /businesses/{businessId}/questions` — List the checkout-question catalog
- `POST /businesses/{businessId}/questions` — Create a checkout question
- `PATCH /businesses/{businessId}/questions/{questionId}` — Update a checkout question
- `POST /businesses/{businessId}/questions/{questionId}/archive` — Archive a checkout question
- `POST /offerings/{id}/images` — Upload an offering photo (feature `catalog.manage`)
- `POST /resources/{id}/images` — Upload a space photo (feature `catalog.manage`)
- `POST /instructor-profiles/{id}/images` — Upload an instructor headshot (feature `team.manage`)
- `POST /locations/{id}/images` — Upload a location photo (feature `location.manage`)
- `GET /locations/{id}/images` — List location photos (feature `location.view`)
- `PATCH /locations/{id}/images/order` — Reorder location photos (feature `location.manage`)
- `GET /offerings/{id}/images` — List offering photos (feature `location.view`)
- `GET /resources/{id}/images` — List space photos (feature `location.view`)
- `GET /instructor-profiles/{id}/images` — List instructor headshots (feature `location.view`)
- `PATCH /resources/{id}/images/order` — Reorder space photos (feature `catalog.manage`)
- `PATCH /offerings/{id}/images/order` — Reorder offering photos (feature `catalog.manage`)
- `GET /images/{id}` — Get a photo placement (feature `location.view`)
- `PATCH /images/{id}` — Frame a photo placement (feature `catalog.manage`)
- `DELETE /images/{id}` — Delete a photo (feature `catalog.manage`)
- `POST /locations/{id}/logo` — Upload a location logo (feature `location.manage`)
- `GET /locations/{id}/logo` — List a location's logo placement (feature `location.view`)
- `POST /locations/{id}/header` — Upload a location header image (feature `location.manage`)
- `GET /locations/{id}/header` — List the location header image (feature `location.view`)
- `DELETE /locations/{id}/header` — Remove a location header image (feature `location.manage`)
- `DELETE /locations/{id}/logo` — Remove a location logo (feature `location.manage`)
- `GET /businesses/{businessId}/offerings/{offeringId}/journey` — List a listing's journey (feature `location.view`)
- `POST /businesses/{businessId}/offerings/{offeringId}/journey/steps` — Add a listing journey step (feature `catalog.manage`)
- `PATCH /businesses/{businessId}/offerings/{offeringId}/journey/steps/{stepId}` — Update a listing journey step (feature `catalog.manage`)
- `DELETE /businesses/{businessId}/offerings/{offeringId}/journey/steps/{stepId}` — Archive a listing journey step (feature `catalog.manage`)
- `PUT /businesses/{businessId}/offerings/{offeringId}/journey/order` — Reorder a listing's own journey steps (feature `catalog.manage`)
- `PUT /businesses/{businessId}/offerings/{offeringId}/journey/off/{stepId}` — Switch a studio step off for one listing (feature `catalog.manage`)
- `PUT /businesses/{businessId}/offerings/{offeringId}/journey/timing/{stepId}` — Retime the studio Check in, Collect balance, Check out or Complete for one listing (feature `catalog.manage`)
- `GET /businesses/{businessId}/offerings/{offeringId}/journey/arrive-and-leave` — Read a listing's Arrive and leave (feature `location.view`)
- `PUT /businesses/{businessId}/offerings/{offeringId}/journey/arrive-and-leave` — Set a listing's Arrive and leave (feature `catalog.manage`)
- `PUT /businesses/{businessId}/offerings/{offeringId}/pieces` — Turn a listing's Pieces on or off (feature `catalog.manage`)

#### products — Products, their options, and the stock ledger

- `GET /businesses/{businessId}/products` — List products (feature `location.view`)
- `POST /businesses/{businessId}/products` — Create a product (feature `catalog.manage`)
- `PATCH /businesses/{businessId}/products/order` — Reorder products (feature `catalog.manage`)
- `GET /products/{productId}` — Get a product (feature `location.view`)
- `PATCH /products/{productId}` — Update a product (feature `catalog.manage`)
- `POST /products/{productId}/publish` — Put a product on sale (feature `catalog.manage`)
- `POST /products/{productId}/hide` — Hide a product (feature `catalog.manage`)
- `POST /products/{productId}/archive` — Archive a product (feature `catalog.manage`)
- `POST /products/{productId}/duplicate` — Copy a product as a new draft (feature `catalog.manage`)
- `GET /products/{productId}/variants/{variantId}/stock` — List an option's stock ledger (feature `location.view`)
- `POST /products/{productId}/variants/{variantId}/stock` — Record received, counted or adjusted stock (feature `catalog.manage`)
- `GET /products/{productId}/images` — List a product's photos (feature `location.view`)
- `POST /products/{productId}/images` — Upload a product photo (feature `catalog.manage`)
- `POST /products/{productId}/images/attach` — Attach a library photo to a product (feature `catalog.manage`)
- `PATCH /products/{productId}/images/order` — Reorder a product's photos (feature `catalog.manage`)
- `POST /businesses/{businessId}/order-lines/{orderLineId}/cancel` — Cancel an order line — refund and restock (feature `booking.manage`)
- `GET /businesses/{businessId}/order-lines` — List pickups (feature `booking.view`)
- `POST /businesses/{businessId}/order-lines/{orderLineId}/fulfill` — Mark an order line picked up (feature `booking.checkin`)

#### availability — Schedule projection and bookable slots

- `GET /offerings/{id}/availability-explain` — Why these times — one day of a reservation’s or rental’s open times, explained (feature `location.view`)
- `GET /availability` — Get projected availability slots
- `GET /occurrence` — Get a single bookable slot
- `POST /occurrences/materialize` — Materialize a bookable slot into a booked time
- `GET /locations/{locationId}/is-open` — Check whether a location is currently open
- `POST /businesses/{businessId}/schedules` — Create a schedule (feature `catalog.manage`)
- `GET /businesses/{businessId}/schedules` — List schedules for a business (feature `location.view`)
- `GET /schedules/{id}` — Get a schedule (feature `location.view`)
- `PATCH /schedules/{id}` — Update a schedule (feature `catalog.manage`)
- `POST /schedules/{id}/archive` — Archive a schedule (feature `catalog.manage`)
- `GET /schedules/{id}/health` — Validate that a schedule projects sane dates (feature `location.view`)
- `GET /schedules/{id}/occurrences` — Project schedule dates in a window (feature `location.view`)
- `DELETE /schedules/{id}` — Delete a schedule (not supported)

#### booking — Operator booking lifecycle

- `POST /businesses/{businessId}/booking-imports` — Start a booking import (feature `booking.manage`)
- `GET /businesses/{businessId}/booking-imports/latest` — The latest booking import (feature `booking.manage`)
- `GET /businesses/{businessId}/booking-imports/sample.csv` — The booking import’s sample file (feature `booking.manage`)
- `GET /businesses/{businessId}/booking-imports/{importId}` — Get a booking import (feature `booking.manage`)
- `PATCH /businesses/{businessId}/booking-imports/{importId}` — Save a booking import’s choices (feature `booking.manage`)
- `POST /businesses/{businessId}/booking-imports/{importId}/read-times` — Check how a booking import reads its times (feature `booking.manage`)
- `POST /businesses/{businessId}/booking-imports/{importId}/match-listings` — Match a booking import’s listings and people (feature `booking.manage`)
- `POST /businesses/{businessId}/booking-imports/{importId}/rows` — Import a chunk of booking rows (feature `booking.manage`)
- `POST /businesses/{businessId}/booking-imports/{importId}/issues/{issueId}/resolve` — Answer a booking import question (feature `booking.manage`)
- `POST /businesses/{businessId}/booking-imports/{importId}/issues/{issueId}/skip` — Skip a booking import question (feature `booking.manage`)
- `POST /businesses/{businessId}/inline-ai/import-columns` — Match an import’s columns with the model (feature `booking.manage`)
- `POST /businesses/{businessId}/inline-ai/import-listings` — Match an import’s listings and people with the model (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings` — Create a booking hold (feature `booking.manage`)
- `GET /businesses/{businessId}/availability` — List bookable dates and times for operators (includes past-cutoff, in-progress, and closed starts) (feature `booking.manage`)
- `POST /businesses/{businessId}/carts` — Create an operator pay-by-link cart (feature `booking.manage`)
- `POST /businesses/{businessId}/carts/{token}/checkout` — Check out an operator cart at the desk (feature `booking.manage`)
- `POST /businesses/{businessId}/carts/{token}/cancel` — Cancel a staff cart and release its holds (feature `booking.manage`)
- `POST /businesses/{businessId}/carts/{token}/email` — Email a pay link to the cart customer (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/agreements/send` — Send the customer a link to accept the booking's waivers & terms (feature `booking.checkin`)
- `POST /businesses/{businessId}/bookings/{bookingId}/agreements/{documentId}/override` — Mark one of the booking's waivers & terms agreed (feature `booking.checkin`)
- `POST /businesses/{businessId}/bookings/{bookingId}/pay-link` — Send a held booking its pay link, by email or text (feature `booking.manage`)
- `GET /businesses/{businessId}/bookings` — List bookings for the operator console (feature `booking.view`)
- `GET /businesses/{businessId}/bookings/export.csv` — Export the bookings list as CSV (feature `booking.view`)
- `GET /businesses/{businessId}/bookings/{bookingId}` — Get a booking (feature `booking.view`)
- `POST /businesses/{businessId}/bookings/{bookingId}/confirm` — Confirm a held booking with payment (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/collect-balance` — Collect remaining booking balance (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/record-payment` — Record a booking as paid through a payment method (feature `booking.manage`)
- `PUT /businesses/{businessId}/bookings/{bookingId}/answers` — Write what the desk asked onto a booking (feature `booking.manage`)
- `GET /businesses/{businessId}/bookings/{bookingId}/add-ons` — What a booking can still add at the class (feature `booking.view`)
- `POST /businesses/{businessId}/bookings/{bookingId}/add-ons` — Add pieces to a booking on its saved card (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/cancel` — Cancel a booking (feature `booking.manage`)
- `POST /businesses/{businessId}/enrollments/{enrollmentId}/cancel` — Cancel a series enrollment (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/email` — Change the email a booking belongs to (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/reschedule` — Reschedule a booking (feature `booking.manage`)
- `PATCH /businesses/{businessId}/bookings/{bookingId}` — Edit a booking (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/spots` — Change how many spots a booking holds (feature `booking.manage`)
- `GET /businesses/{businessId}/bookings/{bookingId}/places` — Where a booking could sit: its room’s tables, and the other rooms (feature `booking.manage`)
- `GET /businesses/{businessId}/bookings/{bookingId}/rooms` — Rooms a booking could move to (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/check-in` — Check in a booking (status checked_in) (feature `booking.checkin`)
- `GET /businesses/{businessId}/bookings/{bookingId}/desk-check-in` — Preview early check-in stay, tables, and next opening (feature `booking.checkin`)
- `POST /businesses/{businessId}/bookings/{bookingId}/check-in-at-desk` — Desk check-in (may start now and seat a table) (feature `booking.checkin`)
- `POST /businesses/{businessId}/bookings/{bookingId}/check-out` — Check out a booking (status checked_out; frees a sole booking's space early) (feature `booking.checkin`)
- `POST /businesses/{businessId}/bookings/{bookingId}/undo-check-out` — Undo check-out (back to checked_in) (feature `booking.checkin`)
- `POST /businesses/{businessId}/money-effects` — Dry-run: declare the money effect of an action without executing it (feature `booking.view`)
- `POST /businesses/{businessId}/bookings/{bookingId}/undo-check-in` — Undo check-in (back to confirmed) (feature `booking.checkin`)
- `POST /businesses/{businessId}/bookings/{bookingId}/no-show` — Mark a booking as no-show (feature `booking.checkin`)
- `GET /businesses/{businessId}/occurrences/{occurrenceId}/positions` — Class date fill map (feature `booking.view`)
- `DELETE /businesses/{businessId}/occurrences/{occurrenceId}/waitlist/{entryId}` — Take someone off a class date's waitlist (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/table` — Move a party to another table (feature `booking.checkin`)
- `POST /businesses/{businessId}/bookings/{bookingId}/positions/move` — Move, swap, or assign one spot (feature `booking.checkin`)
- `POST /businesses/{businessId}/occurrences/{occurrenceId}/message` — Email everyone booked on this date (feature `booking.checkin`)
- `POST /businesses/{businessId}/wallet-notes` — Message Wallet holders (feature `crm.notes`)
- `GET /businesses/{businessId}/channels` — List where spots are sold elsewhere (feature `booking.view`)
- `POST /businesses/{businessId}/channels` — Add where spots are sold elsewhere (feature `booking.manage`)
- `PATCH /businesses/{businessId}/channels/{channelId}` — Rename or archive where spots are sold elsewhere (feature `booking.manage`)
- `GET /businesses/{businessId}/occurrences/{occurrenceId}/claims` — List spots sold elsewhere on this date (feature `booking.view`)
- `POST /businesses/{businessId}/occurrences/{occurrenceId}/claims` — Mark spots sold elsewhere (feature `booking.checkin`)
- `PUT /businesses/{businessId}/channels/{channelId}/claims/by-ref/{externalRef}` — Sync spots sold elsewhere by reference (feature `booking.checkin`)
- `POST /businesses/{businessId}/channels/{channelId}/claims/sync` — Sync many spots sold elsewhere at once (feature `booking.checkin`)
- `PATCH /businesses/{businessId}/claims/{claimId}` — Edit spots sold elsewhere (feature `booking.checkin`)
- `DELETE /businesses/{businessId}/claims/{claimId}` — Release spots sold elsewhere (feature `booking.checkin`)
- `PUT /businesses/{businessId}/carts/{token}/code` — Add or remove a staff cart's code (feature `booking.manage`)
- `GET /businesses/{businessId}/locations/{locationId}/occupancy` — Who is at this location right now (feature `booking.view`)
- `GET /businesses/{businessId}/bookings/{bookingId}/timeline` — Get booking event timeline (feature `booking.view`)
- `GET /businesses/{businessId}/bookings/{bookingId}/steps` — List a booking's journey (feature `booking.view`)
- `POST /businesses/{businessId}/bookings/{bookingId}/steps/{bookingStepId}/mark` — Mark a booking journey step (feature `booking.checkin`)
- `POST /businesses/{businessId}/bookings/{bookingId}/steps/{bookingStepId}/skip` — Skip a booking journey step (feature `booking.checkin`)
- `POST /businesses/{businessId}/bookings/{bookingId}/steps/{bookingStepId}/run` — Run a booking journey step now (feature `booking.checkin`)
- `POST /businesses/{businessId}/occurrences/{occurrenceId}/steps/{stepId}/mark` — Mark a journey step for everyone on a date (feature `booking.checkin`)
- `GET /businesses/{businessId}/bookings/{bookingId}/steps/{bookingStepId}/message` — The message a booking step would send (feature `booking.view`)
- `POST /businesses/{businessId}/bookings/{bookingId}/steps/{bookingStepId}/resend` — Send a booking step’s message again (feature `booking.checkin`)
- `POST /businesses/{businessId}/journey/preview` — Preview a journey message over a sample booking (feature `business.view`)
- `GET /businesses/{businessId}/bookings/{bookingId}/pieces` — List a booking's pieces (feature `booking.view`)
- `GET /businesses/{businessId}/occurrences/{occurrenceId}/pieces` — List a class date's pieces (feature `booking.view`)
- `POST /businesses/{businessId}/bookings/{bookingId}/pieces` — Add a piece to a booking (feature `booking.manage`)
- `POST /businesses/{businessId}/bookings/{bookingId}/pieces/remind` — Send a booking's pickup reminder now (feature `booking.manage`)
- `GET /businesses/{businessId}/pieces` — List the shelf (feature `booking.view`)
- `POST /businesses/{businessId}/pieces/move` — Move pieces to a stage (feature `booking.manage`)
- `PATCH /businesses/{businessId}/pieces/{pieceId}` — Rename a piece or set its shelf (feature `booking.manage`)
- `DELETE /businesses/{businessId}/pieces/{pieceId}` — Remove a piece (feature `booking.manage`)
- `POST /businesses/{businessId}/pieces/{pieceId}/booking` — Move a piece to another booking (feature `booking.manage`)
- `POST /businesses/{businessId}/pieces/{pieceId}/photos` — Add photos to a piece (feature `booking.manage`)
- `DELETE /businesses/{businessId}/pieces/{pieceId}/photos/{photoId}` — Delete a photo of a piece (feature `booking.manage`)
- `POST /businesses/{businessId}/inline-ai/name-piece` — Name a piece from its photo (feature `booking.manage`)
- `GET /businesses/{businessId}/locations/{locationId}/piece-shelves` — Get a location's shelves (feature `booking.view`)
- `PUT /businesses/{businessId}/locations/{locationId}/piece-shelves` — Set a location's shelves (feature `booking.manage`)

#### commerce — Payments, balances, and Stripe Connect

- `GET /businesses/{businessId}/accounting/connect` — Start a QuickBooks Online connection (feature `business.manage`)
- `POST /businesses/{businessId}/accounting/connect/complete` — Finish a QuickBooks Online connection (feature `business.manage`)
- `GET /businesses/{businessId}/accounting/connection` — Get the live accounting connection (feature `business.manage`)
- `PATCH /businesses/{businessId}/accounting/connection` — Update the posting start date (feature `business.manage`)
- `DELETE /businesses/{businessId}/accounting/connection` — Disconnect QuickBooks Online (feature `business.manage`)
- `GET /businesses/{businessId}/accounting/map` — Propose the QuickBooks account map (feature `business.manage`)
- `PUT /businesses/{businessId}/accounting/map` — Confirm QuickBooks account selections (feature `business.manage`)
- `POST /businesses/{businessId}/accounting/map/{category}/create` — Create a QuickBooks account and confirm it (feature `business.manage`)
- `GET /businesses/{businessId}/accounting/postings` — List recent QuickBooks postings (feature `business.manage`)
- `POST /businesses/{businessId}/accounting/postings/{batchId}/retry` — Retry a failed QuickBooks posting (feature `business.manage`)
- `POST /businesses/{businessId}/stripe/connect-account` — Create a Stripe Connect account for the business (feature `business.manage`)
- `POST /businesses/{businessId}/stripe/sandbox-account` — Create a verified Stripe test account (development and staging only) (feature `business.manage`)
- `POST /businesses/{businessId}/stripe/account-session` — Create a Stripe Account Session for embedded onboarding (feature `business.manage`)
- `GET /businesses/{businessId}/stripe/status` — Get the Stripe Connect onboarding status for the business (feature `business.manage`)
- `GET /businesses/{businessId}/payments/status` — The business's payments provider and whether it can take cards now (feature `business.manage`)
- `DELETE /businesses/{businessId}/payments/account` — Unlink the business's payments account (platform admins only) (feature `business.manage`)
- `GET /businesses/{businessId}/demo` — Demo mode: on or off, whether it can be switched on, and what Clear would delete (feature `business.manage`)
- `POST /businesses/{businessId}/demo` — Switch demo mode on (feature `business.manage`)
- `POST /businesses/{businessId}/demo/clear` — Delete the demo data; demo stays on (feature `business.manage`)
- `DELETE /businesses/{businessId}/demo` — Switch demo mode off, deleting its data (feature `business.manage`)
- `POST /businesses/{businessId}/payments/provider` — Choose the business's card processor, Stripe or TRX, before its first payment (feature `business.manage`)
- `GET /businesses/{businessId}/payments/trx-application` — The business's TRX application — status, draft, masked facts (feature `business.manage`)
- `PUT /businesses/{businessId}/payments/trx-application` — Save the non-sensitive half of the TRX application for later (feature `business.manage`)
- `POST /businesses/{businessId}/payments/trx-application/submit` — Send the TRX application: Lead/Insert, then a File/Insert per document (feature `business.manage`)
- `POST /businesses/{businessId}/payments/trx-application/documents` — Send again only the documents TRX did not take — against the same lead (feature `business.manage`)
- `GET /businesses/{businessId}/payments/trx-pricing` — The pricing TRX’s merchant application states for the business (feature `business.manage`)
- `PUT /businesses/{businessId}/payments/trx-pricing` — Set the business’s TRX pricing (platform admins only) (feature `business.manage`)
- `GET /businesses/{businessId}/payments/trx-account` — The TRX merchant record, masked — or null when the business has none (feature `business.manage`)
- `PUT /businesses/{businessId}/payments/trx-account` — Write the TRX merchant record and verify its login (platform admins only) (feature `business.manage`)
- `POST /businesses/{businessId}/payments/trx-account/check` — Check a merchant's TRX gateway login and find TRX's record of it (platform admins only) (feature `business.manage`)
- `POST /businesses/{businessId}/payments/trx-account/verify` — Re-run the login probe on the stored TRX merchant record (feature `business.manage`)
- `GET /businesses/{businessId}/payments/trx-account/legacy-pull` — The last pull of a legacy TRX record asked for on this business — or null (platform admins only) (feature `business.manage`)
- `POST /businesses/{businessId}/payments/trx-account/legacy-pull` — Take the TRX merchant record from the studio's legacy PlaceFull account (platform admins only) (feature `business.manage`)
- `POST /businesses/{businessId}/payments` — Create a payment (feature `business.manage`)
- `GET /businesses/{businessId}/payments/{paymentId}` — Get a payment (feature `business.view`)
- `POST /businesses/{businessId}/payments/{paymentId}/authorize` — Authorize a payment (feature `business.manage`)
- `POST /businesses/{businessId}/payments/{paymentId}/capture` — Capture an authorized payment (feature `business.manage`)
- `POST /businesses/{businessId}/payments/{paymentId}/refund` — Refund a payment (feature `business.manage`)
- `POST /businesses/{businessId}/payments/{paymentId}/receipt` — Send a payment's receipt again (feature `booking.checkin`)
- `GET /businesses/{businessId}/balance` — Get business ledger balance (feature `business.view`)
- `GET /businesses/{businessId}/bookings/{bookingId}/balance` — Get booking ledger balance (feature `booking.view`)
- `GET /businesses/{businessId}/customers/{customerId}/balance` — Get customer ledger balance (feature `crm.view`)
- `GET /businesses/{businessId}/platform-fee-revenue` — Get platform fee revenue for a business (feature `business.manage`)
- `GET /businesses/{businessId}/performance` — Every visible report, drawn for the Overview (feature `reports.view`)
- `GET /businesses/{businessId}/performance/{report}` — One report for a period (feature `reports.view`)
- `GET /businesses/{businessId}/performance/{report}/export` — Export one report as CSV (feature `reports.view`)
- `GET /businesses/{businessId}/reports/money` — Payments report for a period (feature `finance.view`)
- `GET /businesses/{businessId}/reports/tax` — Tax report for a period (feature `finance.view`)
- `GET /businesses/{businessId}/reports/transactions` — Transaction lines for a period (feature `finance.view`)
- `GET /businesses/{businessId}/reports/transactions/export` — Export transaction lines as CSV (feature `finance.export`)
- `GET /businesses/{businessId}/reports/journal/export` — Export journal lines as CSV (feature `finance.export`)
- `GET /businesses/{businessId}/reports/tax/export` — Export the tax report as CSV (feature `finance.export`)
- `GET /businesses/{businessId}/reports/transactions/{paymentId}` — One payment: what it bought, what it cost, its timeline, card, refunds and disputes (feature `finance.view`)
- `GET /businesses/{businessId}/reports/deposits` — Deposits dated in a period — Stripe payouts or TRX batches, one shape (feature `finance.view`)
- `GET /businesses/{businessId}/reports/deposits/{depositId}` — One deposit with its breakdown and movements (feature `finance.view`)
- `GET /businesses/{businessId}/reports/fees` — A month's fees by kind, its sales, total, effective rate, rate history and rate by card type (feature `finance.view`)
- `GET /businesses/{businessId}/reports/statements` — The months a statement can be read for (feature `finance.view`)
- `GET /businesses/{businessId}/reports/statements/{month}` — A closed month's statement: deposits, withdrawals, chargebacks, reserves, fees, brands, totals (feature `finance.view`)
- `GET /businesses/{businessId}/reports/statements/{month}/export` — Export a month's statement as CSV (feature `finance.export`)
- `GET /businesses/{businessId}/payments/balance` — What the processor holds now and where it goes (feature `finance.view`)
- `GET /businesses/{businessId}/reports/payouts/{payoutId}/transactions` — Transaction lines for one Stripe payout (feature `finance.view`)
- `GET /businesses/{businessId}/reports/payouts/{payoutId}/transactions/export` — Export one payout's transaction lines as CSV (feature `finance.export`)
- `GET /businesses/{businessId}/payments/payouts` — TRX batches as the studio's payouts, and what is not yet deposited (feature `finance.view`)
- `GET /businesses/{businessId}/payments/payouts/{batchGuid}` — One TRX batch with its sales, returns and adjustments — the Deposit receipt (feature `finance.view`)
- `GET /businesses/{businessId}/payments/statements` — The monthly TRX statements fetched for this business (feature `finance.view`)
- `GET /businesses/{businessId}/payments/statements/{statementDate}` — One monthly TRX statement — deposits, card plans and the fee table (feature `finance.view`)

#### crm — Customer records and export

- `GET /businesses/{businessId}/customers/{customerId}/agreements` — A customer's waivers & terms at a location (feature `crm.view`)
- `POST /businesses/{businessId}/customers/{customerId}/agreements/{documentId}/mark-signed` — Mark a document as signed on paper (feature `crm.notes`)
- `GET /businesses/{businessId}/customers` — List customers (feature `crm.view`)
- `GET /businesses/{businessId}/customers/export` — Export customers as CSV or JSON (feature `crm.export`)
- `POST /businesses/{businessId}/customers` — Create a customer (feature `crm.notes`)
- `POST /businesses/{businessId}/customers/import` — Import customers (feature `crm.notes`)
- `GET /businesses/{businessId}/customers/{customerId}` — Get a customer (feature `crm.view`)
- `GET /businesses/{businessId}/customers/{customerId}/answers` — A customer's last answer to each question (feature `crm.view`)
- `GET /businesses/{businessId}/customers/{customerId}/bookings` — List a customer's recent bookings (feature `crm.view`)
- `GET /businesses/{businessId}/customers/{customerId}/purchases` — List a customer's product purchases (feature `crm.view`)
- `PATCH /businesses/{businessId}/customers/{customerId}` — Update a customer (feature `crm.notes`)
- `POST /businesses/{businessId}/customers/{customerId}/archive` — Archive a customer (feature `crm.notes`)
- `GET /businesses/{businessId}/customers/duplicates` — List possible duplicate customers (feature `crm.view`)
- `POST /businesses/{businessId}/customers/{customerId}/merge` — Merge another customer into this one (feature `crm.merge`)
- `POST /businesses/{businessId}/customers/{customerId}/split` — Split a contact field onto a new customer (feature `crm.merge`)

#### customers — Customer lists and the messages sent to them

- `GET /businesses/{businessId}/customer-lists` — List customer lists (feature `crm.view`)
- `POST /businesses/{businessId}/customer-lists` — Create a customer list (feature `crm.notes`)
- `POST /businesses/{businessId}/customer-lists/preview-counts` — Preview list counts for a rule (feature `crm.view`)
- `GET /businesses/{businessId}/customer-lists/{id}` — Get a customer list (feature `crm.view`)
- `PATCH /businesses/{businessId}/customer-lists/{id}` — Update a customer list (feature `crm.notes`)
- `POST /businesses/{businessId}/customer-lists/{id}/archive` — Archive a customer list (feature `crm.notes`)
- `GET /businesses/{businessId}/customer-lists/{id}/counts` — Count customers matching a list (feature `crm.view`)
- `GET /businesses/{businessId}/messages` — List marketing messages (feature `crm.view`)
- `POST /businesses/{businessId}/messages` — Create a message draft (feature `crm.notes`)
- `GET /businesses/{businessId}/messages/{id}` — Get a message (feature `crm.view`)
- `PATCH /businesses/{businessId}/messages/{id}` — Update a message draft (feature `crm.notes`)
- `POST /businesses/{businessId}/messages/{id}/schedule` — Schedule or send a message (feature `crm.notes`)
- `POST /businesses/{businessId}/messages/{id}/cancel` — Cancel a scheduled message (feature `crm.notes`)
- `POST /businesses/{businessId}/messages/{id}/reschedule` — Reschedule a scheduled message (feature `crm.notes`)
- `POST /businesses/{businessId}/messages/{id}/clone` — Clone a message into a new draft (feature `crm.notes`)
- `POST /businesses/{businessId}/messages/{id}/archive` — Archive a message (feature `crm.notes`)
- `GET /businesses/{businessId}/messages/{id}/preview` — Preview a message as HTML (feature `crm.view`)
- `GET /businesses/{businessId}/messages/{id}/recipients` — List per-recipient delivery outcomes (feature `crm.view`)
- `POST /businesses/{businessId}/messages/{id}/test` — Send a test to the signed-in operator (feature `crm.notes`)

#### membership — Plans, benefits, and pricing

- `POST /membership-plans/{id}/images/attach` — Attach a photo as a plan cover (feature `catalog.manage`)
- `POST /businesses/{businessId}/membership-plans` — Create a membership plan (feature `catalog.manage`)
- `GET /businesses/{businessId}/membership-plans` — List membership plans (feature `business.view`)
- `PATCH /businesses/{businessId}/membership-plans/order` — Reorder memberships or passes (feature `catalog.manage`)
- `GET /businesses/{businessId}/membership-plans/{planId}` — Get a membership plan (feature `business.view`)
- `PATCH /businesses/{businessId}/membership-plans/{planId}` — Update a membership plan (feature `catalog.manage`)
- `POST /businesses/{businessId}/membership-plans/{planId}/publish` — Publish a membership plan (feature `catalog.manage`)
- `POST /businesses/{businessId}/membership-plans/{planId}/unpublish` — Unpublish a membership plan (feature `catalog.manage`)
- `POST /businesses/{businessId}/membership-plans/{planId}/archive` — Archive a membership plan (feature `catalog.manage`)
- `DELETE /businesses/{businessId}/membership-plans/{planId}` — Delete a draft plan (feature `catalog.manage`)
- `POST /businesses/{businessId}/customers/{customerId}/memberships/purchase` — Purchase a membership for a customer (feature `booking.manage`)
- `POST /businesses/{businessId}/memberships/{membershipId}/record-payment` — Record a membership period as paid through a payment method (feature `booking.manage`)
- `GET /businesses/{businessId}/memberships` — List memberships for the operator console (feature `business.view`)
- `POST /businesses/{businessId}/memberships/{membershipId}/email` — Change the email a pass or membership belongs to (feature `booking.manage`)
- `POST /businesses/{businessId}/memberships/{membershipId}/cancel` — Cancel a membership (feature `booking.manage`)
- `DELETE /businesses/{businessId}/memberships/{membershipId}/cancel` — Keep a membership — take back a cancel at period end (feature `booking.manage`)
- `POST /businesses/{businessId}/memberships/{membershipId}/renew` — Try the card again on a past-due membership (feature `booking.manage`)
- `POST /businesses/{businessId}/memberships/{membershipId}/spots/quote` — Quote a change to a subscription's spots (feature `booking.manage`)
- `POST /businesses/{businessId}/memberships/{membershipId}/spots` — Change a subscription's spots (feature `booking.manage`)
- `POST /businesses/{businessId}/memberships/{membershipId}/card-link` — Email the holder a link to update the card on file (feature `booking.manage`)
- `POST /businesses/{businessId}/memberships/{membershipId}/pause` — Pause a membership (feature `booking.manage`)
- `POST /businesses/{businessId}/memberships/{membershipId}/resume` — Resume a paused membership (feature `booking.manage`)
- `POST /businesses/{businessId}/pricing/quote` — Quote a listing or a product (feature `booking.view`)
- `GET /businesses/{businessId}/pricing/access-check` — Check a customer’s access to an offering (feature `booking.view`)
- `POST /businesses/{businessId}/membership-plans/card/preview` — Preview an unsaved plan's card (feature `catalog.manage`)
- `POST /businesses/{businessId}/membership-plans/{planId}/card/preview` — Preview a plan's card (feature `catalog.manage`)
- `GET /businesses/{businessId}/membership-plans/{planId}/card` — Get a plan's card images (feature `business.view`)
- `GET /businesses/{businessId}/memberships/{membershipId}/card.svg` — Get a holder's card (feature `business.view`)
- `POST /businesses/{businessId}/membership-plans/{planId}/card/redesign` — Propose a plan's card design (feature `catalog.manage`)
- `POST /businesses/{businessId}/membership-plans/card/redesign` — Propose a card design for an unsaved plan (feature `catalog.manage`)
- `POST /membership-plans/{id}/images` — Upload a membership plan photo (feature `catalog.manage`)
- `GET /membership-plans/{id}/images` — List membership plan photos (feature `business.view`)

#### waitlist — Waitlists for full dates

- `POST /businesses/{businessId}/waitlist/join` — Join the waitlist for a date (feature `booking.manage`)
- `GET /businesses/{businessId}/waitlist/{entryId}` — Get a waitlist entry (feature `booking.view`)
- `GET /businesses/{businessId}/occurrences/{occurrenceId}/waitlist` — List waitlist entries for a date (feature `booking.view`)
- `POST /businesses/{businessId}/occurrences/{occurrenceId}/waitlist/process-expired` — Process expired waitlist offers (feature `booking.manage`)

#### chat — Operator chat — an LLM agent over the intent tools

- `GET /me/chat-llm` — List chat model providers
- `POST /businesses/{businessId}/chat` — Ask: send a message (feature `booking.view`)
- `POST /me/setup-chat` — Ask (setup): send a message
- `POST /me/setup-chat/{sessionId}/confirm` — Confirm a setup proposal
- `POST /me/setup-chat/{sessionId}/preview` — Ask (setup): render the page being built
- `GET /me/setup-chat` — Resume the latest setup conversation
- `GET /me/setup-chat/{sessionId}` — Ask (setup): read the draft
- `PATCH /me/setup-chat` — Type the setup answers
- `POST /me/setup-chat/{sessionId}/commit` — Go live from the setup draft
- `POST /me/setup-chat/{sessionId}/apply-site` — Apply the website find to the setup page
- `POST /businesses/{businessId}/chat/{sessionId}/confirm` — Confirm a proposed destructive action (feature `booking.view`)
- `POST /businesses/{businessId}/chat/{sessionId}/decline` — Decline a proposed destructive action (feature `booking.view`)
- `GET /businesses/{businessId}/chat/sessions` — List chat sessions (feature `booking.view`)
- `GET /businesses/{businessId}/chat/sessions/{sessionId}` — Get a chat transcript (feature `booking.view`)
- `DELETE /businesses/{businessId}/chat/sessions/{sessionId}` — Archive a chat session (feature `booking.view`)
- `POST /businesses/{businessId}/inline-ai/listing` — Propose offering form values from plain English (feature `catalog.manage`)
- `POST /businesses/{businessId}/inline-ai/plan` — Propose membership or pass form values from plain English (feature `catalog.manage`)
- `POST /businesses/{businessId}/inline-ai/embed-css` — Propose a revised embed stylesheet from plain English (feature `location.manage`)
- `POST /businesses/{businessId}/inline-ai/format-text` — Clean up the formatting of a document (feature `location.manage, business.manage, team.manage, or booking.manage`)
- `POST /businesses/{businessId}/inline-ai/listing-mark` — Pick a listing’s icon and colour from its name (feature `catalog.manage`)
- `POST /businesses/{businessId}/inline-ai/rewrite-text` — Write a description in the business’s voice (feature `catalog.manage, location.manage, business.manage, team.manage, or booking.manage`)

### Storefront API

#### storefront — Public embeddable booking surface

- `GET /storefront/carts/{token}/agreements` — What the signed-in customer has agreed to, for this cart
- `GET /storefront/offerings/{offeringId}/agreements` — What the signed-in customer has agreed to, for this listing
- `GET /storefront/slugs/{slug}` — Resolve a root slug to a business or location
- `GET /storefront/slugs/{locationSlug}/live` — Get a location’s live walk-in projection
- `GET /storefront/slugs/{locationSlug}/{listingSlug}` — Resolve a location + offering slug pair
- `GET /storefront/businesses/{businessId}` — Get a business page
- `GET /storefront/locations/{locationId}` — Get a location page
- `GET /storefront/locations/{locationId}/offerings` — List published offerings at a location
- `GET /storefront/offerings/{id}` — Get a published offering
- `GET /storefront/offerings/{id}/series` — List published series for an offering
- `GET /storefront/offerings/{id}/availability` — Get a published offering’s availability
- `POST /storefront/offerings/{id}/quote` — Quote a published offering
- `POST /storefront/offerings/{id}/waitlist` — Join a full date's waitlist
- `POST /storefront/offerings/{id}/subscription-waitlist` — Join a full subscription's waitlist
- `POST /storefront/waitlist/leave` — Leave a waitlist
- `POST /storefront/carts` — Create a cart
- `GET /storefront/carts/{token}` — Get a cart by token
- `GET /storefront/carts/{token}/answer-suggestions` — Remembered answers for this cart
- `GET /storefront/offerings/{offeringId}/answer-suggestions` — Last time, for the Book sheet
- `POST /storefront/carts/{token}/items` — Add an item to a cart
- `DELETE /storefront/carts/{token}/items` — Empty a cart
- `DELETE /storefront/carts/{token}/items/{itemId}` — Remove an item from a cart
- `PUT /storefront/carts/{token}/items/{itemId}/answers` — Set a cart line's answers
- `POST /storefront/carts/{token}/cancel` — Cancel a cart
- `POST /storefront/carts/{token}/holds` — Extend or re-acquire cart holds
- `POST /storefront/carts/{token}/settle` — Settle a cart from its provider’s record
- `POST /storefront/carts/{token}/card-session` — Open the cart’s card fields (TRX)
- `POST /storefront/carts/{token}/checkout` — Check out a cart
- `GET /storefront/bookings/{bookingId}` — Get a booking by manage-link id
- `GET /storefront/bookings/{bookingId}/availability` — Availability for rescheduling a booking
- `POST /storefront/bookings/{bookingId}/cancel` — Cancel a booking via manage link
- `POST /storefront/bookings/{bookingId}/reschedule` — Reschedule a booking via manage link
- `POST /storefront/bookings/{bookingId}/feedback` — Rate booking online, from a one-item receipt
- `POST /storefront/carts/{token}/feedback` — Rate booking online, from a receipt of several
- `POST /storefront/membership-plans/{planId}/checkout` — Buy a membership plan
- `POST /storefront/memberships/{membershipId}/cancel` — Cancel a membership at the period end
- `POST /storefront/memberships/{membershipId}/spots/quote` — Quote a change to my subscription's spots
- `POST /storefront/memberships/{membershipId}/spots` — Change my subscription's spots
- `DELETE /storefront/memberships/{membershipId}/cancel` — Keep a membership — take back a cancel at the period end
- `POST /storefront/memberships/{membershipId}/card-session` — Open the update-card page’s card session
- `POST /storefront/memberships/{membershipId}/card` — Save a new card on a membership
- `PUT /storefront/carts/{token}/code` — Add or remove a cart's code
- `GET /storefront/bookings/{bookingId}/pieces` — Get a booking's pieces by manage link
- `POST /storefront/bookings/{bookingId}/pieces` — Add a piece from the booking page
- `DELETE /storefront/bookings/{bookingId}/pieces/{pieceId}` — Take back a piece from the booking page

#### me — Customer self-service for the signed-in person

- `POST /me/google-calendar/complete` — Finish connecting a Google Calendar
- `GET /me/context` — Boot context for the signed-in person
- `POST /me/enrollments/{enrollmentId}/cancel` — Cancel my series enrollment
- `GET /me/profile` — Get my details
- `PATCH /me/profile` — Update my details
- `GET /me/customers` — List my customer relationships
- `PATCH /me/customers/{customerId}` — Update my mobile at a studio
- `GET /me/marketing-consents` — List my marketing email preferences
- `PATCH /me/marketing-consents/{businessId}` — Update marketing email preference for one business
- `GET /me/bookings` — My bookings
- `GET /me/memberships` — List my memberships
- `GET /me/subscriptions` — My subscriptions to a listing
- `POST /me/bookings/{bookingId}/cancel` — Cancel my booking
- `POST /me/bookings/{bookingId}/reschedule` — Reschedule my booking
- `POST /me/meta/complete` — Finish Meta’s return and list Pages

## Agents

MCP (Streamable HTTP): POST https://placefull.ai/mcp · server card: https://placefull.ai/.well-known/mcp.json · agent guide: https://placefull.ai/llms.txt
