Series
A series is a bookable package: a name, the activities it includes, the session dates it covers, and a pricing option. A customer books the whole thing as one enrollment โ a weekly class, a lesson pack, a multi-week course.
The product UI calls series Programs (Experiences โ Programs). The API keeps the series name in URLs, fields, and scopes.
One series gives you:
- One booking for the run โ enrollment creates a single booking with one experience line per included session.
- One payment and one set of forms โ handled once for the enrollment, not once per date.
- One place to see who is on it โ the participants roster spans every session.
Key Conceptsโ
Sessions belong to the program, not to bookingsโ
A series' sessions are the dates the program covers โ each points at a schedule slot (experience_availability). They are the menu, not bookings. Bookings appear only when someone enrolls, and one enrollment produces ONE booking carrying every session as an experience line, stamped with series_id.
This means:
- Capacity is enforced per session slot at enrollment time.
- Cancelling the series stops new enrollments; existing enrollment bookings are untouched and are cancelled through the Bookings API like any other booking.
- A program may be created from activities alone and have its dates added later โ enrollment simply isn't possible until it has at least one upcoming date.
Series created before Programs v2 were built around a fixed saved group with per-session or consolidated billing. Those rows still read back (group, billing_mode), but new series never use them and the consolidated payment-link endpoint is gone.
Reusable programs and cohortsโ
A series can be marked is_template: true โ a reusable program. It is never sold directly. Instead you create cohorts from it (POST /v1/series/{id}/runs), each an ordinary sellable series with its own dates, enrollments and participants, linked back through template_id. Enrollment always targets a cohort's id; enrolling in a template is refused.
Customer-facing surfaces never say "run" โ an unnamed cohort is identified by its start date.
Pick-one choicesโ
Sessions that share a choice_group are alternatives: the customer takes exactly one of them, not all. Set them with PUT /v1/series/{id}/sessions/{sessionId}/choice, read them from the choice_groups summary on get series, and pass the pick back on enroll as choices: {"<choice_group>": <schedule_id>}. Only the chosen option is validated and booked.
Pricingโ
A program prices in one of two ways, chosen at creation with pricing_type:
pricing_type | Description |
|---|---|
sum | Default โ "Add up all sessions". The program total is the sum of the included sessions' prices, using each experience's own pricing. |
fixed | A fixed rate for the whole program, built on the experience pricing engine. Either per rate type โ a rates list mapping each rate category (e.g. adult, child) to a program price โ or per group โ a flat group_price with a max_group_size and an optional price_per_participant for each person beyond per_participant_included. |
Enrollment charges accordingly: Enroll creates one booking whose total is the program rate โ the sum of the sessions for sum, or the fixed rate for fixed.
The v2 price_structure / fixed_price fields still work for existing integrations โ fixed_price sets a single flat program price. New integrations should use pricing_type with rates or the group pricing fields.
Bookable programsโ
A series can be sold as a program: turned on for the booking widget, customers enroll themselves online, and staff can sell it at POS (Experiences tab โ Programs). Either way the sale is one enrollment covering the whole run โ see Enroll, which books the entire program in a single booking.
Series statusโ
| Status | Description |
|---|---|
active | The series is live; upcoming sessions remain booked. |
cancelled | The series has been cancelled โ all upcoming session bookings were cancelled. Past sessions are unaffected. |
Common Use Casesโ
Create a multi-week programโ
Pick the included activities and the schedule slots for every week (sessions can also be added afterwards):
curl -X POST "https://app.equipdash.com/api/v1/series" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"experience_ids": [12], "schedule_ids": [501, 502, 503], "pricing_type": "sum"}'
Sell the same course every termโ
Mark the program reusable, then create a cohort per intake. Customers enroll in the cohort, so each intake tracks its own dates and participants:
curl -X PATCH "https://app.equipdash.com/api/v1/series/1" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"is_template": true}'
curl -X POST "https://app.equipdash.com/api/v1/series/1/runs" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Term 3", "bookable_online": true}'
Offer a choice of datesโ
Give two sessions the same choice name; the customer takes exactly one:
curl -X PUT "https://app.equipdash.com/api/v1/series/1/sessions/15/choice" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"choice_group": "Weekend", "choice_label": "Saturday"}'
curl -X POST "https://app.equipdash.com/api/v1/series/1/enroll" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customer_id": 42, "choices": {"Weekend": 601}}'
See who is on a programโ
curl "https://app.equipdash.com/api/v1/series/1/participants" \
-H "Authorization: Bearer YOUR_API_KEY"
API Endpointsโ
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/series | List series |
| GET | /v1/series/{id} | Get series โ sessions, choice groups, pricing + totals |
| GET | /v1/series/{id}/participants | Who is enrolled โ one row per person, with their rate type and how many sessions they cover. A reusable program rolls up every cohort. |
| GET | /v1/series/{id}/bookings | The enrollments themselves (paginated booking resources) |
| GET | /v1/series/{id}/insights | Plain-language summary: upcoming sessions, enrollments, revenue |
| GET | /v1/series/{id}/gear-list | Gear list โ what to pull for the whole cohort, and from which site (needs gear:read) |
| POST | /v1/series | Create series |
| PATCH | /v1/series/{id} | Edit name, description, categories, pricing, sell-online, enrollment cap, reusable flag. Send only what changes โ anything omitted is left alone. |
| POST | /v1/series/{id}/enroll | Enroll โ one booking for the whole program |
| POST | /v1/series/{id}/runs | Create a cohort from a reusable program (clones the menu, no dates) |
| POST | /v1/series/{id}/duplicate | Copy a program โ activities, dates and pricing, never the bookings. The copy starts with online sales off. |
| POST | /v1/series/{id}/archive ยท /unarchive | Take a program out of circulation, or put it back |
| POST | /v1/series/{id}/sessions | Add session |
| DELETE | /v1/series/{id}/sessions/{sessionId} | Remove one date from the program |
| PUT | /v1/series/{id}/sessions/{sessionId}/choice | Group a date into a pick-one choice (choice_group + choice_label), or pass a null group to make it always included |
| POST | /v1/series/{id}/activities ยท DELETE /activities/{experienceId} | Manage the activities the program includes |
| PUT | /v1/series/{id}/waiver | waiver_mode: per_activity (each activity's own forms) or single (one form covers the program, needs waiver_form_id) |
| POST | /v1/series/{id}/cancel | Cancel series โ stops new enrollments |
| POST | /v1/series/{id}/sessions/{sessionId}/cancel | Cancel session โ legacy per-session bookings only |
Required Scopesโ
| Scope | Operations |
|---|---|
series:read | List programs, get a program, read its participants, enrollments and insights |
series:write | Create and edit programs, enroll customers, manage dates, activities, choices and forms, archive, duplicate, create cohorts, cancel |
gear:read | Read the cohort's gear list |
All endpoints additionally require the experiences module and a plan that includes Programs (Growth or higher); otherwise they return 403 plan_feature_required.