# Cultcha developer docs: MCP server and REST API

> Cultcha is a point of sale, membership and booking platform for gyms, studios, cafes, climbing gyms and kids activity venues. It has a hosted MCP server and a REST API on every plan. AI assistants sign in with OAuth 2.1 and act as the person who connected them; scripts use that person's personal token. Web version: https://cultcha.app/docs

## Quickstart

1. Add the MCP server URL to your AI assistant as a custom connector: `https://cultcha.app/api/mcp`. There is no key to copy: the assistant opens Cultcha, you sign in and approve it.
2. Ask it something, for example "How many active members do we have, and how many joined this month?"
3. Or call the REST API from a script with a personal token, made on the Developers page (https://cultcha.app/developers) once signed in. Tokens are made by managers and admins.

## Connect an AI app

### Claude

1. In claude.ai or the Claude app, open Settings → Connectors → Add custom connector.
2. Name it Cultcha and paste the server URL. Leave the advanced settings empty.
3. Click Connect, sign in to Cultcha, choose the access and click Allow.

### ChatGPT

1. Turn on developer mode: Settings → Apps & Connectors → Advanced settings → Developer mode.
2. Apps & Connectors → Create. Name it Cultcha, paste the server URL and set Authentication to OAuth.
3. ChatGPT opens Cultcha: sign in, choose the access and click Allow.

### Microsoft Copilot Studio

1. Open the agent: Tools → Add a tool → New tool → Model Context Protocol.
2. Paste the server URL. For authentication choose OAuth 2.0, then Dynamic discovery.
3. Create the connection when asked: sign in to Cultcha and click Allow, then publish the agent.

### Claude Code

```sh
claude mcp add --transport http cultcha https://cultcha.app/api/mcp
```

### Cursor · ~/.cursor/mcp.json

```json
{
  "mcpServers": {
    "cultcha": {
      "url": "https://cultcha.app/api/mcp"
    }
  }
}
```

### VS Code · .vscode/mcp.json

```json
{
  "servers": {
    "cultcha": {
      "type": "http",
      "url": "https://cultcha.app/api/mcp"
    }
  }
}
```

Each client asks you to sign in the first time it connects (in Claude Code, run `/mcp` and choose Authenticate). A client that can only send a fixed key can send a personal token in an `X-API-Key` header instead.

## Authentication

### AI apps: OAuth 2.1

- Authorization code flow with PKCE (`S256` only). No implicit or password grants.
- Clients register themselves through dynamic client registration (RFC 7591); public clients need no secret.
- An unauthenticated MCP request gets `401` with a `WWW-Authenticate` header naming the protected-resource metadata (RFC 9728), so clients find the sign-in on their own.
- Access tokens (`cultcha_at_…`) last 24 hours. Refresh tokens (`cultcha_rt_…`) last 30 days from their last use and rotate on every refresh; reusing an old refresh token ends the connection.

### Scripts: personal tokens

- Made on the Developers page by a manager or admin, shown once, and stored only as a hash. Format: `cultcha_pat_…`.
- Send it as `Authorization: Bearer cultcha_pat_…`. The same token works for the REST API and the MCP server.
- Keep it in an environment variable or a secret manager, never in code.

### Scopes and permissions

| Scope | Allows |
|---|---|
| `read` | Read what the person can see. MCP clients see only the read-only tools. |
| `write` | Also create and change what the person can, through the `request` tool or the REST API. |

Every connection acts as the person who made it: one business, their role's access, nothing more. No token can issue refunds, manage staff, or create further tokens. Removing the person, or revoking the connection, stops it at once.

## MCP server

- URL: `https://cultcha.app/api/mcp`
- Transport: streamable HTTP, stateless (one JSON-RPC request per POST, answered in full).
- Protocol versions: 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05.
- Every tool except `request` is annotated read-only; `request` is annotated destructive, so clients ask before it runs.

### Tools

| Tool | What it does | Access |
|---|---|---|
| `get_schema` | Get the data model. The database schema: every collection, its fields and types, its primary key, and how it relates to the others. | read |
| `get_api_reference` | Get the API reference. The full OpenAPI spec — every endpoint, parameter and response. | read |
| `query` | Query the data. Answer any question about the org's data — the general-purpose read. | read |
| `list_endpoints` | Find an endpoint. Every API endpoint this person can call — use it to find how to make a change. | read |
| `list_products` | List products. The org's products: shop items, classes, courses, memberships, packages, passes and gift cards. | read |
| `get_product` | Get a product. One product by id, including its variations and mods. | read |
| `list_customers` | List guests. Guests and members, paginated. | read |
| `get_customer` | Get a guest. One guest with their memberships, credit, waiver status and recent activity. | read |
| `list_transactions` | List sales. Sales, refunds and invoices — the raw source behind every revenue figure. | read |
| `list_checkins` | List attendance. Check-ins: who came in, when, and how they were admitted. | read |
| `list_memberships` | List memberships. Recurring memberships with their plan, billing date and arrears. | read |
| `list_sessions` | List sessions. Scheduled class and course sessions in a date range, with capacity and how many are booked. | read |
| `get_report` | Run a report. A pre-aggregated report — the shortest path to a number. | read |
| `search` | Search. Search the org across guests, products and sales. | read |
| `fetch` | Fetch a record. Fetch one record by an id from search. | read |
| `request` | Call any endpoint. Call any cultcha endpoint directly — how changes are made. | read + write |

### Call a tool from a script

```sh
curl -s https://cultcha.app/api/mcp \
  -H "Authorization: Bearer $CULTCHA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"get_report","arguments":{"report":"memberships"}}}'
```

## REST API

- Base URL: `https://cultcha.app`
- JSON in and out. Money is in dollars, not cents. Dates are ISO 8601 in UTC.
- List endpoints take `page` and `limit`.
- Contract: OpenAPI 3.1 at https://cultcha.app/api/openapi.json (imports into Postman, Insomnia or a ChatGPT action).
- Signed in, the `list_endpoints` MCP tool searches every endpoint the person can call, several hundred in all.

### curl

```sh
curl -s "https://cultcha.app/api/memberships?status=active" \
  -H "Authorization: Bearer $CULTCHA_TOKEN"
```

### JavaScript

```js
const res = await fetch('https://cultcha.app/api/memberships?status=active', {
  headers: { Authorization: `Bearer ${process.env.CULTCHA_TOKEN}` },
})
if (!res.ok) throw new Error((await res.json()).error)
const memberships = await res.json()
```

### Python

```python
import os, requests

res = requests.get(
    "https://cultcha.app/api/memberships",
    params={"status": "active"},
    headers={"Authorization": f"Bearer {os.environ['CULTCHA_TOKEN']}"},
    timeout=30,
)
res.raise_for_status()
memberships = res.json()
```

### Endpoints in the spec

#### Products

- `GET /api/products`: List products
- `POST /api/products`: Create a product
- `GET /api/products/{id}`: Get a product
- `PUT /api/products/{id}`: Update a product
- `DELETE /api/products/{id}`: Soft-delete a product

#### Customers

- `GET /api/customers`: List customers (paginated)
- `POST /api/customers`: Create a customer

#### Transactions

- `GET /api/transactions`: List transactions
- `POST /api/transactions`: Record a transaction
- `GET /api/transactions/{id}`: Get a transaction
- `PUT /api/transactions/{id}`: Update a transaction (e.g. record a refund)

#### Check-ins

- `GET /api/checkins`: List check-ins

#### Sessions

- `GET /api/schedules`: List class/course sessions
- `POST /api/schedules`: Create a session
- `GET /api/schedules/{id}`: Get a session (with attendees)

#### Memberships

- `GET /api/memberships`: List memberships

#### Bookings

- `GET /api/group-bookings`: List group/package bookings
- `POST /api/group-bookings`: Create a group booking
- `GET /api/group-bookings/{id}`: Get a booking
- `PUT /api/group-bookings/{id}`: Update a booking
- `DELETE /api/group-bookings/{id}`: Cancel a booking

#### Adjustments

- `GET /api/adjustments`: List discounts & surcharges
- `POST /api/adjustments`: Create an adjustment
- `GET /api/adjustments/{id}`: Get an adjustment
- `PUT /api/adjustments/{id}`: Update an adjustment
- `DELETE /api/adjustments/{id}`: Delete an adjustment

#### Gift Cards

- `GET /api/gift-cards`: List gift cards
- `GET /api/gift-cards/{id}`: Get a gift card
- `PUT /api/gift-cards/{id}`: Update a gift card

#### Passes

- `GET /api/passes`: List prepaid / general-entry passes

#### Reports

- `GET /api/reports/payments`: Payments report (by method / section)
- `GET /api/reports/product-sales`: Product sales report
- `GET /api/reports/class-attendance`: Class/course attendance report
- `GET /api/reports/transaction-history`: Transaction history — line-item ledger with accounting codes
- `GET /api/reports/accounting-by-department`: Accounting summary — qty, revenue inc GST, GST and revenue ex GST per accounting code or tag
- `GET /api/reports/accounting-by-payment-method`: Accounting by payment method — revenue, fees, tax and profit per tender
- `GET /api/reports/bookings`: Bookings report
- `GET /api/reports/members`: Members report
- `GET /api/reports/discounts`: Discounts report
- `GET /api/reports/segmentation`: Customer segmentation report
- `GET /api/reports/promo-links`: Promo-link performance report

## Data model

MongoDB collections, each row scoped to one business. The primary key is always `_id`; relationships are ObjectId references. The full schema, with every field, is the `get_schema` MCP tool.

- **Customer**: A guest / member. The person who books, buys and checks in.
- **Membership**: A recurring plan held by a customer: status, price, billing cadence, arrears.
- **Transaction**: A sale, refund or invoice. `cart` holds the line items.
- **Product**: Anything sellable, told apart by `type`: shop, class, course, membership, prepaid, package, general, gift_card.
- **Schedule**: One class/course session at a time and place, with its attendees.
- **Checkin**: One attendance record — a guest admitted to a session or on a pass.
- **CustomerPass**: A guest's own pass bought from a PrepaidPack, with its remaining balance.
- **PrepaidPack**: A pack of visits or items sold up front (the product a CustomerPass comes from).
- **GiftCard**: A gift card or promo/checkout link, told apart by `kind`.
- **Location**: A venue (site). Products, sessions and devices belong to one.
- **Employee**: A staff member, with a role: STAFF, FINANCE, MANAGER, ADMIN.
- **Segment**: A saved, rule-driven group of guests. Rules are re-evaluated live.
- **Campaign**: A marketing message sent by email or push to an audience.
- **Form**: A staff-built form (waiver extras, intake questions).
- **FormResponse**: One completed form, answered by a guest.

## Errors and limits

Errors are JSON, `{ "error": "…" }`, with a standard status code:

- `400`: The request didn’t validate; the message says why.
- `401`: Missing, expired or revoked token. Sign in again or use a current token.
- `403`: The token’s owner can’t do this, or the token is read-only.
- `404`: No such record in this business.

MCP errors follow JSON-RPC 2.0, with an `error` object in place of `result`. Use the API at the pace a person would; for bulk access or higher volumes, contact hello@cultcha.app first.

## Discovery URLs

- Protected resource metadata (RFC 9728): https://cultcha.app/.well-known/oauth-protected-resource/api/mcp
- Authorization server metadata (RFC 8414): https://cultcha.app/.well-known/oauth-authorization-server
- Dynamic client registration (RFC 7591, POST): https://cultcha.app/api/oauth/register
- Authorization endpoint: https://cultcha.app/oauth/authorize
- Token endpoint (POST): https://cultcha.app/api/oauth/token
- Revocation endpoint (RFC 7009, POST): https://cultcha.app/api/oauth/revoke
- OpenAPI 3.1 spec: https://cultcha.app/api/openapi.json
- These docs as Markdown: https://cultcha.app/docs.md
- Summary for AI tools: https://cultcha.app/llms.txt
- Full text for AI tools: https://cultcha.app/llms-full.txt

## FAQ

### Do I need an API key to connect an AI assistant?

No. Claude, ChatGPT, Copilot Studio, Cursor and VS Code all sign in with OAuth: add the server URL, sign in to Cultcha and approve the access. Personal tokens are only for scripts and tools that can’t sign in.

### What can a connection see and do?

Exactly what the person who connected it can, in their one business, and nothing more. A read connection can only look. A read-and-change connection can also create and update, but no connection can issue refunds, manage staff, or create further tokens or connections.

### How do I revoke access?

On the Developers page in Cultcha, disconnect the app or delete the token and it stops working at once. An admin can also revoke anyone’s connections at the business, and everything a person made stops when their access to the business is removed.

### Which MCP protocol versions are supported?

The server speaks MCP over streamable HTTP and negotiates versions 2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05. It is stateless: each JSON-RPC request is answered in full, so there is no session to keep alive.

### Who can create tokens?

Managers and admins, from the Developers page once signed in. A token acts as the person who made it, so it can never reach further than their own role.

### Does Cultcha send webhooks?

Not yet. To react to changes, poll the REST API (for example transactions or check-ins filtered by date), or ask an AI assistant connected over MCP. Payments themselves are processed by the business’s own Stripe account, which can send Stripe’s webhooks to your systems.

### Is there a sandbox?

There is no public sandbox. Make a read-only token first to explore safely; a read token cannot change anything.

### Is there an SDK?

No official SDK. The OpenAPI 3.1 spec generates a typed client in most languages, and the MCP server works with any MCP client without code.

## Support

Email hello@cultcha.app or use https://cultcha.app/contact.
