Zum Inhalt springen

Course Participants

A CourseParticipant (Kursteilnehmer) represents the actual booking of one person into one course. Creating a CourseParticipant is the step that:

  • Assigns the person a seat in the course.
  • Optionally adds the person to the main class of the course.
  • Triggers invoicing through the configured billing customer.
  • Records the seller for commission and reporting.

Call this mutation from an authenticated staff context, not from public portals. Public portals should create a CourseRegistration and let staff confirm (Buchen).

mutation CreateCourseParticipant(
$courseParticipant: CourseParticipantCreateInput!
$parentID: ID!
) {
createCourseParticipant(
courseParticipant: $courseParticipant
parentID: $parentID
) {
status
message
id
errorType
errorData
courseParticipant {
id
waitingListPosition
person {
id
lastName
preName
}
}
}
}

parentID must be the UID of the course the person is booked into — not a folder. Omitting it returns CreateCourseParticipantParentIDMustBeSetError.

input CourseParticipantCreateInput {
"Person UID that is being booked into the course. Required."
personID: UID
"Course UID. Usually equal to parentID; specify when differs from parentID (sub-course scenarios)."
courseID: UID
"Create membership in the main class of the course"
createMainClassMembership: Boolean
"When propagating to sub-courses, enroll in each main class"
createSubCourseMainClassMembership: Boolean
dateOfSale: Date
sellerID: UID
"Billing assignment — which customer account pays for the course fee"
simpleCustomer: CourseParticipantSimpleCustomerInput
"Billing target for course material fees (create if missing)"
courseMaterialBillingObjectID: UID
"Member type (participant, auditor, substitute, ...)"
courseMemberTypeID: Int
classDispositionNotes: String
subjectDispositionNotes: String
billingNotes: String
waitingListPosition: Int
# ...plus all BaseObjectInput fields
}
input CourseParticipantSimpleCustomerInput {
"Who pays the course fee. A customer account is created automatically if none exists."
customerType: CourseParticipantSimpleCustomerType
"Term of payment. Default is used when omitted."
termOfPaymentID: Int
}
{
"parentID": "4a9e2c17-...-b3",
"courseParticipant": {
"personID": "8f3a1a8e-...-1c",
"createMainClassMembership": true
}
}
{
"parentID": "4a9e2c17-...-b3",
"courseParticipant": {
"personID": "8f3a1a8e-...-1c",
"dateOfSale": "2026-04-23",
"sellerID": "c12de56f-...-99",
"simpleCustomer": {
"customerType": "SELF",
"termOfPaymentID": 30
},
"createMainClassMembership": true
}
}

When the course is full, set waitingListPosition to the target position. The response’s courseParticipant.waitingListPosition reflects the position actually assigned (it may differ if earlier positions were taken concurrently).

{
"parentID": "4a9e2c17-...-b3",
"courseParticipant": {
"personID": "8f3a1a8e-...-1c",
"waitingListPosition": 1
}
}
query {
courseParticipants(
options: {
parentID: "4a9e2c17-...-b3"
onlyActive: true
limit: 100
}
) {
totalCount
nodes {
id
person {
id
lastName
preName
}
waitingListPosition
}
}
}
mutation UpdateCourseParticipant(
$id: ID!
$courseParticipant: CourseParticipantUpdateInput!
) {
updateCourseParticipant(id: $id, courseParticipant: $courseParticipant) {
status
message
}
}

Updating personID, courseID or parentID is not possible through updateCourseParticipant — use the dedicated transfer mutations (transferCourseParticipant) to move a booking between courses.

mutation {
deleteCourseParticipant(id: "...") {
status
message
}
}

Cancellation preserves the participant row for reporting (soft delete) and removes any class memberships created with createMainClassMembership: true. Associated invoices are not reversed automatically — credit them through the billing module.

createCourseParticipant returns both a generic status/message and a structured pair errorType / errorData for programmatic handling:

errorTypeMeaning
CreateCourseParticipantParentIDMustBeSetErrorparentID was missing.
PersonAlreadyParticipantErrorThe person is already booked into this course.
CoursePlacesExhaustedErrorCourse is full and waitlist is disabled.
BillingCustomerRequiredErrorsimpleCustomer is missing or resolves to no payer.

errorData contains a small JSON payload with the offending IDs so that the UI can link directly to them.