> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dmly.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Run group classes

> Schedule classes with a seat capacity and a waitlist, and control what happens when a place opens up.

A class is a group session with a fixed start time and a limited number of seats — a yoga
class, a group treatment, a workshop. Everyone books the same time slot instead of picking
their own, and once the seats are gone the class is full.

<Note>
  Class services are created in **Offerings → Services**, not in Appointments. Set the
  service type to **Class** there, along with its price, duration and payment mode. You then
  schedule the individual sessions from the Appointments calendar.
</Note>

## How classes differ from 1:1 appointments

<Columns cols={2}>
  <Card title="Seats, not slots" icon="chair">
    A 1:1 appointment takes a staff member's slot. A class has a **Capacity** — several
    clients book the same session until it fills.
  </Card>

  <Card title="No rescheduling" icon="calendar-xmark">
    Clients can cancel a class from their booking link, but they can never reschedule one to
    a different time. There is no other slot to move to.
  </Card>

  <Card title="A waitlist" icon="list-ol">
    When a class is full, clients can join a waitlist and are promoted automatically when
    someone cancels. 1:1 appointments have no waitlist.
  </Card>

  <Card title="Different automation triggers" icon="bolt">
    Booking a seat fires **Class booked**, not **Appointment booked**. See
    [Automation triggers](/automation/triggers).
  </Card>
</Columns>

Everything else works the same way. A booked seat creates a normal booking behind the scenes,
so reminders, the [Inbox](/inbox/overview) record and the client's history all behave exactly
as they do for a 1:1 appointment.

<Warning>
  Flows built on the **Appointment booked** trigger do not run for class seats — build those
  on **Class booked** instead. This is the single most common surprise when a workspace adds
  its first class. Cancellation is the exception: a cancelled seat fires **Appointment
  cancelled** as well as **Class cancelled**, so an existing appointment-cancelled flow *will*
  run for it.
</Warning>

## Schedule a session

<Steps>
  <Step title="Create the class service">
    In **Offerings → Services**, create a service and set its type to **Class**. Set the
    price and payment mode here — they apply to every session of that class.
  </Step>

  <Step title="Open the calendar">
    Go to **Appointments → Calendar**. This is where you *View and manage all bookings,
    classes and blocked time in one place.*
  </Step>

  <Step title="Add the session">
    Select **New class**, pick the class service, and set the date and time. If you see
    **No class services available. Create a class service first.**, the service type is still
    set to appointment.
  </Step>

  <Step title="Set capacity and waitlist">
    Set **Capacity** to the number of seats, and turn on **Enable waitlist** if you want
    clients to queue for a place once it fills.
  </Step>
</Steps>

The class appears on your [booking page](/appointments/booking-page) once the service is
active and set to be publicly visible.

## Capacity

**Capacity** is the seat count for one session, not for the class in general — each session
carries its own. A client who tries to book a full session sees **Sorry, that class is now
full.** A client who is already booked sees **You're already booked for this class.**: the
same contact can only hold one seat in a session.

Cancelling a session (rather than a single seat) stops it taking any further bookings.

## The waitlist

With **Enable waitlist** on, a client booking a full session is added to the queue instead
and sees:

> This session is full, so you've been added to the waitlist. We'll let you know if a place
> opens up.

Joining the waitlist fires the **Joined class waitlist** trigger. A waitlisted client holds a
position in the queue but has no booking yet — so they get no reminders and nothing appears
on your calendar for them.

### When a seat opens up

When a booked client cancels, DMLY promotes the client at the front of the queue — first in,
first promoted — and messages them automatically. A free class gets the class confirmation
message; a pay-before class gets a checkout link instead (see [Paid classes](#paid-classes)).

DMLY also fires the **Class seat opened** trigger for the promoted client at the same time.

<Note>
  In the trigger picker this trigger is called **Class seat opened**. Its internal code is
  `class_slot_opened` and its webhook topic is `class.seat_opened` — all three names refer to
  the same trigger.
</Note>

You can add a [flow](/automation/flow-builder) on **Class seat opened** to send anything extra
you want the promoted client to get. The built-in promotion message goes out either way.

Seats also free up on their own when a pay-before hold expires unpaid, which promotes the
next waitlisted client the same way.

## Paid classes

A class uses the same payment modes as any other service — set them on the service in
**Offerings → Services**. Two behaviours are worth knowing before you charge for a class.

**Pay before booking needs a connected gateway.** With no gateway connected, DMLY refuses the
booking up front with **Online payment isn't available right now. Please contact us to book
this class.** — no seat is held. Connect a gateway first; see
[Payments](/appointments/payments).

**Promotion off a paid waitlist is not a free seat.** When a place opens on a pay-before
class, the promoted client is moved into a payment hold, not a confirmed seat. They are sent
a checkout link and still have to pay within the hold window; if they don't, the seat is
released and the next person in the queue is promoted.

<Warning>
  If DMLY can't mint a checkout link at that moment — the gateway was disconnected after the
  waitlist formed, or there is nothing to collect — it confirms the seat anyway rather than
  strand the promotion, and marks it paid without a payment. Keep your gateway connected for
  as long as a pay-before class has a waitlist behind it.
</Warning>

## What clients can do afterwards

From their booking link a client can cancel a class seat, subject to the cancellation
deadline you set for classes. They cannot reschedule it — that option does not appear for a
class booking at all. If someone needs a different session, they cancel and book the other
one, or you move them from **Appointments → Calendar**.

## Online classes

If the class service uses the **Zoom (auto link)** location, DMLY creates **one** Zoom meeting
for the session and every booked client gets that same join link. Individual seats never get
their own meeting. See [Zoom](/integrations/zoom).

<Accordion title="A class disappeared from the booking page">
  Check three things on the service in **Offerings → Services**: it is active, it is set to be
  publicly visible, and its type is **Class**. Then check the session itself still exists on
  **Appointments → Calendar**, hasn't been cancelled, and is not in the past. A full session
  does not disappear — it still shows, as **Full — join waitlist** or, with the waitlist off,
  as a **Full** row that can't be selected.
</Accordion>

<Accordion title="Nobody is being messaged when a place opens up">
  DMLY sends the promotion message itself, so the cause is that built-in message failing
  rather than a missing flow. Check the client is reachable on WhatsApp, and for a pay-before
  class check a gateway is still connected so the checkout link can be minted.

  If you added your own flow on **Class seat opened** and only that is missing, check the same
  contact — a contact who has opted out, or whose bot is paused, is skipped by the flow.
</Accordion>

<Accordion title="My appointment flow doesn't run for classes">
  Booking a class seat fires **Class booked**, never **Appointment booked** — rebuild that
  flow on **Class booked**.

  Cancelling is different: a cancelled seat fires **Class cancelled** *and* **Appointment
  cancelled**, because the seat has a booking behind it. If you build a **Class cancelled**
  flow while an **Appointment cancelled** flow already exists, both run and the client hears
  from you twice.
</Accordion>
