Run a gym or studio on TeamUp: customers, the class schedule, attendance, memberships and invoices, instructors, venues and front-desk check-ins.
TeamUp ships in the w6w first-party pack. It declares 29 actions, 2 health checks, and the host runs its code in a sandbox that never sees the credential.
io.w6w.teamupTeamUp is the scheduling and member-management system a gym, studio or fitness business runs on, and this app covers the day-to-day it is asked to answer for: who the customers are, what is on the timetable, who is actually coming, and what they are paying for it.
The class side is a full loop. A workflow can read the schedule with the filters that matter — venue, instructor, offering type, category, occupancy, and both the absolute and local time windows — create an event, register a customer for it (optionally against a specific membership, or comped), unregister them, and manage the waiting list on both ends, including the reserved-spot state TeamUp puts a freed place into. Attendance reads back the same relationship as a record, with its own status vocabulary, so a no-show follow-up is a filter rather than a calculation.
The membership side separates the sellable plan from the instance a customer holds: list and read the plans (packs, recurring plans, prepaid plans, drop-ins) and their pricing and allotments, then list and read a customer’s own memberships with their holds, renewal and billing dates, and assign one. Invoices and front-desk check-ins close the loop on money and visits, and the business’s own vocabulary — instructors, venues and their rooms, staff, courses and their sessions, providers and offering types — is readable so downstream steps speak the same language the TeamUp account does.
Everything here talks to the same public v2 API the TeamUp dashboard uses, over one M2M token issued for the business, so a workflow can act on a real gym’s customers and schedule without hand-rolling calls against TeamUp’s own reference.
Three routes to the same 29 actions. The Workflow tab is generated from TeamUp's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.
attendances-get Fetch one attendance by id: the customer, the event, the status and the membership that paid (GET /api/v2/attendances/{id}).
attendances-list List the bookings connecting customers to events, filtered by customer, event, venue, status and event time (GET /api/v2/attendances).
checkins-create Record a front-desk visit for a customer at a venue, against a membership or comped (POST /api/v2/checkins).
course-sessions-list List the dated occurrences inside courses, filtered by course, venue, instructor and time (GET /api/v2/course_sessions).
courses-list List multi-session courses, optionally only the published ones (GET /api/v2/courses).
customer-memberships-create Give a customer one of the business's membership plans, with an optional start date and payment plan (POST /api/v2/customer_memberships).
customer-memberships-get Fetch one customer's membership by id: status, dates, the plan, billing and any hold (GET /api/v2/customer_memberships/{id}).
customer-memberships-list List the memberships customers hold, filtered by customer, plan, status, dates and holds (GET /api/v2/customer_memberships).
customers-create Create a customer with the five fields TeamUp documents, optionally pinning a venue and setting custom fields (POST /api/v2/customers).
customers-get Fetch one customer by id, with the full Customer object TeamUp returns (GET /api/v2/customers/{id}).
customers-list Search the business's customers by status, free text, ids, age and family or membership flags (GET /api/v2/customers).
events-create Put a class on the schedule: times, name, venue, offering type and instructors, with optional capacity and registration settings (POST /api/v2/events).
events-get Fetch one event by id: the schedule entry, its registration window, occupancy and instructors (GET /api/v2/events/{id}).
events-join-waitlist Queue a customer for a full event and return the waitlist spot TeamUp creates (POST /api/v2/events/{id}/join_waitlist).
events-leave-waitlist Remove a customer's waitlist spot for one event (POST /api/v2/events/{id}/leave_waitlist).
events-list Read the class schedule, filtered by venue, instructor, offering type, category, time window and occupancy (GET /api/v2/events).
events-register Register a customer for one event, optionally against a specific membership or comped (POST /api/v2/events/{id}/register).
events-unregister Take a customer off one event, recording whether it counts as a late cancellation (POST /api/v2/events/{id}/unregister).
instructors-get Fetch one instructor by id: the public profile, its linked staff record, permissions and availability (GET /api/v2/instructors/{id}).
instructors-list List the people who teach, filtered by event, class type, content collection or a loose search (GET /api/v2/instructors).
invoices-get Fetch one invoice by id: its status, due date, amount due, line items, discounts, taxes and receipt (GET /api/v2/invoices/{id}).
invoices-list List invoices by status and billing source — a customer membership or a store order (GET /api/v2/invoices).
memberships-get Fetch one membership plan by id, with its pricing, duration, allotment and payment plans (GET /api/v2/memberships/{id}).
memberships-list List the sellable membership plans and packs, filtered by category, offering type, drop-in status and availability (GET /api/v2/memberships).
offering-types-list List the class and session types a business sells — Yoga, Spin, Personal Training — with the filters that resolve them (GET /api/v2/offering_types).
providers-list List the businesses and locations this M2M token can reach — where the providerId values come from (GET /api/v2/providers).
staff-list List the people with an account on this business, optionally filtered by the permissions they hold (GET /api/v2/staff).
venues-get Fetch one venue by id: its address, timezone, rooms and whether it is a physical or online location (GET /api/v2/venues/{id}).
venues-list List the business's physical and online locations, optionally only those with sessions scheduled (GET /api/v2/venues).
A workflow step names the app and the action, and the editor fills in the
connection when you pick one. This is the Step shape from the
workflow spec, carrying TeamUp's real ids.
{
"manifestVersion": "2",
"name": "teamup-example",
"steps": [
{
"id": "attendances-get",
"uses": {
"app": "io.w6w.teamup",
"action": "attendances-get",
"connection": "conn_YOUR_CONNECTION_ID"
},
"with": {
"id": "<id>"
}
}
]
}attendances-get attendances-list checkins-create course-sessions-list courses-list +24 more actions available
Every app-specific value here is a blank you have to fill in. An
app action is reached through the connection that authenticates it, so the
address is a connection id, not the app id — and connections belong to your account,
so a public page cannot know yours. Create one for TeamUp, then fill in
the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the
parameters that action declares. The call itself is real — the shape is transcribed
from the studio's own snippet builder, which prints the same kind of blanks — but
nothing in it is specific to TeamUp. The Workflow tab is where this app's
real ids are.
npm install @w6w/sdkyarn add @w6w/sdkpnpm add @w6w/sdkdeno add npm:@w6w/sdkimport { W6wClient, isActionRun } from "@w6w/sdk";
// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();
const envelope = await client.run({
urn: "conn_YOUR_CONNECTION_ID",
action: "attendances-get",
payload: {
id: "<value>",
// expand: "<value>",
// fields: "<value>",
// format: "<value>",
// providerId: "<value>",
},
});
if (isActionRun(envelope)) console.log(envelope.value); npm install -g @w6w/cli w6w run conn_YOUR_CONNECTION_ID --action attendances-get --payload '{"id":"<value>"}' Give an AI agent TeamUp — without giving it TeamUp's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.
One tool call{
"name": "w6w_invoke",
"arguments": {
"ref": "app:io.w6w.teamup#attendances-get",
"input": {
"id": "<id>"
}
}
}
Every tool names its target with a single ref. The
app: form above doesn't name a connection at all — the
host resolves which of the caller's TeamUp connections to sign
with, and refuses rather than guesses when the answer is ambiguous.
The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.
Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.
Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.
TeamUp's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.
The MCP surface is part of the hosted platform. TeamUp itself is MIT, and the runtime that executes it is source-available (FSL).
TeamUp declares its own checks, so its health is a property of the app rather than something the host guesses at.
Unauthenticated request to the documented API on goteamup.com. A 401/403 is a pass — it proves the host is serving; credential validity is the `auth:token` check's question. TeamUp's own status page is abandoned (expired certificate, untouched template component names), so there is no `service` check in this app.