API-Referenz
Alle Endpoints der CheckCourt REST-API v1
Enterprise-Feature
Die REST-API ist ein Enterprise-Feature und muss beim
Support angefragt werden. Ohne
Freischaltung weist die API jeden Schlüssel mit 401 UNAUTHORIZED ab.
Basis-URL: https://app.checkcourt.de/api/v1 · Authentifizierung per
Authorization: Bearer <API-Schlüssel> · Antworten sind immer benannte
JSON-Objekte, Fehler immer { "error": { "code", "message" } }. Grundlagen
und Fehler-Codes stehen im Developer-Überblick.
Welcher Schlüssel kann was?
Jeder Endpoint trägt unten Badges, die zeigen, mit welcher Schlüsselart er aufrufbar ist. Es gibt zwei Kategorien:
| Kategorie | Endpoints | Regel |
|---|---|---|
| Universell | Alles Vereinsbezogene (Plätze, Mitglieder, Buchungen, ...) | Der Scope entscheidet, nicht die Schlüsselart: Persönliche Schlüssel bringen die Scopes der Mitgliedsrolle mit, Management-Schlüssel ihre explizit vergebenen. Persönliche Schlüssel brauchen dazu immer X-Tenant-Id. |
| Nur persönliche Schlüssel | /me/* | Self-Service mit Mitglieds-Identität: eigene Vereine, eigene Buchungen lesen und anlegen. |
Jeder Endpoint hat genau eine Bedeutung: /me/* handelt für den Nutzer
hinter dem Schlüssel, alles andere verwaltet Vereins-Ressourcen per Scope.
POST /me/bookings bucht für dich selbst, POST /bookings bucht im Namen
eines Mitglieds (forUserId). Endpoints, die nur Management-Schlüssel
aufrufen können, gibt es bewusst nicht: Management-Schlüssel sind durch
Scopes begrenzt, nicht durch eigene Endpoints. DELETE /bookings/{id} ist
absichtlich vereint, "storniere diese Buchung" ist eine Bedeutung; ob das
Eigentum oder der Scope bookings:cancel sie erlaubt, entscheidet sich
zur Laufzeit.
Eigene Vereine
Persönliche Schlüssel sind nutzergebunden: Der Verein wird pro Anfrage über
den Header X-Tenant-Id angegeben. Dieser Endpoint liefert die Vereins-IDs
und deine Rolle im jeweiligen Verein; er selbst benötigt keinen Header.
get/me/tenantsNur Personal
Lists every club the member behind the personal API key belongs to, with the role held in each. This is the entry point of the multi-club model: personal keys are user-bound, and every club-scoped request names its club via the X-Tenant-Id header using the ids from this endpoint. This endpoint itself needs no header. Management keys have no member identity and receive 401.
Beispiel
curl "https://app.checkcourt.de/api/v1/me/tenants" \
-H "Authorization: Bearer ck_user_…"Antworten
200The caller's club memberships.401Missing/invalid key, management key, or no club of the user has personal keys enabled.
200er-Schema anzeigen
tenantsobject[]idstringnamestringrole"member" | "trainer" | "admin"The caller's role in THIS club; a user can be admin in one club and member in another.
Buchungen
Verfügbarkeiten lesen, Plätze buchen und stornieren. Eigene Buchungen
funktionieren mit persönlichen Schlüsseln ohne speziellen Scope;
bookings:write und bookings:cancel braucht nur, wer auf fremde
Buchungen zugreift. Das Tages-Listing mit Namen (für Abgleich und
Reporting) erfordert bookings:read_confidential; für die anonyme
Belegung unter /availability genügt bookings:read.
get/me/bookingsNur Personal
Returns the upcoming bookings owned by the member behind the personal API key in the club addressed via X-Tenant-Id, including cancelled ones (check cancelledAt). Management keys have no member identity and receive 403 FORBIDDEN.
Beispiel
curl "https://app.checkcourt.de/api/v1/me/bookings" \
-H "Authorization: Bearer ck_user_…"Antworten
200Own upcoming bookings.401Missing or invalid API key.403Key lacks bookings:read or has no member identity.
200er-Schema anzeigen
bookingsobject[]idstringcourtIdintegercourtNamestringtypestringdatestring (date)startTimestringendTimestringtitlestring | nullcancelledAtstring | null (date-time)cancelReasonstring | null
post/me/bookingsNur Personal
Creates a booking owned by the member behind the personal API key, in the club addressed via X-Tenant-Id. The full policy engine applies (booking hours, advance window, quotas, slot raster, court locks, time conflicts); policy denials come back as 422 BUSINESS_RULE. adminOverride: true additionally requires bookings:write (admins hold it by role).
Request-Body
courtIdintegerPflichtdatestring (date)PflichtstartTimestringPflichtendTimestringPflichttitlestringnotesstringbookingType"regular" | "training" | "mannschaft"categoryIdstringteamIdstringRequired when bookingType is
mannschaft.playersobject[]Co-players. Members are referenced by userId, guests carry a guestName (guest fees may apply).
userIdstringguestNamestringisGuestbooleanPflicht
adminOverridebooleanSkips all policy attribute checks (booking hours, advance limit, quotas). Requires
bookings:write. Hard integrity checks (court lock, time conflict, past date) still apply.
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/me/bookings" \
-H "Authorization: Bearer ck_user_…" \
-H "Content-Type: application/json" \
-d '{"courtId":1,"date":"2026-06-15","startTime":"18:00","endTime":"19:00"}'Antworten
200The created booking.400Validation error (bad times, unknown forUserId, players not in this club).401Missing or invalid API key.403Key lacks bookings:write for forUserId/adminOverride, or no permission for this team.404Court or team not found.422Policy denial or time conflict. Policy denials include `canOverride`.
200er-Schema anzeigen
bookingobjectidstringBooking id (UUID).
courtIdintegertype"regular" | "training" | "mannschaft"Booking kind.
mannschaftbookings belong to a team and have no personal owner.datestring (date)startTimestringendTimestringtitlestring | nullbookedBystring | nullUser id of the booking owner.
nullfor mannschaft bookings.teamIdstring | null
get/availability
Returns the busy intervals of every court for the given day: bookings and scheduled lock windows, each reduced to start/end time and a coarse kind. No booker names, titles or categories are included, which makes this endpoint safe for public-facing occupancy widgets (e.g. a club website showing which courts are free). Free slots are everything outside the returned intervals within the club's booking hours.
Parameter
datequery · string (date)PflichtCalendar day to evaluate (YYYY-MM-DD)
Beispiel
curl "https://app.checkcourt.de/api/v1/availability?date=2026-06-15" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
datestring (date)Pflichtcourtsobject[]PflichtcourtIdintegerPflichtcourtNamestringPflichtisLockedbooleanPflichtTrue while the court is locked entirely (independent of slots)
occupiedobject[]PflichtstartTimestringPflichtTime of day as HH:MM or HH:MM:SS
endTimestringPflichtTime of day as HH:MM or HH:MM:SS
kind"booking" | "lock"PflichtWhether the interval is a booking or a scheduled lock window
get/availability/slots
Discovery endpoint for assistants and booking widgets: returns the start times that are actually bookable per court on the given day, taking existing bookings, court locks, booking hours, the slot raster, duration bounds, the advance-booking window, and season/month closures into account. POST /bookings remains the authoritative gate; a returned slot can still be lost to a concurrent booking.
Parameter
datequery · string (date)PflichtdurationMinutesquery · integerDesired booking length. With an active slot raster, only durations that are a multiple of the raster interval yield slots.
Beispiel
curl "https://app.checkcourt.de/api/v1/availability/slots?date=2026-06-15" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Bookable start times per court (empty array for locked/closed courts).400Missing/malformed date or durationMinutes.401Missing or invalid API key.403Key lacks bookings:read.
200er-Schema anzeigen
datestring (date)durationMinutesintegercourtsobject[]courtIdintegercourtNamestringslotsstring[]
get/bookings
The reconciliation view for integrations: every booking of the given day including booker names, titles, check-in and cancellation state — exactly the personal data the anonymous /availability endpoint strips away, hence the confidential tier. Cancelled bookings are included (check cancelledAt).
With respectPrivacy=true the listing applies the same privacy rules as the member-facing booking plan and masks the booker identity where members opted out of showing their name.
Parameter
datequery · string (date)PflichtrespectPrivacyquery · booleanApplies the member-facing privacy rules (booking-level showName, category default): bookings whose booker chose to hide their name come back with
bookedByandbookerNameset to null. Use this for display boards and other surfaces that must not out-privilege the public booking plan, even though the key holds the confidential scope.
Beispiel
curl "https://app.checkcourt.de/api/v1/bookings?date=2026-06-15" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200All bookings of the day.400Missing or malformed date.401Missing or invalid API key.403Key lacks bookings:read_confidential.
200er-Schema anzeigen
datestring (date)bookingsobject[]idstringcourtIdintegercourtNamestringtypestringdatestring (date)startTimestringendTimestringtitlestring | nullbookedBystring | nullUser id of the owner; null for mannschaft bookings.
bookerNamestring | nullteamIdstring | nullcheckedInAtstring | null (date-time)cancelledAtstring | null (date-time)cancelReasonstring | null
post/bookings
Club-administration endpoint: creates a booking on BEHALF of a member (forUserId is mandatory; the booking belongs to that member and consumes their quota). Booking for yourself is POST /me/bookings. The full policy engine applies; policy denials come back as 422 BUSINESS_RULE with canOverride telling bookings:write holders that a retry with adminOverride: true would succeed.
Request-Body
courtIdintegerPflichtdatestring (date)PflichtstartTimestringPflichtendTimestringPflichttitlestringnotesstringbookingType"regular" | "training" | "mannschaft"categoryIdstringteamIdstringRequired when bookingType is
mannschaft.playersobject[]Co-players. Members are referenced by userId, guests carry a guestName (guest fees may apply).
userIdstringguestNamestringisGuestbooleanPflicht
forUserIdstringPflichtThe member this booking is created FOR: it belongs to them and consumes their quota. Mandatory — booking for yourself is POST /me/bookings.
adminOverridebooleanSkips all policy attribute checks (booking hours, advance limit, quotas). Requires
bookings:write. Hard integrity checks (court lock, time conflict, past date) still apply.
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/bookings" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"courtId":1,"date":"2026-06-15","startTime":"18:00","endTime":"19:00","forUserId":"forUserId"}'Antworten
200The created booking.400Validation error (bad times, unknown forUserId, players not in this club).401Missing or invalid API key.403Key lacks bookings:write for forUserId/adminOverride, or no permission for this team.404Court or team not found.422Policy denial or time conflict. Policy denials include `canOverride`.
200er-Schema anzeigen
bookingobjectidstringBooking id (UUID).
courtIdintegertype"regular" | "training" | "mannschaft"Booking kind.
mannschaftbookings belong to a team and have no personal owner.datestring (date)startTimestringendTimestringtitlestring | nullbookedBystring | nullUser id of the booking owner.
nullfor mannschaft bookings.teamIdstring | null
delete/bookings/{id}
Cancellation runs through the policy engine (cancellation deadline); denials come back as 422 BUSINESS_RULE with canOverride for bookings:cancel holders, who may retry with ?override=true. Past bookings can never be cancelled. The booking owner is notified by email.
Parameter
idpath · stringPflichtBooking id.
overridequery · booleanSkips policy checks (deadline). Requires bookings:cancel.
Beispiel
curl -X DELETE "https://app.checkcourt.de/api/v1/bookings/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Booking cancelled.401Missing or invalid API key.403Not the owner and key lacks bookings:cancel.404Booking not found.422Already cancelled, in the past, or policy deadline passed.
200er-Schema anzeigen
successbooleanPflicht
Plätze
get/courts
Returns every court of the club, including locked and billing-locked ones, ordered by sortOrder. Use isLocked/isBillingLocked to decide whether a court is currently bookable, and activeMonths/seasonStart/seasonEnd for seasonal availability.
Beispiel
curl "https://app.checkcourt.de/api/v1/courts" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
courtsobject[]PflichtidintegerPflichtNumeric court id (stable, tenant-scoped)
tenantIdstringnamestringPflichtsurfacestringPflichtFree-text surface label, e.g. "Asche" or "Teppich"
isLockedbooleanPflichtTrue while the court is locked for booking
lockReasonstring | nullReason shown to members while locked
isBillingLockedbooleanLocked by the billing system because the subscription does not cover this court. Cannot be lifted via the API.
lockedBystring | nullUser id of whoever locked the court
lockedAtstring | null (date-time)ISO 8601 timestamp
sortOrderintegerPflichtDisplay position, ascending
bookingNoticestring | nullShort notice shown in the booking UI for this court
bookingNoticeUpdatedAtstring | null (date-time)ISO 8601 timestamp
activeMonthsinteger[]Months (1-12) in which the court is bookable. Empty means always.
seasonStartstring | nullSeason start as MM-DD; always set together with seasonEnd
seasonEndstring | nullSeason end as MM-DD
post/courts
Creates a court and appends it to the end of the sort order. The number of courts is limited by the club's subscription plan; exceeding it returns 422. Season and notice fields can be set afterwards via PATCH.
Request-Body
namestringPflichtsurfacestringPflicht
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/courts" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"name":"name","surface":"surface"}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
courtobjectPflichtidintegerPflichtNumeric court id (stable, tenant-scoped)
tenantIdstringnamestringPflichtsurfacestringPflichtFree-text surface label, e.g. "Asche" or "Teppich"
isLockedbooleanPflichtTrue while the court is locked for booking
lockReasonstring | nullReason shown to members while locked
isBillingLockedbooleanLocked by the billing system because the subscription does not cover this court. Cannot be lifted via the API.
lockedBystring | nullUser id of whoever locked the court
lockedAtstring | null (date-time)ISO 8601 timestamp
sortOrderintegerPflichtDisplay position, ascending
bookingNoticestring | nullShort notice shown in the booking UI for this court
bookingNoticeUpdatedAtstring | null (date-time)ISO 8601 timestamp
activeMonthsinteger[]Months (1-12) in which the court is bookable. Empty means always.
seasonStartstring | nullSeason start as MM-DD; always set together with seasonEnd
seasonEndstring | nullSeason end as MM-DD
post/courts/reorder
Replaces the display order. Send ALL court ids of the club in the desired order; the array index becomes the new sortOrder.
Request-Body
courtIdsinteger[]Pflicht
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/courts/reorder" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"courtIds":[]}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflicht
get/courts/{id}
Returns the court plus its next bookings (capped at 20, starting today) and any scheduled lock windows. Bookings include the booker's display name, which is why this endpoint requires the confidential read scope rather than plain courts:read.
Parameter
idpath · integerPflichtNumeric court id
Beispiel
curl "https://app.checkcourt.de/api/v1/courts/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
courtobjectPflichtidintegerPflichtNumeric court id (stable, tenant-scoped)
tenantIdstringnamestringPflichtsurfacestringPflichtFree-text surface label, e.g. "Asche" or "Teppich"
isLockedbooleanPflichtTrue while the court is locked for booking
lockReasonstring | nullReason shown to members while locked
isBillingLockedbooleanLocked by the billing system because the subscription does not cover this court. Cannot be lifted via the API.
lockedBystring | nullUser id of whoever locked the court
lockedAtstring | null (date-time)ISO 8601 timestamp
sortOrderintegerPflichtDisplay position, ascending
bookingNoticestring | nullShort notice shown in the booking UI for this court
bookingNoticeUpdatedAtstring | null (date-time)ISO 8601 timestamp
activeMonthsinteger[]Months (1-12) in which the court is bookable. Empty means always.
seasonStartstring | nullSeason start as MM-DD; always set together with seasonEnd
seasonEndstring | nullSeason end as MM-DD
upcomingBookingsobject[]PflichtNext bookings from today on, capped at 20
idstringBooking id (CUID)
typestringBooking type, e.g. "regular" or "mannschaft"
datestring (date)startTimestringTime of day as HH:MM or HH:MM:SS
endTimestringTime of day as HH:MM or HH:MM:SS
titlestring | nullbookedByNamestring | nullDisplay name of the booker, or the team name for team bookings
lockRangesobject[]PflichtfromDatestring (date)toDatestring (date)fromTimestringTime of day as HH:MM or HH:MM:SS
toTimestringTime of day as HH:MM or HH:MM:SS
titlestring | null
lockedByUserstring | nullDisplay name of the user who locked the court
isBillingLockedboolean
patch/courts/{id}
Partial update: omitted fields stay unchanged, explicit null clears nullable fields. seasonStart and seasonEnd must be set or cleared together. The current month cannot be removed from activeMonths while it is active, because that would strand existing bookings.
Parameter
idpath · integerPflichtNumeric court id
Request-Body
namestringsurfacestringbookingNoticestring | nullactiveMonthsinteger[]seasonStartstring | nullMM-DD
seasonEndstring | nullMM-DD
Beispiel
curl -X PATCH "https://app.checkcourt.de/api/v1/courts/{id}" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
courtIdintegerPflicht
delete/courts/{id}
Destructive: cancels every future booking on the court and emails the affected members a summary. Courts that are part of the current billing period cannot be deleted (422) unless the caller is a platform support user passing forceBillingActive=true.
Parameter
idpath · integerPflichtNumeric court id
forceBillingActivequery · booleanPlatform support only: delete even though the court is billed this month
Beispiel
curl -X DELETE "https://app.checkcourt.de/api/v1/courts/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
cancelledBookingsintegerPflichtNumber of future bookings that were cancelled
post/courts/{id}/lock
Without dates, the court is locked immediately and indefinitely until unlocked. With fromDate/toDate (both required together) a scheduled lock window is created; fromTime/toTime default to 07:00-21:00. Future bookings overlapping the lock are cancelled automatically and the bookers are notified by email. The reason is displayed to members in the booking UI.
Parameter
idpath · integerPflichtNumeric court id
Request-Body
reasonstringPflichtfromDatestring (date)toDatestring (date)fromTimestringTime of day as HH:MM or HH:MM:SS
toTimestringTime of day as HH:MM or HH:MM:SS
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/courts/{id}/lock" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"reason":"reason"}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
courtIdintegerPflicht
post/courts/{id}/unlock
Lifts a manual lock and removes scheduled lock windows. Billing locks (isBillingLocked) are managed by the subscription system and cannot be lifted here (422).
Parameter
idpath · integerPflichtNumeric court id
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/courts/{id}/unlock" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
courtIdintegerPflicht
Mitglieder
Namenslisten erfordern members:read; Kontaktdaten und weitere
personenbezogene Daten erfordern members:read_confidential.
get/members
Returns the full member directory including contact data, 20 per page. search matches name, email, forwarding email, member number and member code (case-insensitive substring). Members awaiting admin approval are sorted first, then alphabetically by name.
Parameter
searchquery · stringSubstring search across name, email, forwarding email, member number, member code
rolequery · "member" | "trainer" | "admin"Only members with this role
pagequery · integer1-based page number
Beispiel
curl "https://app.checkcourt.de/api/v1/members" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
membersobject[]PflichtidstringPflichtUser id (CUID). Use this in /members/{id} paths.
namestringPflichtemailstring (email)PflichtforwardingEmailstring | null (email)Set for accounts without their own mailbox: mail is sent here instead, and
emailis a synthetic addressmemberNumberstring | nullClub-assigned member number, unique per tenant
role"member" | "trainer" | "admin"PflichtTenant role of a member
guestFeesAccumulatedintegerAmount in euro cents
emailVerifiedbooleanadminApprovalPendingbooleanTrue while a self-registered member awaits admin approval
totalintegerPflichtTotal matching members across all pages
pageintegerPflichtpageSizeintegerPflichttotalPagesintegerPflicht
post/members
Adds a member to the club. Three flows, decided by the input:
1. Email already has an account (in no other club): the existing user is added to this club.
2. New email: a new account is created and, unless sendEmail=false, a welcome mail with a claim link is sent.
3. `noOwnEmail=true`: for members without their own mailbox. Creates an account with a synthetic address, stores the given email as forwarding address and requires a password (min 8 chars) the member uses to log in.
Fails with 422 when the club's member limit is reached, the member number is taken, the email already belongs to this club, or the data processing agreement (AVV) has not been signed yet.
Request-Body
emailstring (email)PflichtnamestringPflichtrole"member" | "trainer" | "admin"PflichtTenant role of a member
sendEmailbooleandefault: trueSend the welcome email
noOwnEmailbooleandefault: falseCreate a forwarding-only account (flow 3)
passwordstringRequired when noOwnEmail=true
memberNumberstring
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/members" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"email":"email","name":"name","role":"member"}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflicht
get/members/{id}
Full member record including phone, member code and creation date.
Parameter
idpath · stringPflichtUser id of the member (the
idfield from list responses)
Beispiel
curl "https://app.checkcourt.de/api/v1/members/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
memberobjectPflichtidstringPflichtUser id (CUID)
namestringPflichtemailstring (email)PflichtforwardingEmailstring | null (email)role"member" | "trainer" | "admin"PflichtTenant role of a member
memberNumberstring | nullmitgliedscodestring | nullShort member code used for on-site identification
phonestring | nullguestFeesAccumulatedintegerAmount in euro cents
createdAtstring (date-time)ISO 8601 timestamp
emailVerifiedbooleanadminApprovalPendingboolean
patch/members/{id}
name, email and role are required (send the current values to keep them); phone and memberNumber are optional. For forwarding-only accounts the email update changes the forwarding address, not the login address. If the user is also a member of another club, name/email/phone are left untouched (they are account-level) and only role and member number change. Sessions cannot edit their own account; management keys are exempt from that rule. Member numbers are unique per club (422 on collision).
Parameter
idpath · stringPflichtUser id of the member (the
idfield from list responses)
Request-Body
namestringPflichtemailstring (email)Pflichtrole"member" | "trainer" | "admin"PflichtTenant role of a member
phonestringmemberNumberstring
Beispiel
curl -X PATCH "https://app.checkcourt.de/api/v1/members/{id}" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"name":"name","email":"email","role":"member"}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflicht
delete/members/{id}
Removes the member from the club with a full cascade: future bookings are cancelled (with email notification), open guest fees are resolved according to orphanedFeeAction, and if this was the user's only club the account is anonymized. Members who lead a team cannot be deleted until leadership is handed over (422). The response summarizes what happened.
Parameter
idpath · stringPflichtUser id of the member (the
idfield from list responses)orphanedFeeActionquery · "cancelled" | "paid"Write off open guest fees (
cancelled) or mark them as paid (paid)
Beispiel
curl -X DELETE "https://app.checkcourt.de/api/v1/members/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflichtcancelledBookingCountintegerresolvedFeeCountintegerresolvedFeeTotalCentsintegerAmount in euro cents
anonymizedbooleanTrue if the account was anonymized because no other membership remained
Mannschaften
get/teams
Returns every team with aggregated counts (members, upcoming matches, recurring trainings) and the next scheduled match, so an overview UI needs no follow-up requests.
Beispiel
curl "https://app.checkcourt.de/api/v1/teams" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
teamsobject[]Pflicht
post/teams
Creates an empty team. Add players and leaders afterwards via the team-members endpoint.
Request-Body
namestringPflichtligastringspielklasse"herren" | "damen" | "mixed" | "jugend"farbestringHex color
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/teams" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"name":"name"}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
teamIdstringPflicht
get/teams/{id}
Returns the team with its roster (players and leaders), upcoming matches, one-off and recurring trainings. canManage tells whether the calling actor could use the management endpoints for this team.
Parameter
idpath · stringPflichtTeam id
Beispiel
curl "https://app.checkcourt.de/api/v1/teams/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
teamobjectPflichtidstringPflichtTeam id (CUID)
tenantIdstringnamestringPflichtligastring | nullLeague label, free text
spielklasse"herren" | "damen" | "mixed" | "jugend" | "null"Competition class of a team
farbestring | nullHex color used to mark the team's bookings
createdAtstring (date-time)ISO 8601 timestamp
updatedAtstring (date-time)ISO 8601 timestamp
membersobject[]PflichttenantUserIdstringPflichtMembership id (tenantUser). This is NOT the user id; use it when adding/removing team members.
role"player" | "leader"PflichtA person can appear twice: once as player and once as leader
userIdstringPflichtmemberNumberstring | nullnamestringPflicht
matchesobject[]PflichtUpcoming matches
idstringdatestring (date)startTimestringTime of day as HH:MM or HH:MM:SS
endTimestringTime of day as HH:MM or HH:MM:SS
titlestring | nullisAwaybooleanopponentstring | nulllocationstring | nullcourtNamesstring[]Home matches block one or more courts
oneOffTrainingsobject[]One-off training bookings (raw booking rows)
trainingsobject[]Recurring weekly trainings
canManagebooleanPflichtWhether the calling actor may manage this team (admin role or team leader)
patch/teams/{id}
Updates name, league, class or color. spielklasse: null clears the class.
Beyond the scope, this endpoint needs management rights for the specific team: the actor must have the admin role or be a leader of this team. Management keys carry no role and are therefore always rejected here; use a personal key of an admin or team leader.
Parameter
idpath · stringPflichtTeam id
Request-Body
namestringPflichtligastringspielklasse"herren" | "damen" | "mixed" | "jugend" | "null"Competition class of a team
farbestring
Beispiel
curl -X PATCH "https://app.checkcourt.de/api/v1/teams/{id}" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"name":"name"}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
teamIdstringPflicht
delete/teams/{id}
Deletes the team and its roster assignments. Team bookings are kept but lose their team link.
Parameter
idpath · stringPflichtTeam id
Beispiel
curl -X DELETE "https://app.checkcourt.de/api/v1/teams/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
teamIdstringPflicht
post/teams/{id}/members
Adds a club member to the team as player or leader. The same person can hold both roles (two separate entries). Note that tenantUserId is the membership id from the team detail response, not the user id.
Beyond the scope, this endpoint needs management rights for the specific team: the actor must have the admin role or be a leader of this team. Management keys carry no role and are therefore always rejected here; use a personal key of an admin or team leader.
Parameter
idpath · stringPflichtTeam id
Request-Body
tenantUserIdstringPflichtMembership id (tenantUser)
role"player" | "leader"Pflicht
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/teams/{id}/members" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"tenantUserId":"tenantUserId","role":"player"}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
teamIdstringPflicht
delete/teams/{id}/members/{userId}
Removes one role assignment. Because a person can be player and leader at once, the role query parameter picks which assignment to remove.
Beyond the scope, this endpoint needs management rights for the specific team: the actor must have the admin role or be a leader of this team. Management keys carry no role and are therefore always rejected here; use a personal key of an admin or team leader.
Parameter
idpath · stringPflichtTeam id
userIdpath · stringPflichtMembership id (tenantUser) of the assignment
rolequery · "player" | "leader"PflichtWhich role assignment to remove
Beispiel
curl -X DELETE "https://app.checkcourt.de/api/v1/teams/{id}/members/{userId}?role=player" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflicht
Buchungsrichtlinien
get/policies
Policies form the booking rule engine: each policy has conditions (which booking attempts it applies to) and attributes (the rule values it contributes). On every booking attempt, enabled policies are evaluated in ascending priority; for each attribute the first policy that sets it wins, and the default policy provides the fallback values. This endpoint returns all non-default policies ordered by priority. Fetch the default policy via its id if needed.
Beispiel
curl "https://app.checkcourt.de/api/v1/policies" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
policiesobject[]PflichtidstringPflichttenantIdstringnamestringPflichtdescriptionstring | nullpriorityintegerPflichtLower number = evaluated earlier
isEnabledbooleanPflichtisDefaultbooleanPflichtExactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.
conditionsobjectSelects which booking attempts a policy applies to. Omitted fields match everything; all present fields must match (AND).
daysOfWeek"mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]timeOfDayobjectfromstringTime of day as HH:MM or HH:MM:SS
tostringTime of day as HH:MM or HH:MM:SS
dateRangeobjectfromstring (date)tostring (date)
courtIdsinteger[]categoryIdsstring[]bookerRoles"member" | "trainer" | "admin"[]bookerTeamIdsstring[]bookerGroupIdsstring[]actions"create" | "cancel" | "edit"[]
attributesobjectRule values a policy contributes for matching attempts. Policies are evaluated by ascending priority; the first policy that sets an attribute wins, the default policy fills the rest.
allowbooleanHard allow/deny for matching attempts
denyReasonstringMessage shown when allow=false
maxBookingMinutesintegerminBookingMinutesintegermaxAdvanceBookingDaysintegerHow far into the future bookings may start
maxActiveBookingsintegerCap on simultaneously active (future) bookings per user
maxBookingsPerDayPerUserintegermaxParallelBookingsintegerCap on overlapping bookings per user across courts
cancellationDeadlineHoursintegerslotStartIntervalMinutesintegerAllowed booking start raster, e.g. 30 for :00/:30
slotStartOffsetMinutesintegerbookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
requireTeammatebooleanBooking requires naming at least one teammate
isNameablebooleanWhether bookings may carry a free-text title
createdAtstring (date-time)ISO 8601 timestamp
updatedAtstring (date-time)ISO 8601 timestamp
post/policies
Policies form the booking rule engine: each policy has conditions (which booking attempts it applies to) and attributes (the rule values it contributes). On every booking attempt, enabled policies are evaluated in ascending priority; for each attribute the first policy that sets it wins, and the default policy provides the fallback values. New policies are appended with the lowest priority (evaluated last before the default). Cross-field validation applies: time and date ranges must be ordered, min/max durations consistent.
Request-Body
namestringdescriptionstringisEnabledbooleandefault: trueconditionsobjectSelects which booking attempts a policy applies to. Omitted fields match everything; all present fields must match (AND).
daysOfWeek"mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]timeOfDayobjectfromstringTime of day as HH:MM or HH:MM:SS
tostringTime of day as HH:MM or HH:MM:SS
dateRangeobjectfromstring (date)tostring (date)
courtIdsinteger[]categoryIdsstring[]bookerRoles"member" | "trainer" | "admin"[]bookerTeamIdsstring[]bookerGroupIdsstring[]actions"create" | "cancel" | "edit"[]
attributesobjectRule values a policy contributes for matching attempts. Policies are evaluated by ascending priority; the first policy that sets an attribute wins, the default policy fills the rest.
allowbooleanHard allow/deny for matching attempts
denyReasonstringMessage shown when allow=false
maxBookingMinutesintegerminBookingMinutesintegermaxAdvanceBookingDaysintegerHow far into the future bookings may start
maxActiveBookingsintegerCap on simultaneously active (future) bookings per user
maxBookingsPerDayPerUserintegermaxParallelBookingsintegerCap on overlapping bookings per user across courts
cancellationDeadlineHoursintegerslotStartIntervalMinutesintegerAllowed booking start raster, e.g. 30 for :00/:30
slotStartOffsetMinutesintegerbookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
requireTeammatebooleanBooking requires naming at least one teammate
isNameablebooleanWhether bookings may carry a free-text title
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/policies" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
policyobjectPflichtidstringPflichttenantIdstringnamestringPflichtdescriptionstring | nullpriorityintegerPflichtLower number = evaluated earlier
isEnabledbooleanPflichtisDefaultbooleanPflichtExactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.
conditionsobjectSelects which booking attempts a policy applies to. Omitted fields match everything; all present fields must match (AND).
daysOfWeek"mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]timeOfDayobjectfromstringTime of day as HH:MM or HH:MM:SS
tostringTime of day as HH:MM or HH:MM:SS
dateRangeobjectfromstring (date)tostring (date)
courtIdsinteger[]categoryIdsstring[]bookerRoles"member" | "trainer" | "admin"[]bookerTeamIdsstring[]bookerGroupIdsstring[]actions"create" | "cancel" | "edit"[]
attributesobjectRule values a policy contributes for matching attempts. Policies are evaluated by ascending priority; the first policy that sets an attribute wins, the default policy fills the rest.
allowbooleanHard allow/deny for matching attempts
denyReasonstringMessage shown when allow=false
maxBookingMinutesintegerminBookingMinutesintegermaxAdvanceBookingDaysintegerHow far into the future bookings may start
maxActiveBookingsintegerCap on simultaneously active (future) bookings per user
maxBookingsPerDayPerUserintegermaxParallelBookingsintegerCap on overlapping bookings per user across courts
cancellationDeadlineHoursintegerslotStartIntervalMinutesintegerAllowed booking start raster, e.g. 30 for :00/:30
slotStartOffsetMinutesintegerbookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
requireTeammatebooleanBooking requires naming at least one teammate
isNameablebooleanWhether bookings may carry a free-text title
createdAtstring (date-time)ISO 8601 timestamp
updatedAtstring (date-time)ISO 8601 timestamp
get/policies/{id}
Parameter
idpath · stringPflichtPolicy id
Beispiel
curl "https://app.checkcourt.de/api/v1/policies/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
idstringPflichttenantIdstringnamestringPflichtdescriptionstring | nullpriorityintegerPflichtLower number = evaluated earlier
isEnabledbooleanPflichtisDefaultbooleanPflichtExactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.
conditionsobjectSelects which booking attempts a policy applies to. Omitted fields match everything; all present fields must match (AND).
daysOfWeek"mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]timeOfDayobjectfromstringTime of day as HH:MM or HH:MM:SS
tostringTime of day as HH:MM or HH:MM:SS
dateRangeobjectfromstring (date)tostring (date)
courtIdsinteger[]categoryIdsstring[]bookerRoles"member" | "trainer" | "admin"[]bookerTeamIdsstring[]bookerGroupIdsstring[]actions"create" | "cancel" | "edit"[]
attributesobjectRule values a policy contributes for matching attempts. Policies are evaluated by ascending priority; the first policy that sets an attribute wins, the default policy fills the rest.
allowbooleanHard allow/deny for matching attempts
denyReasonstringMessage shown when allow=false
maxBookingMinutesintegerminBookingMinutesintegermaxAdvanceBookingDaysintegerHow far into the future bookings may start
maxActiveBookingsintegerCap on simultaneously active (future) bookings per user
maxBookingsPerDayPerUserintegermaxParallelBookingsintegerCap on overlapping bookings per user across courts
cancellationDeadlineHoursintegerslotStartIntervalMinutesintegerAllowed booking start raster, e.g. 30 for :00/:30
slotStartOffsetMinutesintegerbookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
requireTeammatebooleanBooking requires naming at least one teammate
isNameablebooleanWhether bookings may carry a free-text title
createdAtstring (date-time)ISO 8601 timestamp
updatedAtstring (date-time)ISO 8601 timestamp
patch/policies/{id}
Replaces the given fields. The default policy is special: it cannot be renamed, its conditions are immutable (it always matches everything), and its attributes can only be extended so that every attribute keeps a fallback value.
Parameter
idpath · stringPflichtPolicy id
Request-Body
namestringdescriptionstringisEnabledbooleandefault: trueconditionsobjectSelects which booking attempts a policy applies to. Omitted fields match everything; all present fields must match (AND).
daysOfWeek"mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]timeOfDayobjectfromstringTime of day as HH:MM or HH:MM:SS
tostringTime of day as HH:MM or HH:MM:SS
dateRangeobjectfromstring (date)tostring (date)
courtIdsinteger[]categoryIdsstring[]bookerRoles"member" | "trainer" | "admin"[]bookerTeamIdsstring[]bookerGroupIdsstring[]actions"create" | "cancel" | "edit"[]
attributesobjectRule values a policy contributes for matching attempts. Policies are evaluated by ascending priority; the first policy that sets an attribute wins, the default policy fills the rest.
allowbooleanHard allow/deny for matching attempts
denyReasonstringMessage shown when allow=false
maxBookingMinutesintegerminBookingMinutesintegermaxAdvanceBookingDaysintegerHow far into the future bookings may start
maxActiveBookingsintegerCap on simultaneously active (future) bookings per user
maxBookingsPerDayPerUserintegermaxParallelBookingsintegerCap on overlapping bookings per user across courts
cancellationDeadlineHoursintegerslotStartIntervalMinutesintegerAllowed booking start raster, e.g. 30 for :00/:30
slotStartOffsetMinutesintegerbookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
requireTeammatebooleanBooking requires naming at least one teammate
isNameablebooleanWhether bookings may carry a free-text title
Beispiel
curl -X PATCH "https://app.checkcourt.de/api/v1/policies/{id}" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
policyobjectPflichtidstringPflichttenantIdstringnamestringPflichtdescriptionstring | nullpriorityintegerPflichtLower number = evaluated earlier
isEnabledbooleanPflichtisDefaultbooleanPflichtExactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.
conditionsobjectSelects which booking attempts a policy applies to. Omitted fields match everything; all present fields must match (AND).
daysOfWeek"mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]timeOfDayobjectfromstringTime of day as HH:MM or HH:MM:SS
tostringTime of day as HH:MM or HH:MM:SS
dateRangeobjectfromstring (date)tostring (date)
courtIdsinteger[]categoryIdsstring[]bookerRoles"member" | "trainer" | "admin"[]bookerTeamIdsstring[]bookerGroupIdsstring[]actions"create" | "cancel" | "edit"[]
attributesobjectRule values a policy contributes for matching attempts. Policies are evaluated by ascending priority; the first policy that sets an attribute wins, the default policy fills the rest.
allowbooleanHard allow/deny for matching attempts
denyReasonstringMessage shown when allow=false
maxBookingMinutesintegerminBookingMinutesintegermaxAdvanceBookingDaysintegerHow far into the future bookings may start
maxActiveBookingsintegerCap on simultaneously active (future) bookings per user
maxBookingsPerDayPerUserintegermaxParallelBookingsintegerCap on overlapping bookings per user across courts
cancellationDeadlineHoursintegerslotStartIntervalMinutesintegerAllowed booking start raster, e.g. 30 for :00/:30
slotStartOffsetMinutesintegerbookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
requireTeammatebooleanBooking requires naming at least one teammate
isNameablebooleanWhether bookings may carry a free-text title
createdAtstring (date-time)ISO 8601 timestamp
updatedAtstring (date-time)ISO 8601 timestamp
delete/policies/{id}
The default policy cannot be deleted (422).
Parameter
idpath · stringPflichtPolicy id
Beispiel
curl -X DELETE "https://app.checkcourt.de/api/v1/policies/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflichtidstringPflicht
post/policies/{id}/toggle
Disabled policies are skipped during evaluation but keep their priority slot.
Parameter
idpath · stringPflichtPolicy id
Request-Body
enabledbooleanPflicht
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/policies/{id}/toggle" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"enabled":true}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
policyobjectPflichtidstringPflichttenantIdstringnamestringPflichtdescriptionstring | nullpriorityintegerPflichtLower number = evaluated earlier
isEnabledbooleanPflichtisDefaultbooleanPflichtExactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.
conditionsobjectSelects which booking attempts a policy applies to. Omitted fields match everything; all present fields must match (AND).
daysOfWeek"mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"[]timeOfDayobjectfromstringTime of day as HH:MM or HH:MM:SS
tostringTime of day as HH:MM or HH:MM:SS
dateRangeobjectfromstring (date)tostring (date)
courtIdsinteger[]categoryIdsstring[]bookerRoles"member" | "trainer" | "admin"[]bookerTeamIdsstring[]bookerGroupIdsstring[]actions"create" | "cancel" | "edit"[]
attributesobjectRule values a policy contributes for matching attempts. Policies are evaluated by ascending priority; the first policy that sets an attribute wins, the default policy fills the rest.
allowbooleanHard allow/deny for matching attempts
denyReasonstringMessage shown when allow=false
maxBookingMinutesintegerminBookingMinutesintegermaxAdvanceBookingDaysintegerHow far into the future bookings may start
maxActiveBookingsintegerCap on simultaneously active (future) bookings per user
maxBookingsPerDayPerUserintegermaxParallelBookingsintegerCap on overlapping bookings per user across courts
cancellationDeadlineHoursintegerslotStartIntervalMinutesintegerAllowed booking start raster, e.g. 30 for :00/:30
slotStartOffsetMinutesintegerbookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
requireTeammatebooleanBooking requires naming at least one teammate
isNameablebooleanWhether bookings may carry a free-text title
createdAtstring (date-time)ISO 8601 timestamp
updatedAtstring (date-time)ISO 8601 timestamp
post/policies/reorder
Send all non-default policy ids in the desired evaluation order (first = highest precedence). Priorities are reassigned accordingly.
Request-Body
orderedIdsstring[]Pflicht
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/policies/reorder" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"orderedIds":[]}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflicht
get/booking-policies
Evaluates the whole policy engine for the calling actor's role and returns the resolved rule values per court and per booking category, plus the categories the actor may book in. This is what the booking UI uses to know slot lengths, advance limits and quotas.
Only meaningful with personal keys: management keys have no role to evaluate against and receive 400.
Beispiel
curl "https://app.checkcourt.de/api/v1/booking-policies" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
role"member" | "trainer" | "admin"Tenant role of a member
evaluatedAtstring (date-time)ISO 8601 timestamp
courtsobject[]courtIdintegercourtNamestringattributesobjectRule values a policy contributes for matching attempts. Policies are evaluated by ascending priority; the first policy that sets an attribute wins, the default policy fills the rest.
allowbooleanHard allow/deny for matching attempts
denyReasonstringMessage shown when allow=false
maxBookingMinutesintegerminBookingMinutesintegermaxAdvanceBookingDaysintegerHow far into the future bookings may start
maxActiveBookingsintegerCap on simultaneously active (future) bookings per user
maxBookingsPerDayPerUserintegermaxParallelBookingsintegerCap on overlapping bookings per user across courts
cancellationDeadlineHoursintegerslotStartIntervalMinutesintegerAllowed booking start raster, e.g. 30 for :00/:30
slotStartOffsetMinutesintegerbookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
requireTeammatebooleanBooking requires naming at least one teammate
isNameablebooleanWhether bookings may carry a free-text title
perCategoryobject[]categoryIdstringcategorySlugstringcategoryNamestringattributesobjectRule values a policy contributes for matching attempts. Policies are evaluated by ascending priority; the first policy that sets an attribute wins, the default policy fills the rest.
allowbooleanHard allow/deny for matching attempts
denyReasonstringMessage shown when allow=false
maxBookingMinutesintegerminBookingMinutesintegermaxAdvanceBookingDaysintegerHow far into the future bookings may start
maxActiveBookingsintegerCap on simultaneously active (future) bookings per user
maxBookingsPerDayPerUserintegermaxParallelBookingsintegerCap on overlapping bookings per user across courts
cancellationDeadlineHoursintegerslotStartIntervalMinutesintegerAllowed booking start raster, e.g. 30 for :00/:30
slotStartOffsetMinutesintegerbookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
requireTeammatebooleanBooking requires naming at least one teammate
isNameablebooleanWhether bookings may carry a free-text title
grantedCategoryIdsstring[]Categories the actor may book in
Buchungskategorien
get/booking-categories
Categories classify bookings (e.g. regular play, training, match) and control visibility: isPublic decides whether other members see details, anonymizeGuests hides guest names. System categories (isSystem) are created automatically and have stable slugs.
Beispiel
curl "https://app.checkcourt.de/api/v1/booking-categories" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
categoriesobject[]PflichtidstringPflichttenantIdstringnamestringPflichtslugstringPflichtStable identifier; system categories use fixed slugs like "regular"
colorstringPflichtHex color from the predefined palette
isSystembooleanPflichtSystem categories cannot be renamed or deleted
isPublicbooleanWhether bookings in this category show details to other members
anonymizeGuestsbooleanallowUserTogglebooleanMembers may toggle visibility per booking
allowUserToggleGuestsbooleansortOrderintegercreatedAtstring (date-time)ISO 8601 timestamp
updatedAtstring (date-time)ISO 8601 timestamp
post/booking-categories
Creates a custom category. color must come from the predefined palette; the number of categories per club is capped (422 when reached). Visibility flags can be adjusted afterwards via PATCH.
Request-Body
namestringPflichtcolorstringPflichtHex color from the predefined palette
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/booking-categories" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"name":"name","color":"color"}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
categoryobjectPflichtidstringPflichttenantIdstringnamestringPflichtslugstringPflichtStable identifier; system categories use fixed slugs like "regular"
colorstringPflichtHex color from the predefined palette
isSystembooleanPflichtSystem categories cannot be renamed or deleted
isPublicbooleanWhether bookings in this category show details to other members
anonymizeGuestsbooleanallowUserTogglebooleanMembers may toggle visibility per booking
allowUserToggleGuestsbooleansortOrderintegercreatedAtstring (date-time)ISO 8601 timestamp
updatedAtstring (date-time)ISO 8601 timestamp
patch/booking-categories/{id}
Partial update. System categories cannot be renamed (422), but their visibility flags and color may be changed.
Parameter
idpath · stringPflichtCategory id
Request-Body
namestringcolorstringisPublicbooleananonymizeGuestsbooleanallowUserTogglebooleanallowUserToggleGuestsbooleansortOrderinteger
Beispiel
curl -X PATCH "https://app.checkcourt.de/api/v1/booking-categories/{id}" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
categoryobjectPflichtidstringPflichttenantIdstringnamestringPflichtslugstringPflichtStable identifier; system categories use fixed slugs like "regular"
colorstringPflichtHex color from the predefined palette
isSystembooleanPflichtSystem categories cannot be renamed or deleted
isPublicbooleanWhether bookings in this category show details to other members
anonymizeGuestsbooleanallowUserTogglebooleanMembers may toggle visibility per booking
allowUserToggleGuestsbooleansortOrderintegercreatedAtstring (date-time)ISO 8601 timestamp
updatedAtstring (date-time)ISO 8601 timestamp
delete/booking-categories/{id}
System categories cannot be deleted (422). Existing bookings of a deleted category are reassigned to the default ("regular") category.
Parameter
idpath · stringPflichtCategory id
Beispiel
curl -X DELETE "https://app.checkcourt.de/api/v1/booking-categories/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflicht
Gastgebühren
get/guest-fees
History of guest fees that have been marked as paid, newest settlement first. search matches the guest's name and the owing member's name or email. Use userId to see one member's history.
Parameter
searchquery · stringSubstring search in guest name, member name, member email
userIdquery · stringOnly fees owed by this member (user id)
pagequery · integer1-based page number
pageSizequery · integerEntries per page
Beispiel
curl "https://app.checkcourt.de/api/v1/guest-fees" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
entriesobject[]PflichtidstringguestNamestringfeeAmountintegerAmount in euro cents
settledAtstring (date-time)ISO 8601 timestamp
createdAtstring (date-time)ISO 8601 timestamp
memberIdstringUser id of the member who owes/paid the fee
memberNamestringmemberEmailstring (email)bookingDatestring (date)
totalintegerPflichtpageintegerPflichtpageSizeintegerPflichttotalPagesintegerPflicht
get/guest-fees/open
All unsettled guest fees one member currently owes, including the booking context (date, time, court) each fee originated from.
Parameter
userIdquery · stringPflichtUser id of the member
Beispiel
curl "https://app.checkcourt.de/api/v1/guest-fees/open?userId=userId" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
entriesobject[]PflichtidstringguestNamestringfeeAmountintegerAmount in euro cents
createdAtstring (date-time)ISO 8601 timestamp
bookingDatestring (date)bookingStartTimestringTime of day as HH:MM or HH:MM:SS
bookingEndTimestringTime of day as HH:MM or HH:MM:SS
courtNamestring
get/guest-fees/members
Distinct members that have at least one settled guest fee. Intended to populate filter dropdowns for the history view.
Beispiel
curl "https://app.checkcourt.de/api/v1/guest-fees/members" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
membersobject[]PflichtidstringPflichtnamestringPflicht
delete/guest-fees/{entryId}
Moves a fee entry back from "paid" to "open", e.g. after marking the wrong entry. Only entries currently marked as paid can be reverted (400 otherwise).
Parameter
entryIdpath · stringPflichtGuest fee entry id
Beispiel
curl -X DELETE "https://app.checkcourt.de/api/v1/guest-fees/{entryId}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflicht
post/guest-fees/reset
Marks open fees as paid. Provide exactly ONE of the two parameters: targetUserId settles all open fees of one member (typical after they paid in person); untilDate settles all open fees of the whole club created on or before that date (typical after a billing cut-off).
Request-Body
targetUserIdstringUser id; settles this member's open fees
untilDatestring (date)Settles all open fees created on or before this date
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/guest-fees/reset" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflicht
Einladungslinks
get/invite-links
All invite links of the club with usage stats. The public join URL for a link is /join/{code} on the web app host.
Beispiel
curl "https://app.checkcourt.de/api/v1/invite-links" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
inviteLinksobject[]PflichtidintegerPflichtNumeric link id
codestringPflicht12-character alphanumeric code; the public join URL is /join/{code}
notestring | nullInternal note, e.g. where the link was published
maxUsesinteger | nullnull = unlimited
usesCountintegerPflichtcreatedAtstring (date-time)ISO 8601 timestamp
lastUsedAtstring | null (date-time)ISO 8601 timestamp
createdByIdstring | nullcreatedByNamestring | nullrequiresAdminApprovalbooleanPflichtIf true, members joining via this link stay in "pending" state until an admin approves them
post/invite-links
Creates a shareable self-signup link. maxUses limits how many members can join through it (null = unlimited). With requiresAdminApproval=true, members joining via this link stay in a pending state and cannot book until an admin approves them. Requires the club's signed data processing agreement (AVV), otherwise 422.
Request-Body
notestringInternal note, e.g. where the link is published
maxUsesinteger | nullrequiresAdminApprovalbooleandefault: false
Beispiel
curl -X POST "https://app.checkcourt.de/api/v1/invite-links" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
inviteLinkobjectPflichtidintegerPflichtNumeric link id
codestringPflicht12-character alphanumeric code; the public join URL is /join/{code}
notestring | nullInternal note, e.g. where the link was published
maxUsesinteger | nullnull = unlimited
usesCountintegerPflichtcreatedAtstring (date-time)ISO 8601 timestamp
lastUsedAtstring | null (date-time)ISO 8601 timestamp
createdByIdstring | nullcreatedByNamestring | nullrequiresAdminApprovalbooleanPflichtIf true, members joining via this link stay in "pending" state until an admin approves them
patch/invite-links/{id}
At least one of the two fields must be present. The code and usage counters of a link cannot be changed; create a new link instead.
Parameter
idpath · integerPflichtNumeric invite link id
Request-Body
notestringrequiresAdminApprovalboolean
Beispiel
curl -X PATCH "https://app.checkcourt.de/api/v1/invite-links/{id}" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflichtidintegerPflicht
delete/invite-links/{id}
The link stops working immediately. Members who already joined through it are unaffected.
Parameter
idpath · integerPflichtNumeric invite link id
Beispiel
curl -X DELETE "https://app.checkcourt.de/api/v1/invite-links/{id}" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
successbooleanPflichtidintegerPflicht
Einstellungen
get/settings
Returns the whitelisted club settings (dashboard announcement, check-in, guest fees, club name, timezone). Keys without a stored value are omitted from the response. All values are strings; see the Settings schema for the semantic type of each key.
Beispiel
curl "https://app.checkcourt.de/api/v1/settings" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
settingsobjectPflichtWhitelisted club settings. The backing store is a string key-value table, so every value is a string:
checkin_enabledandguest_fees_enabledare "true"/"false",checkin_deadline_minutesandguest_fee_centsare integers encoded as strings,timezoneis an IANA zone like "Europe/Berlin".announcement_textstringBanner text shown on the dashboard; empty string hides the banner
announcement_linkstringOptional URL the announcement banner links to
checkin_deadline_minutesstringInteger as string; minutes after booking start until check-in expires
checkin_enabled"true" | "false"club_namestringguest_fee_centsstringInteger as string; fee per guest in cents
guest_fees_enabled"true" | "false"timezonestring
patch/settings
Merge semantics: only the keys you send are written, others stay unchanged. Keys outside the whitelist are silently ignored, values are capped at 2000 characters. The response reports how many settings actually changed.
Request-Body
announcement_textstringBanner text shown on the dashboard; empty string hides the banner
announcement_linkstringOptional URL the announcement banner links to
checkin_deadline_minutesstringInteger as string; minutes after booking start until check-in expires
checkin_enabled"true" | "false"club_namestringguest_fee_centsstringInteger as string; fee per guest in cents
guest_fees_enabled"true" | "false"timezonestring
Beispiel
curl -X PATCH "https://app.checkcourt.de/api/v1/settings" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing429More than 60 requests per minute from one IP
200er-Schema anzeigen
updatedintegerPflichtNumber of settings whose value changed
Verein
get/tenant
Id, display name and short code of the club the API key belongs to. Useful as a connectivity check and to label data in integrations.
Beispiel
curl "https://app.checkcourt.de/api/v1/tenant" \
-H "Authorization: Bearer ck_mgmt_…"Antworten
200Success401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing404Resource does not exist in this club429More than 60 requests per minute from one IP
200er-Schema anzeigen
tenantobjectPflichtidstringPflichtnamestringPflichtClub name
slugstringPflichtShort club code (uppercase letters and digits), used e.g. in member codes
patch/tenant
The slug appears in member codes and on-site displays. Input is normalized to uppercase A-Z and 0-9, then length-checked (3-8 chars) and checked for uniqueness across all clubs (422 if taken).
Request-Body
slugstringPflicht
Beispiel
curl -X PATCH "https://app.checkcourt.de/api/v1/tenant" \
-H "Authorization: Bearer ck_mgmt_…" \
-H "Content-Type: application/json" \
-d '{"slug":"slug"}'Antworten
200Success400Request is syntactically or semantically invalid401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club403The key lacks the required scope, or team management rights are missing422Request is valid but violates a business rule (limit reached, duplicate, protected resource)429More than 60 requests per minute from one IP
200er-Schema anzeigen
slugstringPflichtThe normalized slug that was stored