ReferenceReference by module

Group classes API

Every Group classes action (12) and data model (4): endpoints, scopes, input, preconditions, events and examples.

A weekly class timetable with places, instructors, bookings and attendance.

Module code group_classes · 12 actions · 4 data models · 11 events. A key or token never does more here than the person behind it can; row-level security applies exactly as in the app. Scopes: group_classes (everything), group_classes:read (read only) or group_classes:<capability>.

Resources

ResourceTableList and readPOSTPATCHDELETE
group_class_joiningsgroup_class_joining/api/v1/group_class_joinings
group_class_schedulesgroup_class_schedule/api/v1/group_class_schedules
group_class_servicesgroup_class_service/api/v1/group_class_services
group_classesgroup_class/api/v1/group_classes

Lists take limit (up to 200), cursor, order (e.g. -created_at), fields and q; every other query parameter is a column filter: ?status=paid, ?total[gte]=100, ?id[in]=a,b, ?x=null.

Actions

ActionNeedsWhat it does
group_classes.add_schedulegroup_classes:manageAdd a weekly time
group_classes.archive_classgroup_classes:manageRetire a class
group_classes.cancel_joininggroup_classes:writeCancel a class booking
group_classes.cancel_sessiongroup_classes:manageCancel one session
group_classes.create_classgroup_classes:manageCreate a class
group_classes.end_schedulegroup_classes:manageEnd a series
group_classes.joingroup_classes:writeBook a place
group_classes.join_onlinegroup_classes:writeBook a class place online
group_classes.mark_attendancegroup_classes:writeRecord attendance
group_classes.set_servicesgroup_classes:manageChange the services
group_classes.update_classgroup_classes:manageEdit a class
group_classes.update_schedulegroup_classes:manageEdit a weekly time

group_classes.add_schedule

Add a weekly time — Starts a new series: the class runs every week at this day and time.

Needs group_classes:manage · changes data

POSThttps://app.getera.io/api/v1/group_class_schedules/actions/add_schedule
API key or OAuth token · group_classes:manage
  • Canonical address: POST /api/v1/actions/group_classes.add_schedule

Input

FieldTypeRequiredNotes
groupClassIduuidyesClass · id of group_class
weekdaynumberyesDay · min 0 · max 6
startTimestringyesStarts · max 8
durationnumberyesLength (minutes) · min 1 · max 1440
instructorUserIduuidInstructor
startsOndateFirst session from

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe class must exist.
class_archivedA retired class cannot be scheduled.
no_scheduleDay, time and length must be well-formed.
schedule_existsThe class must not already run at that day and time.
service_not_offered_that_dayThe class’s services must be offered that day.
provider_cannot_performThe instructor must deliver every service in the class.

Events it publishes: group_classes.series_created

What it writes: group_class_schedule (insert) — Writes the series

curl -X POST https://app.getera.io/api/v1/group_class_schedules/actions/add_schedule \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"groupClassId":"GROUP_CLASS_ID","weekday":1,"startTime":"Starts","duration":1}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.series_created"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClassSchedules.addSchedule({
  groupClassId: "GROUP_CLASS_ID",
  weekday: 1,
  startTime: "Starts",
  duration: 1
})
era group_class_schedules add_schedule \
  --group-class-id "GROUP_CLASS_ID" \
  --weekday 1 \
  --start-time "Starts" \
  --duration 1
