REST API reference
Zen Planner API
14 endpoints for Zen Planner. Each one is a POST with a JSON body, called with your API key.
- Base URL
- https://cotlet.dev/api/v1/zen-planner
- Connects with
- Your own Zen Planner Studio staff account (the role must be allowed to see members, billing and reports)
- Integration page
- Zen Planner
| Endpoint | Access | Description |
|---|---|---|
| list_members | read | People in your studio with status, email, phone and memberships. |
| get_member | read | Full profile: contact details, memberships and family members. |
| list_classes | read | Class schedule with time, instructor, capacity and open spots. |
| get_class_roster | read | Who reserved and who checked in for one class. |
| list_attendance | read | A member's class check-ins in a date range, newest first. |
| list_prospects | read | Leads with source, status and date added. |
| list_failed_payments | read | Payments that failed, with member, amount, date and reason. |
| get_revenue_report | read | Revenue for a period, grouped by membership type, class, instructor, location or retail. |
| book_class | write | Reserve a spot in a class for a member. |
| cancel_reservation | write | Cancel a member's class reservation. |
| check_in_member | write | Record that a member attended a class. |
| create_prospect | write | Add a lead with contact details and source. |
| enroll_in_membership | write | Add a membership to a member. Billing follows the membership type. |
| promote_rank | write | Move a student to their next belt or rank. |
List members
readPOST https://cotlet.dev/api/v1/zen-planner/list_members
Lists people in your studio, filtered by name or email, status or last change date. Each item has a person_id, contact details and the names of their active memberships. Pages hold up to 200 people; pass next_cursor back as cursor for the next page.
Parameters
| Name | Type | Description |
|---|---|---|
| query | string | Name or email to search for. |
| status | enum | member, prospect, alumni or all. Default: member. |
| modified_after | date | Only people changed on or after this date. |
| limit | integer | 1 to 200. Default: 50. |
| cursor | string | Next page cursor from the previous call. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/list_members \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("zen-planner", "list_members") const result = await cotlet.call('zen-planner', 'list_members'); cotlet call zen-planner list_members Example response
{
"members": [
{
"person_id": "p253ac9b9",
"name": "Sarah Lee",
"status": "member",
"email": "sarah.lee@example.com",
"phone": "+1 555 0142",
"memberships": [
"Unlimited Monthly"
]
}
],
"next_cursor": null
} Get member
readPOST https://cotlet.dev/api/v1/zen-planner/get_member
Returns one person with contact details, their memberships with start dates and the family members linked to the account. Use it to get a phone number or email before contacting someone.
Parameters
| Name | Type | Description |
|---|---|---|
| person_id required | string | Person ID from list_members. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/get_member \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"person_id":"person_8c41d2"}' result = client.call("zen-planner", "get_member", {"person_id":"person_8c41d2"}) const result = await cotlet.call('zen-planner', 'get_member', {"person_id":"person_8c41d2"}); cotlet call zen-planner get_member --data '{"person_id":"person_8c41d2"}' Example response
{
"person_id": "p253ac9b9",
"name": "Sarah Lee",
"email": "sarah.lee@example.com",
"phone": "+1 555 0142",
"memberships": [
{
"membership_id": "ms_3310",
"type": "Unlimited Monthly",
"start_date": "2026-03-01"
}
],
"family": []
} List classes
readPOST https://cotlet.dev/api/v1/zen-planner/list_classes
Returns the classes in a date range in start order, each with class_id, time, instructor, capacity and open spots. Filter by location or program to narrow the list. Use class_id with book_class and get_class_roster.
Parameters
| Name | Type | Description |
|---|---|---|
| from required | date | First day. |
| to | date | Last day. Default: same as from. |
| location_id | string | Only classes at this location. |
| program_id | string | Only classes of this program. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/list_classes \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"2026-10-01"}' result = client.call("zen-planner", "list_classes", {"from":"2026-10-01"}) const result = await cotlet.call('zen-planner', 'list_classes', {"from":"2026-10-01"}); cotlet call zen-planner list_classes --data '{"from":"2026-10-01"}' Example response
{
"classes": [
{
"class_id": "c7e2a91f",
"name": "CrossFit WOD",
"starts_at": "2026-10-12T06:00:00-04:00",
"instructor": "Coach Alex",
"capacity": 12,
"open_spots": 4
}
]
} Get class roster
readPOST https://cotlet.dev/api/v1/zen-planner/get_class_roster
Returns the people who reserved one class, each with a reservation_id and whether they are checked in. Use reservation_id with cancel_reservation and person_id with check_in_member.
Parameters
| Name | Type | Description |
|---|---|---|
| class_id required | string | Class ID from list_classes. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/get_class_roster \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"class_id":"class_8c41d2"}' result = client.call("zen-planner", "get_class_roster", {"class_id":"class_8c41d2"}) const result = await cotlet.call('zen-planner', 'get_class_roster', {"class_id":"class_8c41d2"}); cotlet call zen-planner get_class_roster --data '{"class_id":"class_8c41d2"}' Example response
{
"class_id": "c4d8b1e0",
"name": "Kids Karate",
"starts_at": "2026-10-11T09:00:00-04:00",
"roster": [
{
"reservation_id": "r_5501",
"person_id": "p253ac9b9",
"name": "Ava Lee",
"checked_in": false
},
{
"reservation_id": "r_5502",
"person_id": "p77a1d03e",
"name": "Sam Ortiz",
"checked_in": false
}
]
} List attendance
readPOST https://cotlet.dev/api/v1/zen-planner/list_attendance
Returns the classes one person checked into between two dates, newest first. An empty list means no visits in that range. Run it once per person.
Parameters
| Name | Type | Description |
|---|---|---|
| person_id required | string | Person ID from list_members. |
| from | date | Start date. Default: 30 days ago. |
| to | date | End date. Default: today. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/list_attendance \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"person_id":"p253ac9b9","from":"2026-08-13","to":"2026-10-11"}' result = client.call("zen-planner", "list_attendance", {"person_id":"p253ac9b9","from":"2026-08-13","to":"2026-10-11"}) const result = await cotlet.call('zen-planner', 'list_attendance', {"person_id":"p253ac9b9","from":"2026-08-13","to":"2026-10-11"}); cotlet call zen-planner list_attendance --data '{"person_id":"p253ac9b9","from":"2026-08-13","to":"2026-10-11"}' Example response
{
"person_id": "p253ac9b9",
"attendance": [
{
"class_id": "c3a90b12",
"name": "CrossFit WOD",
"checked_in_at": "2026-10-07T06:02:00-04:00"
}
]
} List prospects
readPOST https://cotlet.dev/api/v1/zen-planner/list_prospects
Lists prospects in your studio, newest first, filtered by status, source or date added. Status values are the ones set up in your studio. Use it to skip leads that already exist before create_prospect.
Parameters
| Name | Type | Description |
|---|---|---|
| status | string | Prospect status as set up in your studio. |
| source | string | Lead source, e.g. Website or Walk-in. |
| since | date | Only prospects added on or after this date. |
| cursor | string | Next page cursor from the previous call. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/list_prospects \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("zen-planner", "list_prospects") const result = await cotlet.call('zen-planner', 'list_prospects'); cotlet call zen-planner list_prospects Example response
{
"prospects": [
{
"person_id": "p9be2c71a",
"name": "Dana Ortiz",
"source": "Open house",
"status": "New",
"added_on": "2026-10-09"
}
],
"next_cursor": null
} List failed payments
readPOST https://cotlet.dev/api/v1/zen-planner/list_failed_payments
Returns the payments Zen Planner marks as failed in a date range, newest first, with member, amount, date and the reason shown in the report. It is not the past-due total, which Zen Planner counts separately. The total is the sum of the listed amounts.
Parameters
| Name | Type | Description |
|---|---|---|
| from | date | Start date. Default: 7 days ago. |
| to | date | End date. Default: today. |
| location_id | string | Only this location. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/list_failed_payments \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"2026-10-05","to":"2026-10-11"}' result = client.call("zen-planner", "list_failed_payments", {"from":"2026-10-05","to":"2026-10-11"}) const result = await cotlet.call('zen-planner', 'list_failed_payments', {"from":"2026-10-05","to":"2026-10-11"}); cotlet call zen-planner list_failed_payments --data '{"from":"2026-10-05","to":"2026-10-11"}' Example response
{
"payments": [
{
"person_id": "p253ac9b9",
"name": "Sarah Lee",
"amount": 129,
"date": "2026-10-08",
"reason": "Card declined"
},
{
"person_id": "p41c7f0d2",
"name": "Marcus Webb",
"amount": 89,
"date": "2026-10-06",
"reason": "Expired card"
}
],
"total": 218,
"currency": "USD"
} Get revenue report
readPOST https://cotlet.dev/api/v1/zen-planner/get_revenue_report
Returns revenue for one date range as Zen Planner reports it, grouped the way you choose. One call covers one period; compare two months with two calls. The total is the sum of the groups.
Parameters
| Name | Type | Description |
|---|---|---|
| from required | date | Start date. |
| to required | date | End date. |
| group_by | enum | membership_type, class, instructor, location or retail. Default: membership_type. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/get_revenue_report \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"2026-10-01","to":"2026-10-01"}' result = client.call("zen-planner", "get_revenue_report", {"from":"2026-10-01","to":"2026-10-01"}) const result = await cotlet.call('zen-planner', 'get_revenue_report', {"from":"2026-10-01","to":"2026-10-01"}); cotlet call zen-planner get_revenue_report --data '{"from":"2026-10-01","to":"2026-10-01"}' Example response
{
"from": "2026-09-01",
"to": "2026-09-30",
"group_by": "membership_type",
"groups": [
{
"name": "Unlimited Monthly",
"revenue": 18450
},
{
"name": "3x Week",
"revenue": 9200
},
{
"name": "Drop-in",
"revenue": 1350
}
],
"total": 29000,
"currency": "USD"
} POST https://cotlet.dev/api/v1/zen-planner/book_class
Reserves one spot in one class for one member and returns a reservation_id. The member is booked as your staff account does it in Zen Planner Studio. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| class_id required | string | Class ID from list_classes. |
| person_id required | string | Person ID from list_members. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/book_class \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"class_id":"c7e2a91f","person_id":"p253ac9b9"}' result = client.call("zen-planner", "book_class", {"class_id":"c7e2a91f","person_id":"p253ac9b9"}) const result = await cotlet.call('zen-planner', 'book_class', {"class_id":"c7e2a91f","person_id":"p253ac9b9"}); cotlet call zen-planner book_class --data '{"class_id":"c7e2a91f","person_id":"p253ac9b9"}' Example response
{
"reservation_id": "r_5510",
"status": "reserved",
"class": {
"name": "CrossFit WOD",
"starts_at": "2026-10-12T06:00:00-04:00",
"instructor": "Coach Alex"
},
"open_spots_left": 3
} POST https://cotlet.dev/api/v1/zen-planner/cancel_reservation
Cancels one reservation, which frees the spot. Get reservation_id from get_class_roster or book_class. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| class_id required | string | Class ID from list_classes. |
| reservation_id required | string | Reservation ID from get_class_roster. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/cancel_reservation \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"class_id":"class_8c41d2","reservation_id":"reservation_8c41d2"}' result = client.call("zen-planner", "cancel_reservation", {"class_id":"class_8c41d2","reservation_id":"reservation_8c41d2"}) const result = await cotlet.call('zen-planner', 'cancel_reservation', {"class_id":"class_8c41d2","reservation_id":"reservation_8c41d2"}); cotlet call zen-planner cancel_reservation --data '{"class_id":"class_8c41d2","reservation_id":"reservation_8c41d2"}' Example response
{
"reservation_id": "r_5510",
"status": "cancelled"
} POST https://cotlet.dev/api/v1/zen-planner/check_in_member
Checks one member into one class, which adds a visit to their attendance. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| class_id required | string | Class ID from list_classes. |
| person_id required | string | Person ID from list_members. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/check_in_member \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"class_id":"class_8c41d2","person_id":"person_8c41d2"}' result = client.call("zen-planner", "check_in_member", {"class_id":"class_8c41d2","person_id":"person_8c41d2"}) const result = await cotlet.call('zen-planner', 'check_in_member', {"class_id":"class_8c41d2","person_id":"person_8c41d2"}); cotlet call zen-planner check_in_member --data '{"class_id":"class_8c41d2","person_id":"person_8c41d2"}' Example response
{
"class_id": "c4d8b1e0",
"person_id": "p253ac9b9",
"status": "checked_in",
"checked_in_at": "2026-10-11T09:04:00-04:00"
} POST https://cotlet.dev/api/v1/zen-planner/create_prospect
Adds one prospect and returns its person_id. If your studio has lead follow-up workflows set up in Zen Planner, a new prospect can start them. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| first_name required | string | First name. |
| last_name required | string | Last name. |
| string | Email address. | |
| phone | string | Phone number. |
| source | string | Lead source, e.g. Open house. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/create_prospect \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"first_name":"Dana","last_name":"Ortiz","email":"dana.ortiz@example.com","phone":"+1 555 0163","source":"Open house"}' result = client.call("zen-planner", "create_prospect", {"first_name":"Dana","last_name":"Ortiz","email":"dana.ortiz@example.com","phone":"+1 555 0163","source":"Open house"}) const result = await cotlet.call('zen-planner', 'create_prospect', {"first_name":"Dana","last_name":"Ortiz","email":"dana.ortiz@example.com","phone":"+1 555 0163","source":"Open house"}); cotlet call zen-planner create_prospect --data '{"first_name":"Dana","last_name":"Ortiz","email":"dana.ortiz@example.com","phone":"+1 555 0163","source":"Open house"}' Example response
{
"person_id": "p9be2c71a",
"status": "created",
"name": "Dana Ortiz",
"source": "Open house"
} POST https://cotlet.dev/api/v1/zen-planner/enroll_in_membership
Adds a membership to a member from a given start date. Billing then follows the terms of that membership type in your studio, so this reaches money. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| person_id required | string | Person ID from list_members. |
| membership_type_id required | string | Membership type, e.g. Unlimited Monthly. |
| start_date | date | Default: today. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/enroll_in_membership \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"person_id":"person_8c41d2","membership_type_id":"membership_type_8c41d2"}' result = client.call("zen-planner", "enroll_in_membership", {"person_id":"person_8c41d2","membership_type_id":"membership_type_8c41d2"}) const result = await cotlet.call('zen-planner', 'enroll_in_membership', {"person_id":"person_8c41d2","membership_type_id":"membership_type_8c41d2"}); cotlet call zen-planner enroll_in_membership --data '{"person_id":"person_8c41d2","membership_type_id":"membership_type_8c41d2"}' Example response
{
"membership_id": "ms_4402",
"person_id": "p253ac9b9",
"type": "Unlimited Monthly",
"start_date": "2026-10-12",
"status": "active"
} POST https://cotlet.dev/api/v1/zen-planner/promote_rank
Records a new rank for a student from your own rank structure, as in Zen Planner's belt and skill tracking. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| person_id required | string | Person ID from list_members. |
| rank required | string | New rank name from your rank structure. |
| promoted_on | date | Promotion date. Default: today. |
Request
curl -X POST https://cotlet.dev/api/v1/zen-planner/promote_rank \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"person_id":"person_8c41d2","rank":"rank"}' result = client.call("zen-planner", "promote_rank", {"person_id":"person_8c41d2","rank":"rank"}) const result = await cotlet.call('zen-planner', 'promote_rank', {"person_id":"person_8c41d2","rank":"rank"}); cotlet call zen-planner promote_rank --data '{"person_id":"person_8c41d2","rank":"rank"}' Example response
{
"person_id": "p77a1d03e",
"rank": "Yellow Belt",
"promoted_on": "2026-10-11",
"status": "promoted"
}