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
Zen Planner Endpoints
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.

POST 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

Parameters: list_members
NameTypeDescription
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
curl -X POST https://cotlet.dev/api/v1/zen-planner/list_members \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("zen-planner", "list_members")
Node.js
const result = await cotlet.call('zen-planner', 'list_members');
CLI
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

read

POST 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

Parameters: get_member
NameTypeDescription
person_id required string Person ID from list_members.

Request

cURL
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"}'
Python
result = client.call("zen-planner", "get_member", {"person_id":"person_8c41d2"})
Node.js
const result = await cotlet.call('zen-planner', 'get_member', {"person_id":"person_8c41d2"});
CLI
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": []
}

POST 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

Parameters: list_classes
NameTypeDescription
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
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"}'
Python
result = client.call("zen-planner", "list_classes", {"from":"2026-10-01"})
Node.js
const result = await cotlet.call('zen-planner', 'list_classes', {"from":"2026-10-01"});
CLI
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
    }
  ]
}

POST 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

Parameters: get_class_roster
NameTypeDescription
class_id required string Class ID from list_classes.

Request

cURL
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"}'
Python
result = client.call("zen-planner", "get_class_roster", {"class_id":"class_8c41d2"})
Node.js
const result = await cotlet.call('zen-planner', 'get_class_roster', {"class_id":"class_8c41d2"});
CLI
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
    }
  ]
}

POST 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

Parameters: list_attendance
NameTypeDescription
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
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"}'
Python
result = client.call("zen-planner", "list_attendance", {"person_id":"p253ac9b9","from":"2026-08-13","to":"2026-10-11"})
Node.js
const result = await cotlet.call('zen-planner', 'list_attendance', {"person_id":"p253ac9b9","from":"2026-08-13","to":"2026-10-11"});
CLI
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"
    }
  ]
}

POST 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

Parameters: list_prospects
NameTypeDescription
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
curl -X POST https://cotlet.dev/api/v1/zen-planner/list_prospects \
  -H "Authorization: Bearer $COTLET_API_KEY"
Python
result = client.call("zen-planner", "list_prospects")
Node.js
const result = await cotlet.call('zen-planner', 'list_prospects');
CLI
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
}

POST 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

Parameters: list_failed_payments
NameTypeDescription
from date Start date. Default: 7 days ago.
to date End date. Default: today.
location_id string Only this location.

Request

cURL
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"}'
Python
result = client.call("zen-planner", "list_failed_payments", {"from":"2026-10-05","to":"2026-10-11"})
Node.js
const result = await cotlet.call('zen-planner', 'list_failed_payments', {"from":"2026-10-05","to":"2026-10-11"});
CLI
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"
}

POST 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

Parameters: get_revenue_report
NameTypeDescription
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
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"}'
Python
result = client.call("zen-planner", "get_revenue_report", {"from":"2026-10-01","to":"2026-10-01"})
Node.js
const result = await cotlet.call('zen-planner', 'get_revenue_report', {"from":"2026-10-01","to":"2026-10-01"});
CLI
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"
}

Book class

write Confirm

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

Parameters: book_class
NameTypeDescription
class_id required string Class ID from list_classes.
person_id required string Person ID from list_members.

Request

cURL
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"}'
Python
result = client.call("zen-planner", "book_class", {"class_id":"c7e2a91f","person_id":"p253ac9b9"})
Node.js
const result = await cotlet.call('zen-planner', 'book_class', {"class_id":"c7e2a91f","person_id":"p253ac9b9"});
CLI
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
}

Cancel reservation

write Confirm

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

Parameters: cancel_reservation
NameTypeDescription
class_id required string Class ID from list_classes.
reservation_id required string Reservation ID from get_class_roster.

Request

cURL
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"}'
Python
result = client.call("zen-planner", "cancel_reservation", {"class_id":"class_8c41d2","reservation_id":"reservation_8c41d2"})
Node.js
const result = await cotlet.call('zen-planner', 'cancel_reservation', {"class_id":"class_8c41d2","reservation_id":"reservation_8c41d2"});
CLI
cotlet call zen-planner cancel_reservation --data '{"class_id":"class_8c41d2","reservation_id":"reservation_8c41d2"}'

Example response

{
  "reservation_id": "r_5510",
  "status": "cancelled"
}

Check in member

write Confirm

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

Parameters: check_in_member
NameTypeDescription
class_id required string Class ID from list_classes.
person_id required string Person ID from list_members.

Request

cURL
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"}'
Python
result = client.call("zen-planner", "check_in_member", {"class_id":"class_8c41d2","person_id":"person_8c41d2"})
Node.js
const result = await cotlet.call('zen-planner', 'check_in_member', {"class_id":"class_8c41d2","person_id":"person_8c41d2"});
CLI
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"
}

Create prospect

write Confirm

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

Parameters: create_prospect
NameTypeDescription
first_name required string First name.
last_name required string Last name.
email string Email address.
phone string Phone number.
source string Lead source, e.g. Open house.

Request

cURL
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"}'
Python
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"})
Node.js
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"});
CLI
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"
}

Enroll in membership

write Confirm

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

Parameters: enroll_in_membership
NameTypeDescription
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
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"}'
Python
result = client.call("zen-planner", "enroll_in_membership", {"person_id":"person_8c41d2","membership_type_id":"membership_type_8c41d2"})
Node.js
const result = await cotlet.call('zen-planner', 'enroll_in_membership', {"person_id":"person_8c41d2","membership_type_id":"membership_type_8c41d2"});
CLI
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"
}

Promote rank

write Confirm

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

Parameters: promote_rank
NameTypeDescription
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
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"}'
Python
result = client.call("zen-planner", "promote_rank", {"person_id":"person_8c41d2","rank":"rank"})
Node.js
const result = await cotlet.call('zen-planner', 'promote_rank', {"person_id":"person_8c41d2","rank":"rank"});
CLI
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"
}