Skip to main content

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.

note

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.
Legacy series

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_typeDescription
sumDefault โ€” "Add up all sessions". The program total is the sum of the included sessions' prices, using each experience's own pricing.
fixedA 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.

Legacy pricing fields

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โ€‹

StatusDescription
activeThe series is live; upcoming sessions remain booked.
cancelledThe 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โ€‹

MethodEndpointDescription
GET/v1/seriesList series
GET/v1/series/{id}Get series โ€” sessions, choice groups, pricing + totals
GET/v1/series/{id}/participantsWho 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}/bookingsThe enrollments themselves (paginated booking resources)
GET/v1/series/{id}/insightsPlain-language summary: upcoming sessions, enrollments, revenue
GET/v1/series/{id}/gear-listGear list โ€” what to pull for the whole cohort, and from which site (needs gear:read)
POST/v1/seriesCreate 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}/enrollEnroll โ€” one booking for the whole program
POST/v1/series/{id}/runsCreate a cohort from a reusable program (clones the menu, no dates)
POST/v1/series/{id}/duplicateCopy a program โ€” activities, dates and pricing, never the bookings. The copy starts with online sales off.
POST/v1/series/{id}/archive ยท /unarchiveTake a program out of circulation, or put it back
POST/v1/series/{id}/sessionsAdd session
DELETE/v1/series/{id}/sessions/{sessionId}Remove one date from the program
PUT/v1/series/{id}/sessions/{sessionId}/choiceGroup 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}/waiverwaiver_mode: per_activity (each activity's own forms) or single (one form covers the program, needs waiver_form_id)
POST/v1/series/{id}/cancelCancel series โ€” stops new enrollments
POST/v1/series/{id}/sessions/{sessionId}/cancelCancel session โ€” legacy per-session bookings only

Required Scopesโ€‹

ScopeOperations
series:readList programs, get a program, read its participants, enrollments and insights
series:writeCreate and edit programs, enroll customers, manage dates, activities, choices and forms, archive, duplicate, create cohorts, cancel
gear:readRead 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.