Developer docs
Build on Cultcha with AI or code
A hosted MCP server and a REST API, on every plan. AI assistants sign in with OAuth and act as the person who connected them; scripts use that person’s own token.
Quickstart
- Connect an AI assistant. Add this server URL as a custom connector. There’s no key to copy: your assistant opens Cultcha, you sign in and approve it.Server URL
https://cultcha.app/api/mcp
- Ask it something. “How many active members do we have, and how many joined this month?”
- Or call the API from a script with a personal token, made on the Developers page once you’re signed in.
Connect an AI app
Claude
- In claude.ai or the Claude app, open Settings → Connectors → Add custom connector.
- Name it Cultcha and paste the server URL. Leave the advanced settings empty.
- Click Connect, sign in to Cultcha, choose the access and click Allow.
ChatGPT
- Turn on developer mode: Settings → Apps & Connectors → Advanced settings → Developer mode.
- Apps & Connectors → Create. Name it Cultcha, paste the server URL and set Authentication to OAuth.
- ChatGPT opens Cultcha: sign in, choose the access and click Allow.
Microsoft Copilot Studio
- Open the agent: Tools → Add a tool → New tool → Model Context Protocol.
- Paste the server URL. For authentication choose OAuth 2.0, then Dynamic discovery.
- Create the connection when asked: sign in to Cultcha and click Allow, then publish the agent.
Clients configured in a file or a terminal:
claude mcp add --transport http cultcha https://cultcha.app/api/mcp
{
"mcpServers": {
"cultcha": {
"url": "https://cultcha.app/api/mcp"
}
}
}{
"servers": {
"cultcha": {
"type": "http",
"url": "https://cultcha.app/api/mcp"
}
}
}Each one asks you to sign in the first time it connects (in Claude Code, run /mcp and choose Authenticate). Clients that can only send a fixed key, such as Copilot Studio with OAuth tools turned off, can send a personal token as an X-API-Key header instead.
Authentication
AI apps: OAuth 2.1
- Authorization code flow with PKCE (
S256only). No implicit or password grants. - Clients register themselves through dynamic client registration; public clients need no secret.
- An unauthenticated MCP request gets
401with aWWW-Authenticateheader naming the protected-resource metadata, 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, since it means someone else has a copy.
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 or a shared document.
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 on the Developers page, stops it at once.
MCP tools
Tools carry MCP annotations: every tool but request is marked read-only, and request is marked destructive, so clients ask before it runs. Assistants are told to confirm any change with you first.
| 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 |
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. The full contract is the OpenAPI 3.1 spec, which imports into Postman, Insomnia or a ChatGPT action.
curl -s "https://cultcha.app/api/memberships?status=active" \ -H "Authorization: Bearer $CULTCHA_TOKEN"
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()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()Products
- GET
/api/productsList products - POST
/api/productsCreate 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/customersList customers (paginated) - POST
/api/customersCreate a customer
Transactions
- GET
/api/transactionsList transactions - POST
/api/transactionsRecord 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/checkinsList check-ins
Sessions
- GET
/api/schedulesList class/course sessions - POST
/api/schedulesCreate a session - GET
/api/schedules/{id}Get a session (with attendees)
Memberships
- GET
/api/membershipsList memberships
Bookings
- GET
/api/group-bookingsList group/package bookings - POST
/api/group-bookingsCreate 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/adjustmentsList discounts & surcharges - POST
/api/adjustmentsCreate 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-cardsList gift cards - GET
/api/gift-cards/{id}Get a gift card - PUT
/api/gift-cards/{id}Update a gift card
Passes
- GET
/api/passesList prepaid / general-entry passes
Reports
- GET
/api/reports/paymentsPayments report (by method / section) - GET
/api/reports/product-salesProduct sales report - GET
/api/reports/class-attendanceClass/course attendance report - GET
/api/reports/transaction-historyTransaction history — line-item ledger with accounting codes - GET
/api/reports/accounting-by-departmentAccounting summary — qty, revenue inc GST, GST and revenue ex GST per accounting code or tag - GET
/api/reports/accounting-by-payment-methodAccounting by payment method — revenue, fees, tax and profit per tender - GET
/api/reports/bookingsBookings report - GET
/api/reports/membersMembers report - GET
/api/reports/discountsDiscounts report - GET
/api/reports/segmentationCustomer segmentation report - GET
/api/reports/promo-linksPromo-link performance report
Signed in, the list_endpoints tool searches every endpoint the person can call, several hundred in all, including the ones not listed here.
Data model
MongoDB collections, each row scoped to one business. The primary key is always _id, and relationships are ObjectId references. Signed in, the get_schema tool returns every field, and query runs find, count or aggregate on them, limited to what the person can see.
- 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
errorobject in place ofresult.
Use the API at a pace a person would. Need bulk access or higher volumes? Talk to us first.
Discovery URLs
For client builders: everything an MCP or OAuth client needs to configure itself.
- Protected resource metadata (RFC 9728)/.well-known/oauth-protected-resource/api/mcp
- Authorization server metadata (RFC 8414)/.well-known/oauth-authorization-server
- Dynamic client registration (RFC 7591, POST)
/api/oauth/register - Authorization endpoint/oauth/authorize
- Token endpoint (POST)
/api/oauth/token - Revocation endpoint (RFC 7009, POST)
/api/oauth/revoke - OpenAPI 3.1 spec/api/openapi.json
- These docs as Markdown/docs.md
- Summary for AI tools/llms.txt
- Full text for AI tools/llms-full.txt
Frequently asked questions
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.
Ready to connect?
Add the server URL to your assistant, or sign in to make a token for a script.
New to Cultcha? See what AI can do with it.