tools/call
{
  "name": "era__group_classes__add_schedule",
  "arguments": {
    "groupClassId": "GROUP_CLASS_ID",
    "weekday": 1,
    "startTime": "Starts",
    "duration": 1
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, class_archived, no_schedule, schedule_exists, service_not_offered_that_day, provider_cannot_perform · 429 slow down

group_classes.archive_class

Retire a class — Stops taking bookings. The history stays.

Needs group_classes:manage · reaches outside (sends, publishes or charges) · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/group_classes/{id}/actions/archive_class
API key or OAuth token · group_classes:manage
  • Canonical address: POST /api/v1/actions/group_classes.archive_class

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Class · id of group_class

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe class must exist.
class_archivedIt must not already be retired.
has_upcoming_joiningsNobody may be booked on a coming session.
no_workspaceThe workspace must be readable, for its clock.

Events it publishes: group_classes.class_archived

What it writes: group_class (update) — Stamps archived_at; group_class_schedule (update) — Ends every running series today

curl -X POST https://app.getera.io/api/v1/group_classes/GROUP_CLASSE_ID/actions/archive_class \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.class_archived"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClasses.archiveClass("GROUP_CLASSE_ID")
era group_classes archive_class GROUP_CLASSE_ID
tools/call
{
  "name": "era__group_classes__archive_class",
  "arguments": {
    "id": "GROUP_CLASSE_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, class_archived, has_upcoming_joinings, no_workspace · 429 slow down

group_classes.cancel_joining

Cancel a class booking — Frees the place. A reason is required, as in the source.

Needs group_classes:write · removes or cannot be undone · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/group_class_joinings/{id}/actions/cancel_joining
API key or OAuth token · group_classes:write
  • Canonical address: POST /api/v1/actions/group_classes.cancel_joining

Input

FieldTypeRequiredNotes
joiningIduuidyesFilled from the path {id} · Booking · id of group_class_joining
reasonstringyesReason · max 64

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
joining_not_foundThe booking must exist.
already_cancelledIt must not already be cancelled.
already_finishedAttendance must not already be recorded.
unknown_reasonThe reason must be one the workspace uses.

Events it publishes: group_classes.joining_cancelled

What it writes: group_class_joining (update) — Marks it cancelled and records why

curl -X POST https://app.getera.io/api/v1/group_class_joinings/GROUP_CLASS_JOINING_ID/actions/cancel_joining \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"reason":"Reason"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.joining_cancelled"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClassJoinings.cancelJoining("GROUP_CLASS_JOINING_ID", {
  reason: "Reason"
})
era group_class_joinings cancel_joining GROUP_CLASS_JOINING_ID \
  --reason "Reason"
tools/call
{
  "name": "era__group_classes__cancel_joining",
  "arguments": {
    "joiningId": "GROUP_CLASS_JOINING_ID",
    "reason": "Reason"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 joining_not_found, already_cancelled, already_finished, unknown_reason · 429 slow down

group_classes.cancel_session

Cancel one session — Takes one date off the series and cancels everyone booked on it.

Needs group_classes:manage · removes or cannot be undone · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/group_class_joinings/actions/cancel_session
API key or OAuth token · group_classes:manage
  • Canonical address: POST /api/v1/actions/group_classes.cancel_session

Input

FieldTypeRequiredNotes
scheduleIduuidyesSeries · id of group_class_schedule
sessionDatedateyesDate
reasonstringyesReason · max 64

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
schedule_not_foundThe series must exist.
not_foundIts class must exist.
unknown_reasonThe reason must be one the workspace uses.
no_such_sessionThe class must run on that date.
session_cancelledIt must not already be cancelled.
session_in_pastIt must not have started.
no_workspaceThe workspace must be readable, for its clock.

Events it publishes: group_classes.session_cancelled, group_classes.joining_cancelled

What it writes: group_class_session_cancellation (insert) — Records the cancelled date; group_class_joining (update) — Cancels everyone booked on it

curl -X POST https://app.getera.io/api/v1/group_class_joinings/actions/cancel_session \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"scheduleId":"GROUP_CLASS_SCHEDULE_ID","sessionDate":"2026-11-02","reason":"Reason"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.session_cancelled",
    "group_classes.joining_cancelled"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClassJoinings.cancelSession({
  scheduleId: "GROUP_CLASS_SCHEDULE_ID",
  sessionDate: "2026-11-02",
  reason: "Reason"
})
era group_class_joinings cancel_session \
  --schedule-id "GROUP_CLASS_SCHEDULE_ID" \
  --session-date "2026-11-02" \
  --reason "Reason"
tools/call
{
  "name": "era__group_classes__cancel_session",
  "arguments": {
    "scheduleId": "GROUP_CLASS_SCHEDULE_ID",
    "sessionDate": "2026-11-02",
    "reason": "Reason"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 schedule_not_found, not_found, unknown_reason, no_such_session, session_cancelled, session_in_past, no_workspace · 429 slow down

group_classes.create_class

Create a class — A class with its services, its capacity and its weekly times, in one go.

Needs group_classes:manage · changes data

POSThttps://app.getera.io/api/v1/group_classes/actions/create_class
API key or OAuth token · group_classes:manage
  • Canonical address: POST /api/v1/actions/group_classes.create_class

Input

FieldTypeRequiredNotes
namestringyesName · max 255
capacitynumberyesPlaces · min 1 · max 10000
instructorUserIduuidInstructor
itemVariantIdsobject / arrayyesServices · [itemVariantId, …]
schedulesobject / arrayyesWeekly times · [{ weekday: 0–6 (0 = Sunday), startTime: "HH:MM", duration: minutes, instructorUserId? }]

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
no_servicesAt least one service must be chosen.
no_scheduleAt least one well-formed weekly time must be given.
service_not_foundEvery service must exist.
not_a_class_serviceOnly services set up as group classes may be used.
service_not_offered_that_dayEvery weekly time must fall on a day its services are offered.
provider_cannot_performAn instructor must deliver every service in the class.
schedule_existsThe same day and time cannot be listed twice.

Events it publishes: group_classes.class_created

What it writes: group_class (insert) — Creates the class; group_class_service (insert) — Links its services; group_class_schedule (insert) — Writes its weekly series

curl -X POST https://app.getera.io/api/v1/group_classes/actions/create_class \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"name":"Name","capacity":1,"itemVariantIds":{},"schedules":{}}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.class_created"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClasses.createClass({
  name: "Name",
  capacity: 1,
  itemVariantIds: {},
  schedules: {}
})
era group_classes create_class --data '{"name":"Name","capacity":1,"itemVariantIds":{},"schedules":{}}'
tools/call
{
  "name": "era__group_classes__create_class",
  "arguments": {
    "name": "Name",
    "capacity": 1,
    "itemVariantIds": {},
    "schedules": {}
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 no_services, no_schedule, service_not_found, not_a_class_service, service_not_offered_that_day, provider_cannot_perform, schedule_exists · 429 slow down

group_classes.end_schedule

End a series — The class stops running at this time after a date; later bookings are cancelled.

Needs group_classes:manage · reaches outside (sends, publishes or charges) · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/group_class_schedules/{id}/actions/end_schedule
API key or OAuth token · group_classes:manage
  • Canonical address: POST /api/v1/actions/group_classes.end_schedule

Input

FieldTypeRequiredNotes
scheduleIduuidyesFilled from the path {id} · Series · id of group_class_schedule
endsOndateyesLast session on
reasonstringyesReason · max 64

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
schedule_not_foundThe series must exist.
schedule_endedIt must still be running.
not_foundIts class must exist.
unknown_reasonThe reason must be one the workspace uses.
ends_in_pastA series ends today or later, never in the past.
no_workspaceThe workspace must be readable, for its clock.

Events it publishes: group_classes.series_ended, group_classes.joining_cancelled

What it writes: group_class_schedule (update) — Stamps ends_on; group_class_joining (update) — Cancels bookings after the last session

curl -X POST https://app.getera.io/api/v1/group_class_schedules/GROUP_CLASS_SCHEDULE_ID/actions/end_schedule \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"endsOn":"2026-11-02","reason":"Reason"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.series_ended",
    "group_classes.joining_cancelled"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClassSchedules.endSchedule("GROUP_CLASS_SCHEDULE_ID", {
  endsOn: "2026-11-02",
  reason: "Reason"
})
era group_class_schedules end_schedule GROUP_CLASS_SCHEDULE_ID \
  --ends-on "2026-11-02" \
  --reason "Reason"
tools/call
{
  "name": "era__group_classes__end_schedule",
  "arguments": {
    "scheduleId": "GROUP_CLASS_SCHEDULE_ID",
    "endsOn": "2026-11-02",
    "reason": "Reason"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 schedule_not_found, schedule_ended, not_found, unknown_reason, ends_in_past, no_workspace · 429 slow down

group_classes.join

Book a place — Puts a customer on one session of a class, while it has room.

Needs group_classes:write · changes data

POSThttps://app.getera.io/api/v1/group_class_joinings/actions/join
API key or OAuth token · group_classes:write
  • Canonical address: POST /api/v1/actions/group_classes.join

Input

FieldTypeRequiredNotes
scheduleIduuidyesSeries · id of group_class_schedule
sessionDatedateyesDate
customerIduuidyesCustomer · id of customer

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
schedule_not_foundThe series must exist.
not_foundIts class must exist.
class_archivedA retired class takes no bookings.
no_such_sessionThe class must run on that date.
session_cancelledThe session must not be cancelled.
inside_cutoffThe session must not have started (or be inside the cutoff).
outside_windowThe session must be inside the booking window.
class_fullThe session must have a free place.
customer_not_foundThe customer must exist in this workspace.
customer_bannedThe customer must not be banned.
already_joinedThe same person cannot be booked twice on one session.
no_workspaceThe workspace must be readable, for its clock.

Events it publishes: group_classes.joined

What it writes: group_class_joining (insert) — Books the place, with its price frozen

curl -X POST https://app.getera.io/api/v1/group_class_joinings/actions/join \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"scheduleId":"GROUP_CLASS_SCHEDULE_ID","sessionDate":"2026-11-02","customerId":"CUSTOMER_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.joined"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClassJoinings.join({
  scheduleId: "GROUP_CLASS_SCHEDULE_ID",
  sessionDate: "2026-11-02",
  customerId: "CUSTOMER_ID"
})
era group_class_joinings join \
  --schedule-id "GROUP_CLASS_SCHEDULE_ID" \
  --session-date "2026-11-02" \
  --customer-id "CUSTOMER_ID"
tools/call
{
  "name": "era__group_classes__join",
  "arguments": {
    "scheduleId": "GROUP_CLASS_SCHEDULE_ID",
    "sessionDate": "2026-11-02",
    "customerId": "CUSTOMER_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 schedule_not_found, not_found, class_archived, no_such_session, session_cancelled, inside_cutoff, outside_window, class_full, customer_not_found, customer_banned, already_joined, no_workspace · 429 slow down

group_classes.join_online

Book a class place online — A visitor takes one place on a class session from the site timetable, while it has room.

Needs group_classes:write · changes data · Also callable from a published site (visitor)

A website action: your site calls it through the site API (/api/site/v1/{siteId}, e.g. with @getera/storefront). With an API key or a token it is refused (403 site_only).
POSThttps://app.getera.io/api/v1/group_class_joinings/actions/join_online
API key or OAuth token · group_classes:write
  • Canonical address: POST /api/v1/actions/group_classes.join_online

Input

FieldTypeRequiredNotes
scheduleIduuidyesSeries · id of group_class_schedule
sessionDatedateyesDate

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
guest_details_requiredA guest leaves their details before booking.
class_fullThe session must have a free place.

Events it publishes: group_classes.joined

What it writes: group_class_joining (insert) — Books the place, with its price frozen

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 guest_details_required, class_full · 429 slow down

group_classes.mark_attendance

Record attendance — Came, or did not come.

Needs group_classes:write · changes data

POSThttps://app.getera.io/api/v1/group_class_joinings/{id}/actions/mark_attendance
API key or OAuth token · group_classes:write
  • Canonical address: POST /api/v1/actions/group_classes.mark_attendance

Input

FieldTypeRequiredNotes
joiningIduuidyesFilled from the path {id} · Booking · id of group_class_joining
attendedbooleanyesAttended

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
joining_not_foundThe booking must exist.
already_cancelledA cancelled booking has no attendance.
already_finishedAttendance is recorded once.
not_yet_startedThe session must have started.
no_workspaceThe workspace must be readable, for its clock.

Events it publishes: group_classes.attended, group_classes.no_show

What it writes: group_class_joining (update) — Moves it to completed or no_show

curl -X POST https://app.getera.io/api/v1/group_class_joinings/GROUP_CLASS_JOINING_ID/actions/mark_attendance \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"attended":true}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.attended",
    "group_classes.no_show"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClassJoinings.markAttendance("GROUP_CLASS_JOINING_ID", {
  attended: true
})
era group_class_joinings mark_attendance GROUP_CLASS_JOINING_ID \
  --attended true
tools/call
{
  "name": "era__group_classes__mark_attendance",
  "arguments": {
    "joiningId": "GROUP_CLASS_JOINING_ID",
    "attended": true
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 joining_not_found, already_cancelled, already_finished, not_yet_started, no_workspace · 429 slow down

group_classes.set_services

Change the services — Which services make up the class — and so its price.

Needs group_classes:manage · removes or cannot be undone

POSThttps://app.getera.io/api/v1/group_class_services/actions/set_services
API key or OAuth token · group_classes:manage
  • Canonical address: POST /api/v1/actions/group_classes.set_services

Input

FieldTypeRequiredNotes
iduuidyesClass · id of group_class
itemVariantIdsobject / arrayyesServices · [itemVariantId, …]

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe class must exist.
class_archivedA retired class cannot be edited.
no_servicesAt least one service must remain.
service_not_foundEvery service must exist.
not_a_class_serviceOnly services set up as group classes may be used.
service_not_offered_that_dayEvery service must be offered on the days the class runs.

Events it publishes: group_classes.class_updated

What it writes: group_class_service (upsert) — Sets the class’s services; group_class_service (delete) — Removes the ones no longer in it

curl -X POST https://app.getera.io/api/v1/group_class_services/actions/set_services \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"id":"GROUP_CLASS_ID","itemVariantIds":{}}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.class_updated"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClassServices.setServices({
  id: "GROUP_CLASS_ID",
  itemVariantIds: {}
})
era group_class_services set_services --data '{"id":"GROUP_CLASS_ID","itemVariantIds":{}}'
tools/call
{
  "name": "era__group_classes__set_services",
  "arguments": {
    "id": "GROUP_CLASS_ID",
    "itemVariantIds": {}
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, class_archived, no_services, service_not_found, not_a_class_service, service_not_offered_that_day · 429 slow down

group_classes.update_class

Edit a class — Name, places and the default instructor.

Needs group_classes:manage · changes data

POSThttps://app.getera.io/api/v1/group_classes/{id}/actions/update_class
API key or OAuth token · group_classes:manage
  • Canonical address: POST /api/v1/actions/group_classes.update_class

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Class · id of group_class
namestringName · max 255
capacitynumberPlaces · min 1 · max 10000
instructorUserIduuidInstructor
clearInstructorbooleanNo default instructor

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe class must exist.
class_archivedA retired class cannot be edited.
capacity_below_bookedPlaces cannot drop below a coming session’s bookings.
provider_cannot_performThe instructor must deliver every service in the class.
no_workspaceThe workspace must be readable, for its clock.

Events it publishes: group_classes.class_updated

What it writes: group_class (update) — Updates the class

curl -X POST https://app.getera.io/api/v1/group_classes/GROUP_CLASSE_ID/actions/update_class \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"name":"Name"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.class_updated"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClasses.updateClass("GROUP_CLASSE_ID", {
  name: "Name"
})
era group_classes update_class GROUP_CLASSE_ID \
  --name "Name"
tools/call
{
  "name": "era__group_classes__update_class",
  "arguments": {
    "id": "GROUP_CLASSE_ID",
    "name": "Name"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, class_archived, capacity_below_booked, provider_cannot_perform, no_workspace · 429 slow down

group_classes.update_schedule

Edit a weekly time — Length and instructor always; day and time only while nobody is booked on it.

Needs group_classes:manage · changes data

POSThttps://app.getera.io/api/v1/group_class_schedules/{id}/actions/update_schedule
API key or OAuth token · group_classes:manage
  • Canonical address: POST /api/v1/actions/group_classes.update_schedule

Input

FieldTypeRequiredNotes
scheduleIduuidyesFilled from the path {id} · Series · id of group_class_schedule
weekdaynumberDay · min 0 · max 6
startTimestringStarts · max 8
durationnumberLength (minutes) · min 1 · max 1440
instructorUserIduuidInstructor
clearInstructorbooleanUse the class’s instructor

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
schedule_not_foundThe series must exist.
schedule_endedAn ended series cannot be edited.
class_archivedA retired class cannot be edited.
no_scheduleDay, time and length must be well-formed.
has_upcoming_joiningsDay and time cannot move while people are booked on the series.
schedule_existsThe class must not already run at the new day and time.
service_not_offered_that_dayThe class’s services must be offered on the new day.
provider_cannot_performThe instructor must deliver every service in the class.

Events it publishes: group_classes.series_updated

What it writes: group_class_schedule (update) — Updates the series

curl -X POST https://app.getera.io/api/v1/group_class_schedules/GROUP_CLASS_SCHEDULE_ID/actions/update_schedule \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"weekday":1}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "group_classes.series_updated"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.groupClassSchedules.updateSchedule("GROUP_CLASS_SCHEDULE_ID", {
  weekday: 1
})
era group_class_schedules update_schedule GROUP_CLASS_SCHEDULE_ID \
  --weekday 1
tools/call
{
  "name": "era__group_classes__update_schedule",
  "arguments": {
    "scheduleId": "GROUP_CLASS_SCHEDULE_ID",
    "weekday": 1
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold group_classes:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 schedule_not_found, schedule_ended, class_archived, no_schedule, has_upcoming_joinings, schedule_exists, service_not_offered_that_day, provider_cannot_perform · 429 slow down

Data models

GroupClassJoining

Table group_class_joining · Resource group_class_joinings

  • GET /api/v1/group_class_joinings
  • GET /api/v1/group_class_joinings/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
group_class_idstring (uuid) · uuidgroup_class
schedule_idstring (uuid) · uuidgroup_class_schedule
customer_idstring (uuid) · uuidcustomer
session_datestring (date) · date
start_timestring (time) · time
statusstring · textactive, cancelled, completed, no_show
price_amountstring (int64) · int8
price_currencystring · bpcharyesmax 3
cancelled_atstring (date-time) · timestamptzyes
cancellation_reasonstring · textyes
attended_marked_atstring (date-time) · timestamptzyes
owner_user_idstring (uuid) · uuidyesapp_user
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Checks:

  • CHECK ((price_amount >= 0))

GroupClassSchedule

Table group_class_schedule · Resource group_class_schedules

  • GET /api/v1/group_class_schedules
  • GET /api/v1/group_class_schedules/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
group_class_idstring (uuid) · uuidgroup_class
weekdayinteger · int4
start_timestring (time) · time
durationinteger · int4
instructor_user_idstring (uuid) · uuidyesapp_user
starts_onstring (date) · dateyes
ends_onstring (date) · dateyes
created_atstring (date-time) · timestamptz

Primary key: id

Checks:

  • CHECK (((starts_on IS NULL) OR (ends_on IS NULL) OR (ends_on >= starts_on)))
  • CHECK ((duration > 0))
  • CHECK (((weekday >= 0) AND (weekday <= 6)))

GroupClassService

Table group_class_service · Resource group_class_services

  • GET /api/v1/group_class_services
  • GET /api/v1/group_class_services/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
group_class_idstring (uuid) · uuidgroup_class
item_variant_idstring (uuid) · uuiditem_variant
sort_orderinteger · int4
created_atstring (date-time) · timestamptz

Primary key: id

Unique: group_class_id, item_variant_id

GroupClass

Table group_class · Resource group_classes

  • GET /api/v1/group_classes
  • GET /api/v1/group_classes/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
namestring · text
capacityinteger · int4
instructor_user_idstring (uuid) · uuidyesapp_user
archived_atstring (date-time) · timestamptzyes
created_bystring (uuid) · uuidyesapp_user
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz
is_publicboolean · boolyes

Primary key: id

Checks:

  • CHECK ((capacity > 0))
  • CHECK (((length(btrim(name)) >= 1) AND (length(btrim(name)) <= 255)))

Events

Workflows and webhooks react to these events.

EventWhat happensPayload
group_classes.attendedA customer came to their class.id, groupClassId, customerId, sessionDate
group_classes.class_archivedA class was retired.id
group_classes.class_createdA class was created.id, name, capacity
group_classes.class_updatedA class changed.id
group_classes.joinedA customer booked a place.id, groupClassId, customerId, sessionDate, startTime, priceAmount, priceCurrency, scheduleId
group_classes.joining_cancelledA class booking was cancelled.id, groupClassId, customerId, sessionDate, reason
group_classes.no_showA customer did not come to their class.id, groupClassId, customerId, sessionDate
group_classes.series_createdA class started running at a new weekly time.id, groupClassId, weekday, startTime
group_classes.series_endedA weekly series was ended.id, groupClassId, endsOn, cancelled
group_classes.series_updatedA weekly time changed.id, groupClassId
group_classes.session_cancelledOne date of a series was cancelled.id, groupClassId, sessionDate, cancelled