CheckCourt

API reference

All endpoints of the CheckCourt REST API v1

Requires enablement

API keys are an enterprise feature and must be requested from support. Without enablement, the API rejects every key with 401 UNAUTHORIZED. Apps don't need the club to have API keys enabled; they use their own tokens.

Base URL: https://app.checkcourt.de/api/v1 · Authentication via Authorization: Bearer <key or token> · Responses are always named JSON objects, errors always { "error": { "code", "message" } }. Basics and error codes are in the developer overview.

Which key can do what?

Each endpoint below carries badges that show which kind of key can call it. There are two categories:

CategoryEndpointsRule
UniversalEverything club-scoped (courts, members, bookings, ...)The scope decides, not the kind of key: personal keys carry the scopes from the member's roles, management keys their explicitly granted ones. Personal keys always need X-Tenant-Id for this.
Personal keys only/me/*Self-service with the member's identity: your own clubs, reading and creating your own bookings.

Each endpoint has exactly one meaning: /me/* acts for the user behind the key, everything else manages club resources by scope. POST /me/bookings books for yourself, POST /bookings books on behalf of a member (forUserId). There are deliberately no endpoints that only management keys can call: management keys are limited by scopes, not by endpoints of their own. DELETE /bookings/{id} is intentionally shared, "cancel this booking" is one meaning. Whether ownership or the bookings:cancel scope allows it is decided at runtime. Roles are the exception: only a personal key can change them (roles:manage).

What about apps?

App tokens call the same endpoints. A club app token (cca_…) behaves like a management key, a member token (ccu_…) like a personal key and may also use /me/*. In addition:

  • The UI's visibility rules always apply to apps, even with confidential scopes. Hidden bookers stay null, and respectPrivacy is always on for apps.
  • Roles (/roles, /members/{id}/roles) and creating or changing webhook endpoints are blocked for apps.

All details in API for apps.

Your clubs

Personal keys are bound to the user: the club is specified per request via the X-Tenant-Id header. This endpoint returns the club IDs and your roles in each club. It does not need the header itself. With a member app token, it returns only the clubs in which the app is connected, without roles.

get/me
Who am I (member app tokens)
Member app token

Only for member app tokens (ccu_); API keys and installation tokens receive 401. Returns a pseudonymous user_id and the clubs where the app is connected. user_id is stable for your app (across clubs, reconnects and token rotation) and different for every other app, so use it as the key of the member's account in your app. It is not the CheckCourt user ID that appears in API objects, webhook payloads and extension context tokens, and it cannot be resolved to one. Name and email are not part of the response.

Example

curl "https://app.checkcourt.de/api/v1/me" \
  -H "Authorization: Bearer ccu_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • user_idstringrequired

    Pairwise pseudonym of the member for this app: stable for your app, different for every other app.

  • tenantsobject[]required

    Clubs where the member has your app connected and running.

    • idstringrequired
    • namestringrequired
get/me/tenants
List the caller's clubs
Personal key

Lists every club the member behind the personal API key belongs to, with the roles 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. Member app tokens (ccu_) get only the clubs where the app is connected, with id and name and without roles.

Example

curl "https://app.checkcourt.de/api/v1/me/tenants" \
  -H "Authorization: Bearer ck_user_…"

Responses

  • 200The caller's club memberships.
  • 401Missing/invalid key, management key, or no club of the user has personal keys enabled.
200er-Schema anzeigen
  • tenantsobject[]
    • idstring
    • namestring
    • rolesobject[]

      The caller's roles in THIS club, highest first, Mitglied (member) last; a user can be Administrator in one club and only Mitglied in another.

      • idstringrequired

        Role id, as in GET /roles

      • namestringrequired
      • systemKey"admin" | "trainer" | "member" | "null"required

        Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

Bookings

Read availability, book and cancel courts. Your own bookings work with personal keys without any special scope. You only need bookings:write and bookings:cancel to access other people's bookings. The daily listing with names (for syncing and reporting) requires bookings:read_confidential. For anonymous occupancy under /availability, bookings:read is enough.

get/me/bookings
List the caller's own upcoming bookings
Personal keybookings:read

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.

Example

curl "https://app.checkcourt.de/api/v1/me/bookings" \
  -H "Authorization: Bearer ck_user_…"

Responses

  • 200Own upcoming bookings.
  • 401Missing or invalid API key.
  • 403Key lacks bookings:read or has no member identity.
200er-Schema anzeigen
  • bookingsobject[]
    • idstring
    • courtIdinteger
    • courtNamestring
    • typestring
    • datestring (date)
    • startTimestring
    • endTimestring
    • titlestring | null
    • cancelledAtstring | null (date-time)
    • cancelReasonstring | null
post/me/bookings
Book a court for yourself
Personal keybookings:read (personal keys only)

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

  • courtIdintegerrequired
  • datestring (date)required
  • startTimestringrequired
  • endTimestringrequired
  • titlestring
  • notesstring
  • bookingType"regular" | "training" | "mannschaft"
  • categoryIdstring
  • teamIdstring

    Required when bookingType is mannschaft.

  • playersobject[]

    Co-players. Members are referenced by userId, guests carry a guestName (guest fees may apply).

    • userIdstring
    • guestNamestring
    • isGuestbooleanrequired
  • adminOverrideboolean

    Skips all policy attribute checks (booking hours, advance limit, quotas). Requires bookings:write. Hard integrity checks (court lock, time conflict, past date) still apply.

Example

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"}'

Responses

  • 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
  • bookingobject
    • idstring

      Booking id (UUID).

    • courtIdinteger
    • type"regular" | "training" | "mannschaft"

      Booking kind. mannschaft bookings belong to a team and have no personal owner.

    • datestring (date)
    • startTimestring
    • endTimestring
    • titlestring | null
    • bookedBystring | null

      User id of the booking owner. null for mannschaft bookings.

    • teamIdstring | null
get/availability
Court occupancy for one day
Personal keyManagement keybookings:read

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.

Parameters

  • datequery · string (date)required

    Calendar day to evaluate (YYYY-MM-DD)

Example

curl "https://app.checkcourt.de/api/v1/availability?date=2026-06-15" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • datestring (date)required
  • courtsobject[]required
    • courtIdintegerrequired
    • courtNamestringrequired
    • isLockedbooleanrequired

      True while the court is locked entirely (independent of slots)

    • occupiedobject[]required
      • startTimestringrequired

        Time of day as HH:MM or HH:MM:SS

      • endTimestringrequired

        Time of day as HH:MM or HH:MM:SS

      • kind"booking" | "lock"required

        Whether the interval is a booking or a scheduled lock window

get/availability/slots
Bookable start times per court
Personal keyManagement keybookings:read

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.

Parameters

  • datequery · string (date)required
  • durationMinutesquery · integer

    Desired booking length. With an active slot raster, only durations that are a multiple of the raster interval yield slots.

Example

curl "https://app.checkcourt.de/api/v1/availability/slots?date=2026-06-15" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 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)
  • durationMinutesinteger
  • courtsobject[]
    • courtIdinteger
    • courtNamestring
    • slotsstring[]
get/bookings
All bookings of one day, with booker names
Personal keyManagement keybookings:read_confidential

The reconciliation view for integrations: every booking of the given day including booker names, titles, check-in and cancellation state, i.e. 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. App tokens always get these rules, whatever respectPrivacy says; a member app still sees its own member's bookings in full.

Parameters

  • datequery · string (date)required
  • respectPrivacyquery · boolean

    Applies the member-facing privacy rules (booking-level showName, category default): bookings whose booker chose to hide their name come back with bookedBy and bookerName set 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.

Example

curl "https://app.checkcourt.de/api/v1/bookings?date=2026-06-15" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 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[]
    • idstring
    • courtIdinteger
    • courtNamestring
    • typestring
    • datestring (date)
    • startTimestring
    • endTimestring
    • titlestring | null
    • bookedBystring | null

      User id of the owner; null for mannschaft bookings.

    • bookerNamestring | null
    • teamIdstring | null
    • checkedInAtstring | null (date-time)
    • cancelledAtstring | null (date-time)
    • cancelReasonstring | null
post/bookings
Book a court on behalf of a member
Personal keyManagement keybookings:write

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

  • courtIdintegerrequired
  • datestring (date)required
  • startTimestringrequired
  • endTimestringrequired
  • titlestring
  • notesstring
  • bookingType"regular" | "training" | "mannschaft"
  • categoryIdstring
  • teamIdstring

    Required when bookingType is mannschaft.

  • playersobject[]

    Co-players. Members are referenced by userId, guests carry a guestName (guest fees may apply).

    • userIdstring
    • guestNamestring
    • isGuestbooleanrequired
  • forUserIdstringrequired

    The member this booking is created FOR: it belongs to them and consumes their quota. Mandatory; booking for yourself is POST /me/bookings.

  • adminOverrideboolean

    Skips all policy attribute checks (booking hours, advance limit, quotas). Requires bookings:write. Hard integrity checks (court lock, time conflict, past date) still apply.

Example

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"}'

Responses

  • 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
  • bookingobject
    • idstring

      Booking id (UUID).

    • courtIdinteger
    • type"regular" | "training" | "mannschaft"

      Booking kind. mannschaft bookings belong to a team and have no personal owner.

    • datestring (date)
    • startTimestring
    • endTimestring
    • titlestring | null
    • bookedBystring | null

      User id of the booking owner. null for mannschaft bookings.

    • teamIdstring | null
delete/bookings/{id}
Cancel a booking
Personal keyManagement keybookings:cancel (only for foreign bookings / override)

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.

Parameters

  • idpath · stringrequired

    Booking id.

  • overridequery · boolean

    Skips policy checks (deadline). Requires bookings:cancel.

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/bookings/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 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
  • successbooleanrequired
get/bookings/{id}/metadata
Read app metadata attached to a booking
Installation tokenbookings:read

Returns the calling app's own keys on this booking and the keys of other apps that the caller declares under reads.metadata in its manifest, the producer declares under shares.metadata, and the club approved. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    Booking id

Example

curl "https://app.checkcourt.de/api/v1/bookings/{id}/metadata" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • metadataobjectrequired

    Grouped by app slug, then by key. Contains the calling app's own keys and the keys of other apps that the caller declares under reads.metadata and the club approved.

put/bookings/{id}/metadata/{key}
Attach or replace a metadata value on a booking
Installation tokenbookings:read

Writes one of the app's own keys. The key must be declared under shares.metadata with object: "booking". A changed value sends app.metadata_changed to the apps the club connected to yours for this key. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    Booking id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Request body

  • valueobjectrequired

    Any JSON value except null, at most 4096 bytes serialized

Example

curl -X PUT "https://app.checkcourt.de/api/v1/bookings/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…" \
  -H "Content-Type: application/json" \
  -d '{"value":"value"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • keystringrequired
  • valueobjectrequired
  • updated_atstring (date-time)required
delete/bookings/{id}/metadata/{key}
Remove one of the app's metadata values from a booking
Installation tokenbookings:read

Removes the app's own value. Works for keys a newer manifest no longer declares, so an app can clean up. deleted: false when there was nothing to remove. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    Booking id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/bookings/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • deletedbooleanrequired

Courts

get/courts
List all courts
Personal keyManagement keycourts:read

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.

Example

curl "https://app.checkcourt.de/api/v1/courts" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • courtsobject[]required
    • idintegerrequired

      Numeric court id (stable, tenant-scoped)

    • tenantIdstring
    • namestringrequired
    • surfacestringrequired

      Free-text surface label, e.g. "Asche" or "Teppich"

    • isLockedbooleanrequired

      True while the court is locked for booking

    • lockReasonstring | null

      Reason shown to members while locked

    • isBillingLockedboolean

      Locked by the billing system because the subscription does not cover this court. Cannot be lifted via the API.

    • lockedBystring | null

      User id of whoever locked the court

    • lockedAtstring | null (date-time)

      ISO 8601 timestamp

    • sortOrderintegerrequired

      Display position, ascending

    • bookingNoticestring | null

      Short 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 | null

      Season start as MM-DD; always set together with seasonEnd

    • seasonEndstring | null

      Season end as MM-DD

post/courts
Create a court
Personal keyManagement keycourts:write

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

  • namestringrequired
  • surfacestringrequired

Example

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"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • courtobjectrequired
    • idintegerrequired

      Numeric court id (stable, tenant-scoped)

    • tenantIdstring
    • namestringrequired
    • surfacestringrequired

      Free-text surface label, e.g. "Asche" or "Teppich"

    • isLockedbooleanrequired

      True while the court is locked for booking

    • lockReasonstring | null

      Reason shown to members while locked

    • isBillingLockedboolean

      Locked by the billing system because the subscription does not cover this court. Cannot be lifted via the API.

    • lockedBystring | null

      User id of whoever locked the court

    • lockedAtstring | null (date-time)

      ISO 8601 timestamp

    • sortOrderintegerrequired

      Display position, ascending

    • bookingNoticestring | null

      Short 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 | null

      Season start as MM-DD; always set together with seasonEnd

    • seasonEndstring | null

      Season end as MM-DD

post/courts/reorder
Reorder courts
Personal keyManagement keycourts:write

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[]required

Example

curl -X POST "https://app.checkcourt.de/api/v1/courts/reorder" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{"courtIds":[]}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
get/courts/{id}
Court details with upcoming bookings
Personal keyManagement keycourts:read_confidential

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.

Parameters

  • idpath · integerrequired

    Numeric court id

Example

curl "https://app.checkcourt.de/api/v1/courts/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • courtobjectrequired
    • idintegerrequired

      Numeric court id (stable, tenant-scoped)

    • tenantIdstring
    • namestringrequired
    • surfacestringrequired

      Free-text surface label, e.g. "Asche" or "Teppich"

    • isLockedbooleanrequired

      True while the court is locked for booking

    • lockReasonstring | null

      Reason shown to members while locked

    • isBillingLockedboolean

      Locked by the billing system because the subscription does not cover this court. Cannot be lifted via the API.

    • lockedBystring | null

      User id of whoever locked the court

    • lockedAtstring | null (date-time)

      ISO 8601 timestamp

    • sortOrderintegerrequired

      Display position, ascending

    • bookingNoticestring | null

      Short 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 | null

      Season start as MM-DD; always set together with seasonEnd

    • seasonEndstring | null

      Season end as MM-DD

  • upcomingBookingsobject[]required

    Next bookings from today on, capped at 20

    • idstring

      Booking id (CUID)

    • typestring

      Booking type, e.g. "regular" or "mannschaft"

    • datestring (date)
    • startTimestring

      Time of day as HH:MM or HH:MM:SS

    • endTimestring

      Time of day as HH:MM or HH:MM:SS

    • titlestring | null
    • bookedByNamestring | null

      Display name of the booker, or the team name for team bookings

  • lockRangesobject[]required
    • fromDatestring (date)
    • toDatestring (date)
    • fromTimestring

      Time of day as HH:MM or HH:MM:SS

    • toTimestring

      Time of day as HH:MM or HH:MM:SS

    • titlestring | null
  • lockedByUserstring | null

    Display name of the user who locked the court

  • isBillingLockedboolean
patch/courts/{id}
Update a court
Personal keyManagement keycourts:write

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.

Parameters

  • idpath · integerrequired

    Numeric court id

Request body

  • namestring
  • surfacestring
  • bookingNoticestring | null
  • activeMonthsinteger[]
  • seasonStartstring | null

    MM-DD

  • seasonEndstring | null

    MM-DD

Example

curl -X PATCH "https://app.checkcourt.de/api/v1/courts/{id}" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • courtIdintegerrequired
delete/courts/{id}
Delete a court
Personal keyManagement keycourts:write

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.

Parameters

  • idpath · integerrequired

    Numeric court id

  • forceBillingActivequery · boolean

    Platform support only: delete even though the court is billed this month

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/courts/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • cancelledBookingsintegerrequired

    Number of future bookings that were cancelled

post/courts/{id}/lock
Lock a court
Personal keyManagement keycourts:write

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.

Parameters

  • idpath · integerrequired

    Numeric court id

Request body

  • reasonstringrequired
  • fromDatestring (date)
  • toDatestring (date)
  • fromTimestring

    Time of day as HH:MM or HH:MM:SS

  • toTimestring

    Time of day as HH:MM or HH:MM:SS

Example

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"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • courtIdintegerrequired
post/courts/{id}/unlock
Unlock a court
Personal keyManagement keycourts:write

Lifts a manual lock and removes scheduled lock windows. Billing locks (isBillingLocked) are managed by the subscription system and cannot be lifted here (422).

Parameters

  • idpath · integerrequired

    Numeric court id

Example

curl -X POST "https://app.checkcourt.de/api/v1/courts/{id}/unlock" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • courtIdintegerrequired
get/courts/{id}/metadata
Read app metadata attached to a court
Installation tokencourts:read

Returns the calling app's own keys on this court and the keys of other apps that the caller declares under reads.metadata in its manifest, the producer declares under shares.metadata, and the club approved. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · integerrequired

    Numeric court id

Example

curl "https://app.checkcourt.de/api/v1/courts/{id}/metadata" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • metadataobjectrequired

    Grouped by app slug, then by key. Contains the calling app's own keys and the keys of other apps that the caller declares under reads.metadata and the club approved.

put/courts/{id}/metadata/{key}
Attach or replace a metadata value on a court
Installation tokencourts:read

Writes one of the app's own keys. The key must be declared under shares.metadata with object: "court". A changed value sends app.metadata_changed to the apps the club connected to yours for this key. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · integerrequired

    Numeric court id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Request body

  • valueobjectrequired

    Any JSON value except null, at most 4096 bytes serialized

Example

curl -X PUT "https://app.checkcourt.de/api/v1/courts/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…" \
  -H "Content-Type: application/json" \
  -d '{"value":"value"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • keystringrequired
  • valueobjectrequired
  • updated_atstring (date-time)required
delete/courts/{id}/metadata/{key}
Remove one of the app's metadata values from a court
Installation tokencourts:read

Removes the app's own value. Works for keys a newer manifest no longer declares, so an app can clean up. deleted: false when there was nothing to remove. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · integerrequired

    Numeric court id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/courts/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • deletedbooleanrequired

Members

Name lists require members:read. Contact details and other personal data require members:read_confidential.

get/members
Search members (paginated)
Personal keyManagement keymembers:read_confidential

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.

Parameters

  • searchquery · string

    Substring search across name, email, forwarding email, member number, member code

  • roleIdquery · string

    Only members holding this role (id from GET /roles). The base role Mitglied (member) matches everyone.

  • pagequery · integer

    1-based page number

Example

curl "https://app.checkcourt.de/api/v1/members" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • membersobject[]required
    • idstringrequired

      User id (CUID). Use this in /members/{id} paths.

    • namestringrequired
    • emailstring (email)required
    • forwardingEmailstring | null (email)

      Set for accounts without their own mailbox: mail is sent here instead, and email is a synthetic address

    • memberNumberstring | null

      Club-assigned member number, unique per tenant

    • rolesobject[]required

      Roles the member holds, highest first, the base role Mitglied (member) last. Without roles:read only the roles the club shows next to member names (plus Mitglied) are listed.

      • idstringrequired

        Role id, as in GET /roles

      • namestringrequired
      • systemKey"admin" | "trainer" | "member" | "null"required

        Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • guestFeesAccumulatedinteger

      Amount in euro cents

    • emailVerifiedboolean
    • adminApprovalPendingboolean

      True while a self-registered member awaits admin approval

  • totalintegerrequired

    Total matching members across all pages

  • pageintegerrequired
  • pageSizeintegerrequired
  • totalPagesintegerrequired
post/members
Invite or create a member
Personal keyManagement keymembers:invite

Adds a member to the club. Three flows, decided by the input: 1. Email already has an account (in no other club): the account owner is invited. The membership stays pending (awaitingAcceptance: true) until they accept after their next login; until then the club cannot change the account's name, email, phone or password, and deleting the member only withdraws the invitation. sendEmail controls the invitation mail. 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.

roleIds (optional) assigns roles besides the base role Mitglied and requires roles:manage, which only personal keys can hold: the caller must outrank each role and hold all of its scopes (403). Unknown ids fail with 404 before anything is created.

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)required
  • namestringrequired
  • roleIdsstring[]

    Role ids from GET /roles; omit for members without further roles

  • sendEmailbooleandefault: true

    Send the welcome email

  • noOwnEmailbooleandefault: false

    Create a forwarding-only account (flow 3)

  • passwordstring

    Required when noOwnEmail=true

  • memberNumberstring

Example

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"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
  • awaitingAcceptancebooleanrequired

    True when an existing account was invited and its owner still has to accept

get/members/count
Count members
Personal keyManagement keymembers:read

Number of members of the club, including members awaiting admin approval. Returns no names or ids, so it needs only members:read, not members:read_confidential like the directory in GET /members.

Example

curl "https://app.checkcourt.de/api/v1/members/count" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • totalintegerrequired
get/members/{id}
Get one member
Personal keyManagement keymembers:read_confidential

Full member record including phone, member code and creation date.

Parameters

  • idpath · stringrequired

    User id of the member (the id field from list responses)

Example

curl "https://app.checkcourt.de/api/v1/members/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • memberobjectrequired
    • idstringrequired

      User id (CUID)

    • namestringrequired
    • emailstring (email)required
    • forwardingEmailstring | null (email)
    • rolesobject[]required

      Roles the member holds, highest first, the base role Mitglied (member) last. Without roles:read only the roles the club shows next to member names (plus Mitglied) are listed.

      • idstringrequired

        Role id, as in GET /roles

      • namestringrequired
      • systemKey"admin" | "trainer" | "member" | "null"required

        Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • memberNumberstring | null
    • mitgliedscodestring | null

      Short member code used for on-site identification

    • phonestring | null
    • guestFeesAccumulatedinteger

      Amount in euro cents

    • createdAtstring (date-time)

      ISO 8601 timestamp

    • emailVerifiedboolean
    • adminApprovalPendingboolean
patch/members/{id}
Update a member
Personal keyManagement keymembers:write

name and email 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 the member number changes. Sessions cannot edit their own account; management keys are exempt from that rule. Changing the email requires outranking the member (403): only administrators may change the email of members holding an equal or higher role; management keys act with their creator's rank but never on administrators. While the member's invitation is pending, changing name, email or phone fails with 422. Member numbers are unique per club (422 on collision). Roles are not part of this endpoint: use PUT /members/{id}/roles. Sending role fails with 400.

Parameters

  • idpath · stringrequired

    User id of the member (the id field from list responses)

Request body

  • namestringrequired
  • emailstring (email)required
  • phonestring
  • memberNumberstring

Example

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"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
delete/members/{id}
End a membership
Personal keyManagement keymembers:delete

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 (not for a pending invitation, which only withdraws the invitation). The caller must outrank the member (403): only administrators may delete members holding an equal or higher role; management keys act with their creator's rank but never on administrators. Members who lead a team cannot be deleted until leadership is handed over, and the club's last administrator cannot be deleted (422). The response summarizes what happened.

Parameters

  • idpath · stringrequired

    User id of the member (the id field from list responses)

  • orphanedFeeActionquery · "cancelled" | "paid"

    Write off open guest fees (cancelled) or mark them as paid (paid)

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/members/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
  • cancelledBookingCountinteger
  • resolvedFeeCountinteger
  • resolvedFeeTotalCentsinteger

    Amount in euro cents

  • anonymizedboolean

    True if the account was anonymized because no other membership remained

get/members/{id}/metadata
Read app metadata attached to a member
Installation tokenmembers:read

Returns the calling app's own keys on this member and the keys of other apps that the caller declares under reads.metadata in its manifest, the producer declares under shares.metadata, and the club approved. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    The member's user id

Example

curl "https://app.checkcourt.de/api/v1/members/{id}/metadata" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • metadataobjectrequired

    Grouped by app slug, then by key. Contains the calling app's own keys and the keys of other apps that the caller declares under reads.metadata and the club approved.

put/members/{id}/metadata/{key}
Attach or replace a metadata value on a member
Installation tokenmembers:read

Writes one of the app's own keys. The key must be declared under shares.metadata with object: "member". A changed value sends app.metadata_changed to the apps the club connected to yours for this key. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    The member's user id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Request body

  • valueobjectrequired

    Any JSON value except null, at most 4096 bytes serialized

Example

curl -X PUT "https://app.checkcourt.de/api/v1/members/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…" \
  -H "Content-Type: application/json" \
  -d '{"value":"value"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • keystringrequired
  • valueobjectrequired
  • updated_atstring (date-time)required
delete/members/{id}/metadata/{key}
Remove one of the app's metadata values from a member
Installation tokenmembers:read

Removes the app's own value. Works for keys a newer manifest no longer declares, so an app can clean up. deleted: false when there was nothing to remove. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    The member's user id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/members/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • deletedbooleanrequired

Roles

The club's roles and groups and who holds them. Reading works with roles:read, changing only with a personal key and roles:manage. The same rules apply as in the UI: you can only assign and revoke roles that rank below your highest role, and only for members whose highest role ranks below yours. You can also only assign a role if you hold all of its permissions yourself. Only administrators can change the Administrator role.

get/roles
List roles
Personal keyManagement keyroles:read

All roles of the club, highest first, including the system roles Administrator, Trainer and Mitglied (member).

Example

curl "https://app.checkcourt.de/api/v1/roles" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • rolesobject[]required
    • idstringrequired
    • namestringrequired
    • descriptionstring | nullrequired
    • colorstringrequired

      Hex color from the role palette (see RoleColor)

    • positionintegerrequired

      Rank in the club's hierarchy; higher outranks lower. Mitglied (member) is always 0, Administrator always the highest.

    • systemKey"admin" | "trainer" | "member" | "null"required

      Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • isVisiblebooleanrequired

      Whether the role is shown as a badge next to its members

    • permissionsstring[]required

      Scopes granted by this role (see GET /permissions). Administrator lists every scope.

    • memberCountintegerrequired

      Members holding the role; for Mitglied (member) the size of the whole club

post/roles
Create a role
Personal keyroles:manage

Personal keys only: management keys can never hold roles:manage (403). The key acts as its member: non-administrators can only change roles that sit below their own highest role, only touch members ranked below them, and only grant permissions they hold themselves (403 otherwise). Creates a role directly above the base role Mitglied (member), either from scratch or from a template ({ "template": "kassenwart" }, no other fields). Prerequisite scopes are added automatically. Returns the new role as stored. An unknown template returns 404.

Request body

Example

curl -X POST "https://app.checkcourt.de/api/v1/roles" \
  -H "Authorization: Bearer ck_user_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200The role as stored, in the same shape as an item of `GET /roles`
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • roleobjectrequired

    A role of the club with its permissions

    • idstringrequired
    • namestringrequired
    • descriptionstring | nullrequired
    • colorstringrequired

      Hex color from the role palette (see RoleColor)

    • positionintegerrequired

      Rank in the club's hierarchy; higher outranks lower. Mitglied (member) is always 0, Administrator always the highest.

    • systemKey"admin" | "trainer" | "member" | "null"required

      Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • isVisiblebooleanrequired

      Whether the role is shown as a badge next to its members

    • permissionsstring[]required

      Scopes granted by this role (see GET /permissions). Administrator lists every scope.

    • memberCountintegerrequired

      Members holding the role; for Mitglied (member) the size of the whole club

put/roles/reorder
Reorder roles
Personal keyroles:manage

Personal keys only: management keys can never hold roles:manage (403). The key acts as its member: non-administrators can only change roles that sit below their own highest role, only touch members ranked below them, and only grant permissions they hold themselves (403 otherwise). Send every role except Administrator and Mitglied (member) exactly once, highest first (400 otherwise). Non-administrators can only reshuffle roles below their own highest role; those at or above it must keep their place (403).

Request body

  • orderedIdsstring[]required

Example

curl -X PUT "https://app.checkcourt.de/api/v1/roles/reorder" \
  -H "Authorization: Bearer ck_user_…" \
  -H "Content-Type: application/json" \
  -d '{"orderedIds":[]}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
get/roles/{id}
Get one role with its members
Personal keyManagement keyroles:read

The role plus everyone holding it. email and memberNumber of the members are null unless the key also holds members:read_confidential. For the base role „Mitglied“ (systemKey member), which applies to everyone, the list contains every member of the club.

Parameters

  • idpath · stringrequired

    Role id (the id field from GET /roles)

Example

curl "https://app.checkcourt.de/api/v1/roles/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • roleobjectrequired

    A role of the club with its permissions

    • idstringrequired
    • namestringrequired
    • descriptionstring | nullrequired
    • colorstringrequired

      Hex color from the role palette (see RoleColor)

    • positionintegerrequired

      Rank in the club's hierarchy; higher outranks lower. Mitglied (member) is always 0, Administrator always the highest.

    • systemKey"admin" | "trainer" | "member" | "null"required

      Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • isVisiblebooleanrequired

      Whether the role is shown as a badge next to its members

    • permissionsstring[]required

      Scopes granted by this role (see GET /permissions). Administrator lists every scope.

    • memberCountintegerrequired

      Members holding the role; for Mitglied (member) the size of the whole club

  • membersobject[]required
    • userIdstringrequired

      User id (same as id in GET /members)

    • namestringrequired
    • memberNumberstring | nullrequired

      Null without members:read_confidential

    • emailstring | null (email)required

      Null without members:read_confidential

patch/roles/{id}
Update a role
Personal keyroles:manage

Personal keys only: management keys can never hold roles:manage (403). The key acts as its member: non-administrators can only change roles that sit below their own highest role, only touch members ranked below them, and only grant permissions they hold themselves (403 otherwise). Changes name, description, color or visibility; omitted fields stay. description: null clears it.

Parameters

  • idpath · stringrequired

    Role id (the id field from GET /roles)

Request body

  • namestring
  • descriptionstring | null
  • color"#166534" | "#f97316" | "#2563eb" | "#8b5cf6" | "#ec4899" | "#14b8a6" | "#f59e0b" | "#ef4444" | "#6366f1" | "#84cc16" | "#06b6d4" | "#d946ef"

    Display color of a role, one of a fixed palette

  • isVisibleboolean

Example

curl -X PATCH "https://app.checkcourt.de/api/v1/roles/{id}" \
  -H "Authorization: Bearer ck_user_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200The role as stored, in the same shape as an item of `GET /roles`
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • roleobjectrequired

    A role of the club with its permissions

    • idstringrequired
    • namestringrequired
    • descriptionstring | nullrequired
    • colorstringrequired

      Hex color from the role palette (see RoleColor)

    • positionintegerrequired

      Rank in the club's hierarchy; higher outranks lower. Mitglied (member) is always 0, Administrator always the highest.

    • systemKey"admin" | "trainer" | "member" | "null"required

      Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • isVisiblebooleanrequired

      Whether the role is shown as a badge next to its members

    • permissionsstring[]required

      Scopes granted by this role (see GET /permissions). Administrator lists every scope.

    • memberCountintegerrequired

      Members holding the role; for Mitglied (member) the size of the whole club

delete/roles/{id}
Delete a role
Personal keyroles:manage

Personal keys only: management keys can never hold roles:manage (403). The key acts as its member: non-administrators can only change roles that sit below their own highest role, only touch members ranked below them, and only grant permissions they hold themselves (403 otherwise). Deletes the role and removes it from all members. Administrator and Mitglied (member) cannot be deleted (422).

Parameters

  • idpath · stringrequired

    Role id (the id field from GET /roles)

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/roles/{id}" \
  -H "Authorization: Bearer ck_user_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
put/roles/{id}/permissions
Replace a role's permissions
Personal keyroles:manage

Personal keys only: management keys can never hold roles:manage (403). The key acts as its member: non-administrators can only change roles that sit below their own highest role, only touch members ranked below them, and only grant permissions they hold themselves (403 otherwise). Replaces the full scope list; prerequisite scopes are added automatically and included in the returned role. Administrator always holds everything and cannot be changed (422). Unknown scopes return 400.

Parameters

  • idpath · stringrequired

    Role id (the id field from GET /roles)

Request body

  • scopesstring[]required

Example

curl -X PUT "https://app.checkcourt.de/api/v1/roles/{id}/permissions" \
  -H "Authorization: Bearer ck_user_…" \
  -H "Content-Type: application/json" \
  -d '{"scopes":[]}'

Responses

  • 200The role as stored, in the same shape as an item of `GET /roles`
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • roleobjectrequired

    A role of the club with its permissions

    • idstringrequired
    • namestringrequired
    • descriptionstring | nullrequired
    • colorstringrequired

      Hex color from the role palette (see RoleColor)

    • positionintegerrequired

      Rank in the club's hierarchy; higher outranks lower. Mitglied (member) is always 0, Administrator always the highest.

    • systemKey"admin" | "trainer" | "member" | "null"required

      Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • isVisiblebooleanrequired

      Whether the role is shown as a badge next to its members

    • permissionsstring[]required

      Scopes granted by this role (see GET /permissions). Administrator lists every scope.

    • memberCountintegerrequired

      Members holding the role; for Mitglied (member) the size of the whole club

post/roles/{id}/reset
Reset the base role Mitglied to the default permissions
Personal keyroles:manage

Personal keys only: management keys can never hold roles:manage (403). The key acts as its member: non-administrators can only change roles that sit below their own highest role, only touch members ranked below them, and only grant permissions they hold themselves (403 otherwise). Restores the permissions a new club starts with. Only for the base role Mitglied (member) (422 for any other role). The key's member must be able to grant every default permission.

Parameters

  • idpath · stringrequired

    Role id (the id field from GET /roles)

Example

curl -X POST "https://app.checkcourt.de/api/v1/roles/{id}/reset" \
  -H "Authorization: Bearer ck_user_…"

Responses

  • 200The role as stored, in the same shape as an item of `GET /roles`
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • roleobjectrequired

    A role of the club with its permissions

    • idstringrequired
    • namestringrequired
    • descriptionstring | nullrequired
    • colorstringrequired

      Hex color from the role palette (see RoleColor)

    • positionintegerrequired

      Rank in the club's hierarchy; higher outranks lower. Mitglied (member) is always 0, Administrator always the highest.

    • systemKey"admin" | "trainer" | "member" | "null"required

      Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • isVisiblebooleanrequired

      Whether the role is shown as a badge next to its members

    • permissionsstring[]required

      Scopes granted by this role (see GET /permissions). Administrator lists every scope.

    • memberCountintegerrequired

      Members holding the role; for Mitglied (member) the size of the whole club

get/roles/{id}/members
List members of a role
Personal keyManagement keyroles:read

Same member list as GET /roles/{id}. email and memberNumber are null unless the key also holds members:read_confidential. For the base role „Mitglied“ (systemKey member), which applies to everyone, the list contains every member of the club.

Parameters

  • idpath · stringrequired

    Role id (the id field from GET /roles)

Example

curl "https://app.checkcourt.de/api/v1/roles/{id}/members" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • membersobject[]required
    • userIdstringrequired

      User id (same as id in GET /members)

    • namestringrequired
    • memberNumberstring | nullrequired

      Null without members:read_confidential

    • emailstring | null (email)required

      Null without members:read_confidential

post/roles/{id}/members
Assign a role to members
Personal keyroles:manage

Personal keys only: management keys can never hold roles:manage (403). The key acts as its member: non-administrators can only change roles that sit below their own highest role, only touch members ranked below them, and only grant permissions they hold themselves (403 otherwise). Adds the role to every listed member; members who already hold it are skipped. Any id outside the club returns 404 and nothing changes. The base role Mitglied (member) cannot be assigned (422).

Parameters

  • idpath · stringrequired

    Role id (the id field from GET /roles)

Request body

  • userIdsstring[]required

    User ids (the id field from GET /members)

Example

curl -X POST "https://app.checkcourt.de/api/v1/roles/{id}/members" \
  -H "Authorization: Bearer ck_user_…" \
  -H "Content-Type: application/json" \
  -d '{"userIds":[]}'

Responses

  • 200Everyone holding the role after the change, as in `GET /roles/{id}/members`
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • membersobject[]required
    • userIdstringrequired

      User id (same as id in GET /members)

    • namestringrequired
    • memberNumberstring | nullrequired

      Null without members:read_confidential

    • emailstring | null (email)required

      Null without members:read_confidential

delete/roles/{id}/members/{userId}
Take a role from a member
Personal keyroles:manage

Personal keys only: management keys can never hold roles:manage (403). The key acts as its member: non-administrators can only change roles that sit below their own highest role, only touch members ranked below them, and only grant permissions they hold themselves (403 otherwise). Removing a role the member does not hold is a no-op. The base role Mitglied (member) cannot be taken away, and the club's last administrator keeps the role Administrator (422).

Parameters

  • idpath · stringrequired

    Role id (the id field from GET /roles)

  • userIdpath · stringrequired

    User id of the member (the id field from GET /members)

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/roles/{id}/members/{userId}" \
  -H "Authorization: Bearer ck_user_…"

Responses

  • 200Everyone holding the role after the change, as in `GET /roles/{id}/members`
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • membersobject[]required
    • userIdstringrequired

      User id (same as id in GET /members)

    • namestringrequired
    • memberNumberstring | nullrequired

      Null without members:read_confidential

    • emailstring | null (email)required

      Null without members:read_confidential

get/members/{id}/roles
List a member's roles
Personal keyManagement keyroles:read

Every role the member holds, highest first, including the base role Mitglied (member), with color and permissions. /members lists the same roles by name only.

Parameters

  • idpath · stringrequired

    User id of the member (the id field from GET /members)

Example

curl "https://app.checkcourt.de/api/v1/members/{id}/roles" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • rolesobject[]required
    • idstringrequired
    • namestringrequired
    • descriptionstring | nullrequired
    • colorstringrequired

      Hex color from the role palette (see RoleColor)

    • positionintegerrequired

      Rank in the club's hierarchy; higher outranks lower. Mitglied (member) is always 0, Administrator always the highest.

    • systemKey"admin" | "trainer" | "member" | "null"required

      Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • isVisiblebooleanrequired

      Whether the role is shown as a badge next to its members

    • permissionsstring[]required

      Scopes granted by this role (see GET /permissions). Administrator lists every scope.

put/members/{id}/roles
Replace a member's roles
Personal keyroles:manage

Personal keys only: management keys can never hold roles:manage (403). The key acts as its member: non-administrators can only change roles that sit below their own highest role, only touch members ranked below them, and only grant permissions they hold themselves (403 otherwise). Sets exactly the given roles; roles not listed are taken away. The base role Mitglied (member) is implicit and ignored. Unknown role ids return 404. Taking Administrator from the club's last administrator fails with 422. This is the multi-role counterpart of the legacy role field on PATCH /members/{id}.

Parameters

  • idpath · stringrequired

    User id of the member (the id field from GET /members)

Request body

  • roleIdsstring[]required

Example

curl -X PUT "https://app.checkcourt.de/api/v1/members/{id}/roles" \
  -H "Authorization: Bearer ck_user_…" \
  -H "Content-Type: application/json" \
  -d '{"roleIds":[]}'

Responses

  • 200The member's roles after the change, as in `GET /members/{id}/roles`
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • rolesobject[]required
    • idstringrequired
    • namestringrequired
    • descriptionstring | nullrequired
    • colorstringrequired

      Hex color from the role palette (see RoleColor)

    • positionintegerrequired

      Rank in the club's hierarchy; higher outranks lower. Mitglied (member) is always 0, Administrator always the highest.

    • systemKey"admin" | "trainer" | "member" | "null"required

      Set for the three roles every club starts with. admin always holds every permission; member (Mitglied) applies to every member automatically and is never assigned.

    • isVisiblebooleanrequired

      Whether the role is shown as a badge next to its members

    • permissionsstring[]required

      Scopes granted by this role (see GET /permissions). Administrator lists every scope.

Permissions

The catalog of all scopes with German labels and descriptions, grouped by area.

get/permissions
Permission catalog
Personal keyManagement key

All scopes with German labels and descriptions, grouped into areas with the levels the role editor offers. Areas that belong to a feature appear only while the key's club has that feature enabled, so the catalog matches what the club's role editor shows. Use it to render permission pickers and to validate the scopes of PUT /roles/{id}/permissions.

Example

curl "https://app.checkcourt.de/api/v1/permissions" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • areasobject[]required
    • keystringrequired
    • labelstringrequired
    • descriptionstringrequired
    • featureKeystring | nullrequired

      Feature the area belongs to (enabled for this club, otherwise the area is omitted); null for areas every club has

    • scopesobject[]required
      • scopestringrequired
      • labelstringrequired
      • descriptionstringrequired
      • requiresstring[]required

        Scopes this one is useless without; they are added automatically when the scope is granted

    • levelsobject[]required

      Ascending, always starting with none

      • level"none" | "read" | "edit" | "manage"required
      • labelstringrequired
      • descriptionstringrequired
      • scopesstring[]required

        Every scope of the area this level grants, including those of lower levels

  • scopesstring[]required

    Every scope of the returned areas, in catalog order

Teams

get/teams
List all teams
Personal keyManagement keyteams:read

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.

Example

curl "https://app.checkcourt.de/api/v1/teams" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • teamsobject[]required
post/teams
Create a team
Personal keyManagement keyteams:write

Creates an empty team. Add players and leaders afterwards via the team-members endpoint.

Request body

  • namestringrequired
  • ligastring
  • spielklasse"herren" | "damen" | "mixed" | "jugend"
  • farbestring

    Hex color

Example

curl -X POST "https://app.checkcourt.de/api/v1/teams" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{"name":"name"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • teamIdstringrequired
get/teams/{id}
Team details
Personal keyManagement keyteams:read

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.

Parameters

  • idpath · stringrequired

    Team id

Example

curl "https://app.checkcourt.de/api/v1/teams/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • teamobjectrequired
    • idstringrequired

      Team id (CUID)

    • tenantIdstring
    • namestringrequired
    • ligastring | null

      League label, free text

    • spielklasse"herren" | "damen" | "mixed" | "jugend" | "null"

      Competition class of a team

    • farbestring | null

      Hex color used to mark the team's bookings

    • createdAtstring (date-time)

      ISO 8601 timestamp

    • updatedAtstring (date-time)

      ISO 8601 timestamp

  • membersobject[]required
    • tenantUserIdstringrequired

      Membership id (tenantUser). This is NOT the user id; use it when adding/removing team members.

    • role"player" | "leader"required

      A person can appear twice: once as player and once as leader

    • userIdstringrequired
    • memberNumberstring | null
    • namestringrequired
  • matchesobject[]required

    Upcoming matches

    • idstring
    • datestring (date)
    • startTimestring

      Time of day as HH:MM or HH:MM:SS

    • endTimestring

      Time of day as HH:MM or HH:MM:SS

    • titlestring | null
    • isAwayboolean
    • opponentstring | null
    • locationstring | null
    • courtNamesstring[]

      Home matches block one or more courts

  • oneOffTrainingsobject[]

    One-off training bookings (raw booking rows)

  • trainingsobject[]

    Recurring weekly trainings

  • canManagebooleanrequired

    Whether the calling actor may manage this team (admin role or team leader)

patch/teams/{id}
Update a team
Personal keyManagement keyteams:read

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.

Parameters

  • idpath · stringrequired

    Team id

Request body

  • namestringrequired
  • ligastring
  • spielklasse"herren" | "damen" | "mixed" | "jugend" | "null"

    Competition class of a team

  • farbestring

Example

curl -X PATCH "https://app.checkcourt.de/api/v1/teams/{id}" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{"name":"name"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • teamIdstringrequired
delete/teams/{id}
Delete a team
Personal keyManagement keyteams:write

Deletes the team and its roster assignments. Team bookings are kept but lose their team link.

Parameters

  • idpath · stringrequired

    Team id

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/teams/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • teamIdstringrequired
post/teams/{id}/members
Add a member to a team
Personal keyManagement keyteams:read

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.

Parameters

  • idpath · stringrequired

    Team id

Request body

  • tenantUserIdstringrequired

    Membership id (tenantUser)

  • role"player" | "leader"required

Example

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"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • teamIdstringrequired
delete/teams/{id}/members/{userId}
Remove a member from a team
Personal keyManagement keyteams:read

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.

Parameters

  • idpath · stringrequired

    Team id

  • userIdpath · stringrequired

    Membership id (tenantUser) of the assignment

  • rolequery · "player" | "leader"required

    Which role assignment to remove

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/teams/{id}/members/{userId}?role=player" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired

Booking policies

get/policies
List booking policies
Personal keyManagement keypolicies:read_confidential

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.

Example

curl "https://app.checkcourt.de/api/v1/policies" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • policiesobject[]required
    • idstringrequired
    • tenantIdstring
    • namestringrequired
    • descriptionstring | null
    • priorityintegerrequired

      Lower number = evaluated earlier

    • isEnabledbooleanrequired
    • isDefaultbooleanrequired

      Exactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.

    • conditionsobject

      Selects 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"[]
      • timeOfDayobject
        • fromstring

          Time of day as HH:MM or HH:MM:SS

        • tostring

          Time of day as HH:MM or HH:MM:SS

      • dateRangeobject
        • fromstring (date)
        • tostring (date)
      • courtIdsinteger[]
      • categoryIdsstring[]
      • bookerTeamIdsstring[]
      • bookerGroupIdsstring[]

        Role or group ids (GET /roles). Matches when the booker holds at least one of them. The base role Mitglied (member) is rejected because it applies to everyone.

      • actions"create" | "cancel" | "edit"[]
    • attributesobject

      Rule 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.

      • allowboolean

        Hard allow/deny for matching attempts

      • denyReasonstring

        Message shown when allow=false

      • maxBookingMinutesinteger
      • minBookingMinutesinteger
      • maxAdvanceBookingDaysinteger

        How far into the future bookings may start

      • maxActiveBookingsinteger

        Cap on simultaneously active (future) bookings per user

      • maxBookingsPerDayPerUserinteger
      • maxParallelBookingsinteger

        Cap on overlapping bookings per user across courts

      • cancellationDeadlineHoursinteger
      • slotStartIntervalMinutesinteger

        Allowed booking start raster, e.g. 30 for :00/:30

      • slotStartOffsetMinutesinteger
      • bookingStartTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingEndTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingDurationStepMinutesinteger

        Step the booking duration must be a multiple of. 0 or absent falls back to slotStartIntervalMinutes (which only applies when the start raster is active).

      • minTeammatesinteger

        How many teammates or guests a booking must name; 0 makes them optional. The booker does not count.

      • isNameableboolean

        Whether bookings may carry a free-text title

    • createdAtstring (date-time)

      ISO 8601 timestamp

    • updatedAtstring (date-time)

      ISO 8601 timestamp

post/policies
Create a policy
Personal keyManagement keypolicies:write

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

  • namestring
  • descriptionstring
  • isEnabledbooleandefault: true
  • conditionsobject

    Selects 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"[]
    • timeOfDayobject
      • fromstring

        Time of day as HH:MM or HH:MM:SS

      • tostring

        Time of day as HH:MM or HH:MM:SS

    • dateRangeobject
      • fromstring (date)
      • tostring (date)
    • courtIdsinteger[]
    • categoryIdsstring[]
    • bookerTeamIdsstring[]
    • bookerGroupIdsstring[]

      Role or group ids (GET /roles). Matches when the booker holds at least one of them. The base role Mitglied (member) is rejected because it applies to everyone.

    • actions"create" | "cancel" | "edit"[]
  • attributesobject

    Rule 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.

    • allowboolean

      Hard allow/deny for matching attempts

    • denyReasonstring

      Message shown when allow=false

    • maxBookingMinutesinteger
    • minBookingMinutesinteger
    • maxAdvanceBookingDaysinteger

      How far into the future bookings may start

    • maxActiveBookingsinteger

      Cap on simultaneously active (future) bookings per user

    • maxBookingsPerDayPerUserinteger
    • maxParallelBookingsinteger

      Cap on overlapping bookings per user across courts

    • cancellationDeadlineHoursinteger
    • slotStartIntervalMinutesinteger

      Allowed booking start raster, e.g. 30 for :00/:30

    • slotStartOffsetMinutesinteger
    • bookingStartTimestring

      Time of day as HH:MM or HH:MM:SS

    • bookingEndTimestring

      Time of day as HH:MM or HH:MM:SS

    • bookingDurationStepMinutesinteger

      Step the booking duration must be a multiple of. 0 or absent falls back to slotStartIntervalMinutes (which only applies when the start raster is active).

    • minTeammatesinteger

      How many teammates or guests a booking must name; 0 makes them optional. The booker does not count.

    • isNameableboolean

      Whether bookings may carry a free-text title

Example

curl -X POST "https://app.checkcourt.de/api/v1/policies" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • policyobjectrequired
    • idstringrequired
    • tenantIdstring
    • namestringrequired
    • descriptionstring | null
    • priorityintegerrequired

      Lower number = evaluated earlier

    • isEnabledbooleanrequired
    • isDefaultbooleanrequired

      Exactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.

    • conditionsobject

      Selects 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"[]
      • timeOfDayobject
        • fromstring

          Time of day as HH:MM or HH:MM:SS

        • tostring

          Time of day as HH:MM or HH:MM:SS

      • dateRangeobject
        • fromstring (date)
        • tostring (date)
      • courtIdsinteger[]
      • categoryIdsstring[]
      • bookerTeamIdsstring[]
      • bookerGroupIdsstring[]

        Role or group ids (GET /roles). Matches when the booker holds at least one of them. The base role Mitglied (member) is rejected because it applies to everyone.

      • actions"create" | "cancel" | "edit"[]
    • attributesobject

      Rule 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.

      • allowboolean

        Hard allow/deny for matching attempts

      • denyReasonstring

        Message shown when allow=false

      • maxBookingMinutesinteger
      • minBookingMinutesinteger
      • maxAdvanceBookingDaysinteger

        How far into the future bookings may start

      • maxActiveBookingsinteger

        Cap on simultaneously active (future) bookings per user

      • maxBookingsPerDayPerUserinteger
      • maxParallelBookingsinteger

        Cap on overlapping bookings per user across courts

      • cancellationDeadlineHoursinteger
      • slotStartIntervalMinutesinteger

        Allowed booking start raster, e.g. 30 for :00/:30

      • slotStartOffsetMinutesinteger
      • bookingStartTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingEndTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingDurationStepMinutesinteger

        Step the booking duration must be a multiple of. 0 or absent falls back to slotStartIntervalMinutes (which only applies when the start raster is active).

      • minTeammatesinteger

        How many teammates or guests a booking must name; 0 makes them optional. The booker does not count.

      • isNameableboolean

        Whether bookings may carry a free-text title

    • createdAtstring (date-time)

      ISO 8601 timestamp

    • updatedAtstring (date-time)

      ISO 8601 timestamp

get/policies/{id}
Get one policy
Personal keyManagement keypolicies:read_confidential

Parameters

  • idpath · stringrequired

    Policy id

Example

curl "https://app.checkcourt.de/api/v1/policies/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • idstringrequired
  • tenantIdstring
  • namestringrequired
  • descriptionstring | null
  • priorityintegerrequired

    Lower number = evaluated earlier

  • isEnabledbooleanrequired
  • isDefaultbooleanrequired

    Exactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.

  • conditionsobject

    Selects 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"[]
    • timeOfDayobject
      • fromstring

        Time of day as HH:MM or HH:MM:SS

      • tostring

        Time of day as HH:MM or HH:MM:SS

    • dateRangeobject
      • fromstring (date)
      • tostring (date)
    • courtIdsinteger[]
    • categoryIdsstring[]
    • bookerTeamIdsstring[]
    • bookerGroupIdsstring[]

      Role or group ids (GET /roles). Matches when the booker holds at least one of them. The base role Mitglied (member) is rejected because it applies to everyone.

    • actions"create" | "cancel" | "edit"[]
  • attributesobject

    Rule 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.

    • allowboolean

      Hard allow/deny for matching attempts

    • denyReasonstring

      Message shown when allow=false

    • maxBookingMinutesinteger
    • minBookingMinutesinteger
    • maxAdvanceBookingDaysinteger

      How far into the future bookings may start

    • maxActiveBookingsinteger

      Cap on simultaneously active (future) bookings per user

    • maxBookingsPerDayPerUserinteger
    • maxParallelBookingsinteger

      Cap on overlapping bookings per user across courts

    • cancellationDeadlineHoursinteger
    • slotStartIntervalMinutesinteger

      Allowed booking start raster, e.g. 30 for :00/:30

    • slotStartOffsetMinutesinteger
    • bookingStartTimestring

      Time of day as HH:MM or HH:MM:SS

    • bookingEndTimestring

      Time of day as HH:MM or HH:MM:SS

    • bookingDurationStepMinutesinteger

      Step the booking duration must be a multiple of. 0 or absent falls back to slotStartIntervalMinutes (which only applies when the start raster is active).

    • minTeammatesinteger

      How many teammates or guests a booking must name; 0 makes them optional. The booker does not count.

    • isNameableboolean

      Whether bookings may carry a free-text title

  • createdAtstring (date-time)

    ISO 8601 timestamp

  • updatedAtstring (date-time)

    ISO 8601 timestamp

patch/policies/{id}
Update a policy
Personal keyManagement keypolicies:write

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.

Parameters

  • idpath · stringrequired

    Policy id

Request body

  • namestring
  • descriptionstring
  • isEnabledbooleandefault: true
  • conditionsobject

    Selects 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"[]
    • timeOfDayobject
      • fromstring

        Time of day as HH:MM or HH:MM:SS

      • tostring

        Time of day as HH:MM or HH:MM:SS

    • dateRangeobject
      • fromstring (date)
      • tostring (date)
    • courtIdsinteger[]
    • categoryIdsstring[]
    • bookerTeamIdsstring[]
    • bookerGroupIdsstring[]

      Role or group ids (GET /roles). Matches when the booker holds at least one of them. The base role Mitglied (member) is rejected because it applies to everyone.

    • actions"create" | "cancel" | "edit"[]
  • attributesobject

    Rule 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.

    • allowboolean

      Hard allow/deny for matching attempts

    • denyReasonstring

      Message shown when allow=false

    • maxBookingMinutesinteger
    • minBookingMinutesinteger
    • maxAdvanceBookingDaysinteger

      How far into the future bookings may start

    • maxActiveBookingsinteger

      Cap on simultaneously active (future) bookings per user

    • maxBookingsPerDayPerUserinteger
    • maxParallelBookingsinteger

      Cap on overlapping bookings per user across courts

    • cancellationDeadlineHoursinteger
    • slotStartIntervalMinutesinteger

      Allowed booking start raster, e.g. 30 for :00/:30

    • slotStartOffsetMinutesinteger
    • bookingStartTimestring

      Time of day as HH:MM or HH:MM:SS

    • bookingEndTimestring

      Time of day as HH:MM or HH:MM:SS

    • bookingDurationStepMinutesinteger

      Step the booking duration must be a multiple of. 0 or absent falls back to slotStartIntervalMinutes (which only applies when the start raster is active).

    • minTeammatesinteger

      How many teammates or guests a booking must name; 0 makes them optional. The booker does not count.

    • isNameableboolean

      Whether bookings may carry a free-text title

Example

curl -X PATCH "https://app.checkcourt.de/api/v1/policies/{id}" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • policyobjectrequired
    • idstringrequired
    • tenantIdstring
    • namestringrequired
    • descriptionstring | null
    • priorityintegerrequired

      Lower number = evaluated earlier

    • isEnabledbooleanrequired
    • isDefaultbooleanrequired

      Exactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.

    • conditionsobject

      Selects 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"[]
      • timeOfDayobject
        • fromstring

          Time of day as HH:MM or HH:MM:SS

        • tostring

          Time of day as HH:MM or HH:MM:SS

      • dateRangeobject
        • fromstring (date)
        • tostring (date)
      • courtIdsinteger[]
      • categoryIdsstring[]
      • bookerTeamIdsstring[]
      • bookerGroupIdsstring[]

        Role or group ids (GET /roles). Matches when the booker holds at least one of them. The base role Mitglied (member) is rejected because it applies to everyone.

      • actions"create" | "cancel" | "edit"[]
    • attributesobject

      Rule 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.

      • allowboolean

        Hard allow/deny for matching attempts

      • denyReasonstring

        Message shown when allow=false

      • maxBookingMinutesinteger
      • minBookingMinutesinteger
      • maxAdvanceBookingDaysinteger

        How far into the future bookings may start

      • maxActiveBookingsinteger

        Cap on simultaneously active (future) bookings per user

      • maxBookingsPerDayPerUserinteger
      • maxParallelBookingsinteger

        Cap on overlapping bookings per user across courts

      • cancellationDeadlineHoursinteger
      • slotStartIntervalMinutesinteger

        Allowed booking start raster, e.g. 30 for :00/:30

      • slotStartOffsetMinutesinteger
      • bookingStartTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingEndTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingDurationStepMinutesinteger

        Step the booking duration must be a multiple of. 0 or absent falls back to slotStartIntervalMinutes (which only applies when the start raster is active).

      • minTeammatesinteger

        How many teammates or guests a booking must name; 0 makes them optional. The booker does not count.

      • isNameableboolean

        Whether bookings may carry a free-text title

    • createdAtstring (date-time)

      ISO 8601 timestamp

    • updatedAtstring (date-time)

      ISO 8601 timestamp

delete/policies/{id}
Delete a policy
Personal keyManagement keypolicies:write

The default policy cannot be deleted (422).

Parameters

  • idpath · stringrequired

    Policy id

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/policies/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
  • idstringrequired
post/policies/{id}/toggle
Enable or disable a policy
Personal keyManagement keypolicies:write

Disabled policies are skipped during evaluation but keep their priority slot.

Parameters

  • idpath · stringrequired

    Policy id

Request body

  • enabledbooleanrequired

Example

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}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • policyobjectrequired
    • idstringrequired
    • tenantIdstring
    • namestringrequired
    • descriptionstring | null
    • priorityintegerrequired

      Lower number = evaluated earlier

    • isEnabledbooleanrequired
    • isDefaultbooleanrequired

      Exactly one default policy exists per tenant. It matches everything, cannot be renamed or deleted.

    • conditionsobject

      Selects 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"[]
      • timeOfDayobject
        • fromstring

          Time of day as HH:MM or HH:MM:SS

        • tostring

          Time of day as HH:MM or HH:MM:SS

      • dateRangeobject
        • fromstring (date)
        • tostring (date)
      • courtIdsinteger[]
      • categoryIdsstring[]
      • bookerTeamIdsstring[]
      • bookerGroupIdsstring[]

        Role or group ids (GET /roles). Matches when the booker holds at least one of them. The base role Mitglied (member) is rejected because it applies to everyone.

      • actions"create" | "cancel" | "edit"[]
    • attributesobject

      Rule 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.

      • allowboolean

        Hard allow/deny for matching attempts

      • denyReasonstring

        Message shown when allow=false

      • maxBookingMinutesinteger
      • minBookingMinutesinteger
      • maxAdvanceBookingDaysinteger

        How far into the future bookings may start

      • maxActiveBookingsinteger

        Cap on simultaneously active (future) bookings per user

      • maxBookingsPerDayPerUserinteger
      • maxParallelBookingsinteger

        Cap on overlapping bookings per user across courts

      • cancellationDeadlineHoursinteger
      • slotStartIntervalMinutesinteger

        Allowed booking start raster, e.g. 30 for :00/:30

      • slotStartOffsetMinutesinteger
      • bookingStartTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingEndTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingDurationStepMinutesinteger

        Step the booking duration must be a multiple of. 0 or absent falls back to slotStartIntervalMinutes (which only applies when the start raster is active).

      • minTeammatesinteger

        How many teammates or guests a booking must name; 0 makes them optional. The booker does not count.

      • isNameableboolean

        Whether bookings may carry a free-text title

    • createdAtstring (date-time)

      ISO 8601 timestamp

    • updatedAtstring (date-time)

      ISO 8601 timestamp

post/policies/reorder
Reorder policy priorities
Personal keyManagement keypolicies:write

Send all non-default policy ids in the desired evaluation order (first = highest precedence). Priorities are reassigned accordingly.

Request body

  • orderedIdsstring[]required

Example

curl -X POST "https://app.checkcourt.de/api/v1/policies/reorder" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{"orderedIds":[]}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
get/booking-policies
Resolve effective booking rules for the calling actor
Personal keyManagement keypolicies:read

Evaluates the whole policy engine for the calling member, including the roles and groups they hold, 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 member to evaluate for and receive 400.

Example

curl "https://app.checkcourt.de/api/v1/booking-policies" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • evaluatedAtstring (date-time)

    ISO 8601 timestamp

  • courtsobject[]
    • courtIdinteger
    • courtNamestring
    • attributesobject

      Rule 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.

      • allowboolean

        Hard allow/deny for matching attempts

      • denyReasonstring

        Message shown when allow=false

      • maxBookingMinutesinteger
      • minBookingMinutesinteger
      • maxAdvanceBookingDaysinteger

        How far into the future bookings may start

      • maxActiveBookingsinteger

        Cap on simultaneously active (future) bookings per user

      • maxBookingsPerDayPerUserinteger
      • maxParallelBookingsinteger

        Cap on overlapping bookings per user across courts

      • cancellationDeadlineHoursinteger
      • slotStartIntervalMinutesinteger

        Allowed booking start raster, e.g. 30 for :00/:30

      • slotStartOffsetMinutesinteger
      • bookingStartTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingEndTimestring

        Time of day as HH:MM or HH:MM:SS

      • bookingDurationStepMinutesinteger

        Step the booking duration must be a multiple of. 0 or absent falls back to slotStartIntervalMinutes (which only applies when the start raster is active).

      • minTeammatesinteger

        How many teammates or guests a booking must name; 0 makes them optional. The booker does not count.

      • isNameableboolean

        Whether bookings may carry a free-text title

    • perCategoryobject[]
      • categoryIdstring
      • categorySlugstring
      • categoryNamestring
      • attributesobject

        Rule 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.

        • allowboolean

          Hard allow/deny for matching attempts

        • denyReasonstring

          Message shown when allow=false

        • maxBookingMinutesinteger
        • minBookingMinutesinteger
        • maxAdvanceBookingDaysinteger

          How far into the future bookings may start

        • maxActiveBookingsinteger

          Cap on simultaneously active (future) bookings per user

        • maxBookingsPerDayPerUserinteger
        • maxParallelBookingsinteger

          Cap on overlapping bookings per user across courts

        • cancellationDeadlineHoursinteger
        • slotStartIntervalMinutesinteger

          Allowed booking start raster, e.g. 30 for :00/:30

        • slotStartOffsetMinutesinteger
        • bookingStartTimestring

          Time of day as HH:MM or HH:MM:SS

        • bookingEndTimestring

          Time of day as HH:MM or HH:MM:SS

        • bookingDurationStepMinutesinteger

          Step the booking duration must be a multiple of. 0 or absent falls back to slotStartIntervalMinutes (which only applies when the start raster is active).

        • minTeammatesinteger

          How many teammates or guests a booking must name; 0 makes them optional. The booker does not count.

        • isNameableboolean

          Whether bookings may carry a free-text title

  • grantedCategoryIdsstring[]

    Categories the actor may book in

Booking categories

get/booking-categories
List booking categories
Personal keyManagement keycategories:read

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.

Example

curl "https://app.checkcourt.de/api/v1/booking-categories" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • categoriesobject[]required
    • idstringrequired
    • tenantIdstring
    • namestringrequired
    • slugstringrequired

      Stable identifier; system categories use fixed slugs like "regular"

    • colorstringrequired

      Hex color from the predefined palette

    • isSystembooleanrequired

      System categories cannot be renamed or deleted

    • isPublicboolean

      Whether bookings in this category show details to other members

    • anonymizeGuestsboolean
    • allowUserToggleboolean

      Members may toggle visibility per booking

    • allowUserToggleGuestsboolean
    • sortOrderinteger
    • createdAtstring (date-time)

      ISO 8601 timestamp

    • updatedAtstring (date-time)

      ISO 8601 timestamp

post/booking-categories
Create a category
Personal keyManagement keycategories:write

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

  • namestringrequired
  • colorstringrequired

    Hex color from the predefined palette

Example

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"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • categoryobjectrequired
    • idstringrequired
    • tenantIdstring
    • namestringrequired
    • slugstringrequired

      Stable identifier; system categories use fixed slugs like "regular"

    • colorstringrequired

      Hex color from the predefined palette

    • isSystembooleanrequired

      System categories cannot be renamed or deleted

    • isPublicboolean

      Whether bookings in this category show details to other members

    • anonymizeGuestsboolean
    • allowUserToggleboolean

      Members may toggle visibility per booking

    • allowUserToggleGuestsboolean
    • sortOrderinteger
    • createdAtstring (date-time)

      ISO 8601 timestamp

    • updatedAtstring (date-time)

      ISO 8601 timestamp

patch/booking-categories/{id}
Update a category
Personal keyManagement keycategories:write

Partial update. System categories cannot be renamed (422), but their visibility flags and color may be changed.

Parameters

  • idpath · stringrequired

    Category id

Request body

  • namestring
  • colorstring
  • isPublicboolean
  • anonymizeGuestsboolean
  • allowUserToggleboolean
  • allowUserToggleGuestsboolean
  • sortOrderinteger

Example

curl -X PATCH "https://app.checkcourt.de/api/v1/booking-categories/{id}" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • categoryobjectrequired
    • idstringrequired
    • tenantIdstring
    • namestringrequired
    • slugstringrequired

      Stable identifier; system categories use fixed slugs like "regular"

    • colorstringrequired

      Hex color from the predefined palette

    • isSystembooleanrequired

      System categories cannot be renamed or deleted

    • isPublicboolean

      Whether bookings in this category show details to other members

    • anonymizeGuestsboolean
    • allowUserToggleboolean

      Members may toggle visibility per booking

    • allowUserToggleGuestsboolean
    • sortOrderinteger
    • createdAtstring (date-time)

      ISO 8601 timestamp

    • updatedAtstring (date-time)

      ISO 8601 timestamp

delete/booking-categories/{id}
Delete a category
Personal keyManagement keycategories:write

System categories cannot be deleted (422). Existing bookings of a deleted category are reassigned to the default ("regular") category.

Parameters

  • idpath · stringrequired

    Category id

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/booking-categories/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired

Guest fees

get/guest-fees
List settled guest fees (paginated)
Personal keyManagement keyguest_fees:read

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.

Parameters

  • searchquery · string

    Substring search in guest name, member name, member email

  • userIdquery · string

    Only fees owed by this member (user id)

  • pagequery · integer

    1-based page number

  • pageSizequery · integer

    Entries per page

Example

curl "https://app.checkcourt.de/api/v1/guest-fees" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • entriesobject[]required
    • idstring
    • guestNamestring
    • feeAmountinteger

      Amount in euro cents

    • settledAtstring (date-time)

      ISO 8601 timestamp

    • createdAtstring (date-time)

      ISO 8601 timestamp

    • memberIdstring

      User id of the member who owes/paid the fee

    • memberNamestring
    • memberEmailstring (email)
    • bookingDatestring (date)
  • totalintegerrequired
  • pageintegerrequired
  • pageSizeintegerrequired
  • totalPagesintegerrequired
get/guest-fees/open
List a member's open guest fees
Personal keyManagement keyguest_fees:read

All unsettled guest fees one member currently owes, including the booking context (date, time, court) each fee originated from.

Parameters

  • userIdquery · stringrequired

    User id of the member

Example

curl "https://app.checkcourt.de/api/v1/guest-fees/open?userId=userId" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • entriesobject[]required
    • idstring
    • guestNamestring
    • feeAmountinteger

      Amount in euro cents

    • createdAtstring (date-time)

      ISO 8601 timestamp

    • bookingDatestring (date)
    • bookingStartTimestring

      Time of day as HH:MM or HH:MM:SS

    • bookingEndTimestring

      Time of day as HH:MM or HH:MM:SS

    • courtNamestring
get/guest-fees/members
Members appearing in the paid-fees history
Personal keyManagement keyguest_fees:read

Distinct members that have at least one settled guest fee. Intended to populate filter dropdowns for the history view.

Example

curl "https://app.checkcourt.de/api/v1/guest-fees/members" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • membersobject[]required
    • idstringrequired
    • namestringrequired
delete/guest-fees/{entryId}
Revert a paid mark
Personal keyManagement keyguest_fees:write

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).

Parameters

  • entryIdpath · stringrequired

    Guest fee entry id

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/guest-fees/{entryId}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
post/guest-fees/reset
Settle open guest fees in bulk
Personal keyManagement keyguest_fees:write

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

  • targetUserIdstring

    User id; settles this member's open fees

  • untilDatestring (date)

    Settles all open fees created on or before this date

Example

curl -X POST "https://app.checkcourt.de/api/v1/guest-fees/reset" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired

Settings

get/settings
Get club settings
Personal keyManagement keysettings:read

Returns the whitelisted club settings (dashboard announcement, check-in, guest fees, timezone). The club name is not a setting: it lives on the tenant row, see PATCH /tenant. 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.

Example

curl "https://app.checkcourt.de/api/v1/settings" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • settingsobjectrequired

    Whitelisted club settings. The club name is not here: it lives on the tenant row, see PATCH /tenant. The backing store is a string key-value table, so every value is a string: checkin_enabled and guest_fees_enabled are "true"/"false", checkin_deadline_minutes and guest_fee_cents are integers encoded as strings, timezone is an IANA zone like "Europe/Berlin".

    • announcement_textstring

      Banner text shown on the dashboard; empty string hides the banner

    • announcement_linkstring

      Optional URL the announcement banner links to

    • checkin_deadline_minutesstring

      Integer as string; minutes after booking start until check-in expires

    • checkin_enabled"true" | "false"
    • guest_fee_centsstring

      Integer as string; fee per guest in cents

    • guest_fees_enabled"true" | "false"
    • timezonestring
patch/settings
Update club settings
Personal keyManagement keysettings:write

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_textstring

    Banner text shown on the dashboard; empty string hides the banner

  • announcement_linkstring

    Optional URL the announcement banner links to

  • checkin_deadline_minutesstring

    Integer as string; minutes after booking start until check-in expires

  • checkin_enabled"true" | "false"
  • guest_fee_centsstring

    Integer as string; fee per guest in cents

  • guest_fees_enabled"true" | "false"
  • timezonestring

Example

curl -X PATCH "https://app.checkcourt.de/api/v1/settings" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • updatedintegerrequired

    Number of settings whose value changed

Club

get/tenant
Get club master data
Personal keyManagement keysettings:read_confidential

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.

Example

curl "https://app.checkcourt.de/api/v1/tenant" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • tenantobjectrequired
    • idstringrequired
    • namestringrequired

      Club name

    • slugstringrequired

      Short club code (uppercase letters and digits), used e.g. in member codes

patch/tenant
Change the club name or short code
Personal keyManagement keysettings:write

Send name, slug, or both; at least one is required. name is the club's display name (trimmed, 2-120 chars) and is the single source for the name shown across the product. The slug appears in member codes and on-site displays. Slug 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

  • namestring
  • slugstring

Example

curl -X PATCH "https://app.checkcourt.de/api/v1/tenant" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • namestring

    The normalized name that was stored, if it was sent

  • slugstring

    The normalized slug that was stored, if it was sent

Endpoints for apps

Only with app tokens, never with API keys:

  • GET /app/installation (club app token cca_…): the installation the token was issued for, with the club's settings. More in API for apps.
  • …/metadata on bookings, courts and members, and POST /app/events (club app token): data and events shared with other apps, see Connections between apps.
  • POST /app/notifications (with notifications:send): notify a member, see Notifications.
get/app/installation
Read the calling app's installation and settings
Installation token

Only for club app installation tokens (cca_). Returns the installation the token was minted for, including the club's settings from the manifest's settingsSchema. Read it after app.installed, app.upgraded and app.settings_updated; the event payloads carry ids only. Member app tokens (ccu_) and API keys receive 403: member installations have no settings, a member app reads its club's settings with the club installation token.

Example

curl "https://app.checkcourt.de/api/v1/app/installation" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • installation_idstringrequired
  • app_idstringrequired
  • versionintegerrequired

    Version of the app the installation currently runs on

  • status"active" | "pending_upgrade" | "paused" | "uninstalled"required
  • tenant_idstringrequired

    The club the installation belongs to

  • scopesstring[]required

    Scopes the token holds right now

  • settingsobjectrequired

    Values the club entered in the form generated from the manifest's settingsSchema, defaults filled in. {} when the app has no settings.

  • installed_atstring (date-time)required
get/bookings/{id}/metadata
Read app metadata attached to a booking
Installation tokenbookings:read

Returns the calling app's own keys on this booking and the keys of other apps that the caller declares under reads.metadata in its manifest, the producer declares under shares.metadata, and the club approved. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    Booking id

Example

curl "https://app.checkcourt.de/api/v1/bookings/{id}/metadata" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • metadataobjectrequired

    Grouped by app slug, then by key. Contains the calling app's own keys and the keys of other apps that the caller declares under reads.metadata and the club approved.

put/bookings/{id}/metadata/{key}
Attach or replace a metadata value on a booking
Installation tokenbookings:read

Writes one of the app's own keys. The key must be declared under shares.metadata with object: "booking". A changed value sends app.metadata_changed to the apps the club connected to yours for this key. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    Booking id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Request body

  • valueobjectrequired

    Any JSON value except null, at most 4096 bytes serialized

Example

curl -X PUT "https://app.checkcourt.de/api/v1/bookings/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…" \
  -H "Content-Type: application/json" \
  -d '{"value":"value"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • keystringrequired
  • valueobjectrequired
  • updated_atstring (date-time)required
delete/bookings/{id}/metadata/{key}
Remove one of the app's metadata values from a booking
Installation tokenbookings:read

Removes the app's own value. Works for keys a newer manifest no longer declares, so an app can clean up. deleted: false when there was nothing to remove. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    Booking id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/bookings/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • deletedbooleanrequired
get/courts/{id}/metadata
Read app metadata attached to a court
Installation tokencourts:read

Returns the calling app's own keys on this court and the keys of other apps that the caller declares under reads.metadata in its manifest, the producer declares under shares.metadata, and the club approved. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · integerrequired

    Numeric court id

Example

curl "https://app.checkcourt.de/api/v1/courts/{id}/metadata" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • metadataobjectrequired

    Grouped by app slug, then by key. Contains the calling app's own keys and the keys of other apps that the caller declares under reads.metadata and the club approved.

put/courts/{id}/metadata/{key}
Attach or replace a metadata value on a court
Installation tokencourts:read

Writes one of the app's own keys. The key must be declared under shares.metadata with object: "court". A changed value sends app.metadata_changed to the apps the club connected to yours for this key. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · integerrequired

    Numeric court id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Request body

  • valueobjectrequired

    Any JSON value except null, at most 4096 bytes serialized

Example

curl -X PUT "https://app.checkcourt.de/api/v1/courts/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…" \
  -H "Content-Type: application/json" \
  -d '{"value":"value"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • keystringrequired
  • valueobjectrequired
  • updated_atstring (date-time)required
delete/courts/{id}/metadata/{key}
Remove one of the app's metadata values from a court
Installation tokencourts:read

Removes the app's own value. Works for keys a newer manifest no longer declares, so an app can clean up. deleted: false when there was nothing to remove. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · integerrequired

    Numeric court id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/courts/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • deletedbooleanrequired
get/members/{id}/metadata
Read app metadata attached to a member
Installation tokenmembers:read

Returns the calling app's own keys on this member and the keys of other apps that the caller declares under reads.metadata in its manifest, the producer declares under shares.metadata, and the club approved. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    The member's user id

Example

curl "https://app.checkcourt.de/api/v1/members/{id}/metadata" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • metadataobjectrequired

    Grouped by app slug, then by key. Contains the calling app's own keys and the keys of other apps that the caller declares under reads.metadata and the club approved.

put/members/{id}/metadata/{key}
Attach or replace a metadata value on a member
Installation tokenmembers:read

Writes one of the app's own keys. The key must be declared under shares.metadata with object: "member". A changed value sends app.metadata_changed to the apps the club connected to yours for this key. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    The member's user id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Request body

  • valueobjectrequired

    Any JSON value except null, at most 4096 bytes serialized

Example

curl -X PUT "https://app.checkcourt.de/api/v1/members/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…" \
  -H "Content-Type: application/json" \
  -d '{"value":"value"}'

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • objectobjectrequired
    • type"booking" | "court" | "member"required
    • idstringrequired
  • keystringrequired
  • valueobjectrequired
  • updated_atstring (date-time)required
delete/members/{id}/metadata/{key}
Remove one of the app's metadata values from a member
Installation tokenmembers:read

Removes the app's own value. Works for keys a newer manifest no longer declares, so an app can clean up. deleted: false when there was nothing to remove. Only for club app installation tokens (cca_); member app tokens and API keys receive 403. Data between apps flows only along connections the club approved under Admin, Apps, Verbindungen.

Parameters

  • idpath · stringrequired

    The member's user id

  • keypath · stringrequired

    A key your app declares under shares.metadata for this object type

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/members/{id}/metadata/{key}" \
  -H "Authorization: Bearer cca_…"

Responses

  • 200Success
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • deletedbooleanrequired
post/app/events
Publish an event to connected apps
Installation token

Only for club app installation tokens (cca_). The name must be declared under emits in the manifest. CheckCourt delivers the event as app.<your app slug>.<name> through the regular signed webhooks, only to club installations that declare it under subscribes and that the club connected to yours. At most 60 events per minute per installation (429 with Retry-After beyond).

Request body

  • namestringrequired

    An event the app declares under emits in its manifest

  • dataobject

    At most 4096 bytes serialized. Validated against the event's schema if the manifest declares one. Defaults to {}.

  • subjectobject

    Optional club object the event is about; becomes object in the delivery. Needs the read scope of that object type. Without it, object is the sending installation.

    • type"booking" | "court" | "member"required
    • idstringrequired

Example

curl -X POST "https://app.checkcourt.de/api/v1/app/events" \
  -H "Authorization: Bearer cca_…" \
  -H "Content-Type: application/json" \
  -d '{"name":"name"}'

Responses

  • 200Accepted into the outbox
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • idstringrequired

    evt_…, equal to CheckCourt-Event-Id of every delivery

  • typestringrequired

    app.<your app slug>.<name>

post/app/notifications
Notify a member through CheckCourt
Installation tokenMember app tokennotifications:send (app tokens only)

CheckCourt delivers a short message to one member: in their CheckCourt inbox and, if they allow it, by email. Your app never learns the member's contact data.

recipient accepts only ids your app legitimately received: - the CheckCourt user id, if the installation holds members:read; - the per-installation pseudonym (psn_...) from an extension context token; - the pairwise id (usr_...) from GET /api/v1/me of a member who connected your app.

A member app token may only notify its own member. Unknown ids, ids of other clubs, pending or removed members and ids your app may not use all return the same 404.

url is either a path inside CheckCourt (/booking?date=2026-05-01, not /api/...) or an https link on an origin your app registered (a redirect URI or the listing's connect URL).

Limits: 60 per minute and 1,000 per day per installation, 10 per day per member and app (429 with Retry-After). CheckCourt sends at most 3 emails per member and app per day; further messages only reach the inbox. With the same idempotency_key within 24 hours, the first notification's id comes back and nothing is sent again.

The response never reveals whether the member muted your app. If the club paused your app's notifications, the request fails with 422 BUSINESS_RULE.

Request body

  • recipientstringrequired

    CheckCourt user id (needs members:read), extension pseudonym psn_... or pairwise id usr_...

  • titlestringrequired

    One line of plain text

  • bodystringrequired

    Plain text; line breaks are kept, HTML is shown as text

  • urlstring

    Path inside CheckCourt or https link on an origin your app registered

  • categorystring

    Your own label for the kind of message, stored for later filtering

  • idempotency_keystring

    Repeat a request safely: the same key within 24 hours returns the first notification

Example

curl -X POST "https://app.checkcourt.de/api/v1/app/notifications" \
  -H "Authorization: Bearer cca_…" \
  -H "Content-Type: application/json" \
  -d '{"recipient":"psn_4hQ2v0bD1xZk8yWm3nT7aLc9eRf","title":"Deine Ballmaschine ist bereit","body":"Ab 17:30 Uhr auf Platz 3."}'

Responses

  • 200Accepted for delivery
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • idstringrequired
  • acceptedbooleanrequired

    Always true; whether and how the member sees it stays private

Webhooks

Create and manage the club's webhook endpoints, send test events and read the delivery log. The Webhooks page explains the format, signature and event catalog. As long as the webhooks feature is off for the club, these endpoints respond with 422 BUSINESS_RULE.

get/webhooks
List webhook endpoints
Personal keyManagement keywebhooks:read

All endpoints of the club, oldest first. Secrets are never included. Returns 422 BUSINESS_RULE while the club has webhooks switched off.

Example

curl "https://app.checkcourt.de/api/v1/webhooks" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • webhooksobject[]required
    • idstringrequired

      Prefixed we_

    • urlstring (uri)required

      HTTPS URL that receives the events

    • descriptionstring | nullrequired
    • eventTypes"booking.created" | "booking.updated" | "booking.cancelled" | "booking.checked_in" | "member.joined" | "member.updated" | "member.left" | "court.locked" | "court.unlocked"[]required
    • status"active" | "disabled"required
    • disabledReason"manual" | "consecutive_failures" | "null"required

      Why the endpoint is disabled; null while active

    • failingSincestring | null (date-time)required

      Start of the current run of failed attempts; null while deliveries succeed

    • createdAtstring (date-time)required
    • updatedAtstring (date-time)required
post/webhooks
Create a webhook endpoint
Personal keyManagement keywebhooks:manage

Registers an HTTPS endpoint (plain http only for localhost outside production). The response is the only place the signing secret appears. You can only subscribe to events whose scope (see the event table in the introduction) you hold (403 otherwise). A club can have at most 10 endpoints (422). Returns 422 BUSINESS_RULE while the club has webhooks switched off.

Request body

  • urlstring (uri)required
  • descriptionstring | null
  • eventTypes"booking.created" | "booking.updated" | "booking.cancelled" | "booking.checked_in" | "member.joined" | "member.updated" | "member.left" | "court.locked" | "court.unlocked"[]required

Example

curl -X POST "https://app.checkcourt.de/api/v1/webhooks" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{"url":"url","eventTypes":[]}'

Responses

  • 200The endpoint and its signing secret
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • webhookobjectrequired

    A webhook endpoint. The signing secret is never part of this object; it is returned once by create and rotate-secret.

    • idstringrequired

      Prefixed we_

    • urlstring (uri)required

      HTTPS URL that receives the events

    • descriptionstring | nullrequired
    • eventTypes"booking.created" | "booking.updated" | "booking.cancelled" | "booking.checked_in" | "member.joined" | "member.updated" | "member.left" | "court.locked" | "court.unlocked"[]required
    • status"active" | "disabled"required
    • disabledReason"manual" | "consecutive_failures" | "null"required

      Why the endpoint is disabled; null while active

    • failingSincestring | null (date-time)required

      Start of the current run of failed attempts; null while deliveries succeed

    • createdAtstring (date-time)required
    • updatedAtstring (date-time)required
  • secretstringrequired

    Signing secret (whsec_...). Shown only in this response; store it now.

get/webhooks/{id}
Get a webhook endpoint
Personal keyManagement keywebhooks:read

A single endpoint. The secret is never included. Returns 422 BUSINESS_RULE while the club has webhooks switched off.

Parameters

  • idpath · stringrequired

    Webhook id (the id field from GET /webhooks)

Example

curl "https://app.checkcourt.de/api/v1/webhooks/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • webhookobjectrequired

    A webhook endpoint. The signing secret is never part of this object; it is returned once by create and rotate-secret.

    • idstringrequired

      Prefixed we_

    • urlstring (uri)required

      HTTPS URL that receives the events

    • descriptionstring | nullrequired
    • eventTypes"booking.created" | "booking.updated" | "booking.cancelled" | "booking.checked_in" | "member.joined" | "member.updated" | "member.left" | "court.locked" | "court.unlocked"[]required
    • status"active" | "disabled"required
    • disabledReason"manual" | "consecutive_failures" | "null"required

      Why the endpoint is disabled; null while active

    • failingSincestring | null (date-time)required

      Start of the current run of failed attempts; null while deliveries succeed

    • createdAtstring (date-time)required
    • updatedAtstring (date-time)required
patch/webhooks/{id}
Update a webhook endpoint
Personal keyManagement keywebhooks:manage

Partial update. enabled: false disables the endpoint (disabledReason: manual) and fails its pending deliveries; enabled: true re-activates a disabled endpoint and resets its failure run. Replacing eventTypes needs the scope of every listed event. Returns 422 BUSINESS_RULE while the club has webhooks switched off.

Parameters

  • idpath · stringrequired

    Webhook id (the id field from GET /webhooks)

Request body

  • urlstring (uri)
  • descriptionstring | null
  • eventTypes"booking.created" | "booking.updated" | "booking.cancelled" | "booking.checked_in" | "member.joined" | "member.updated" | "member.left" | "court.locked" | "court.unlocked"[]
  • enabledboolean

Example

curl -X PATCH "https://app.checkcourt.de/api/v1/webhooks/{id}" \
  -H "Authorization: Bearer ck_mgmt_…" \
  -H "Content-Type: application/json" \
  -d '{}'

Responses

  • 200The endpoint as stored
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • webhookobjectrequired

    A webhook endpoint. The signing secret is never part of this object; it is returned once by create and rotate-secret.

    • idstringrequired

      Prefixed we_

    • urlstring (uri)required

      HTTPS URL that receives the events

    • descriptionstring | nullrequired
    • eventTypes"booking.created" | "booking.updated" | "booking.cancelled" | "booking.checked_in" | "member.joined" | "member.updated" | "member.left" | "court.locked" | "court.unlocked"[]required
    • status"active" | "disabled"required
    • disabledReason"manual" | "consecutive_failures" | "null"required

      Why the endpoint is disabled; null while active

    • failingSincestring | null (date-time)required

      Start of the current run of failed attempts; null while deliveries succeed

    • createdAtstring (date-time)required
    • updatedAtstring (date-time)required
delete/webhooks/{id}
Delete a webhook endpoint
Personal keyManagement keywebhooks:manage

Deletes the endpoint together with its delivery log. Returns 422 BUSINESS_RULE while the club has webhooks switched off.

Parameters

  • idpath · stringrequired

    Webhook id (the id field from GET /webhooks)

Example

curl -X DELETE "https://app.checkcourt.de/api/v1/webhooks/{id}" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200Success
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • successbooleanrequired
post/webhooks/{id}/rotate-secret
Rotate the signing secret
Personal keyManagement keywebhooks:manage

Generates a new secret and returns it once. The old secret stops working immediately; pending retries are signed with the new one. Returns 422 BUSINESS_RULE while the club has webhooks switched off.

Parameters

  • idpath · stringrequired

    Webhook id (the id field from GET /webhooks)

Example

curl -X POST "https://app.checkcourt.de/api/v1/webhooks/{id}/rotate-secret" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200The new secret
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • idstringrequired
  • secretstringrequired

    Signing secret (whsec_...). Shown only in this response; store it now.

post/webhooks/{id}/test
Send a test event
Personal keyManagement keywebhooks:manage

Queues a webhook.test event for this endpoint only. It is sent by the next worker run, usually within a minute, and then shows up in the delivery log. Disabled endpoints return 422. Returns 422 BUSINESS_RULE while the club has webhooks switched off.

Parameters

  • idpath · stringrequired

    Webhook id (the id field from GET /webhooks)

Example

curl -X POST "https://app.checkcourt.de/api/v1/webhooks/{id}/test" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200The queued event and delivery
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • eventIdstringrequired
  • deliveryIdstringrequired
get/webhooks/{id}/deliveries
List deliveries of an endpoint
Personal keyManagement keywebhooks:read

Newest first, cursor-paginated: pass nextCursor from the previous page as cursor until it is null. Deliveries are kept for 30 days. Returns 422 BUSINESS_RULE while the club has webhooks switched off.

Parameters

  • idpath · stringrequired

    Webhook id (the id field from GET /webhooks)

  • limitquery · integer
  • cursorquery · string

    nextCursor of the previous page

Example

curl "https://app.checkcourt.de/api/v1/webhooks/{id}/deliveries" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200One page of deliveries
  • 400Request is syntactically or semantically invalid
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • deliveriesobject[]required
    • idstringrequired

      Prefixed whd_

    • webhookIdstringrequired
    • eventIdstringrequired

      Same value as the CheckCourt-Event-Id header and the body's id

    • eventTypestringrequired

      A WebhookEventType or webhook.test

    • eventCreatedAtstring (date-time)required
    • status"pending" | "succeeded" | "failed"required

      failed is final: all attempts are used up or the endpoint was disabled

    • attemptsintegerrequired
    • nextAttemptAtstring | null (date-time)required
    • lastAttemptAtstring | null (date-time)required
    • lastResponseStatusinteger | nullrequired

      HTTP status of the latest attempt; null when no response arrived

    • lastResponseBodystring | nullrequired

      First 2 KB of the latest response body

    • lastErrorstring | nullrequired

      Network or validation error of the latest attempt

    • createdAtstring (date-time)required
  • nextCursorstring | nullrequired
post/webhook-deliveries/{id}/redeliver
Redeliver an event
Personal keyManagement keywebhooks:manage

Queues the delivery again, whatever its current status, with the same event id. It is sent by the next worker run, usually within a minute. Returns 422 when the endpoint is disabled. Returns 422 BUSINESS_RULE while the club has webhooks switched off.

Parameters

  • idpath · stringrequired

    Delivery id (the id field from GET /webhooks/{id}/deliveries)

Example

curl -X POST "https://app.checkcourt.de/api/v1/webhook-deliveries/{id}/redeliver" \
  -H "Authorization: Bearer ck_mgmt_…"

Responses

  • 200The delivery, now pending
  • 401Not authenticated: header missing, key unknown/revoked/expired, or the API key feature is disabled for this club
  • 403The key lacks the required scope, team management rights are missing, or a role change exceeds the rank of the key's member
  • 404Resource does not exist in this club
  • 422Request is valid but violates a business rule (limit reached, duplicate, protected resource)
  • 429More than 60 requests per minute from one IP, or more than 120 per minute with one credential
200er-Schema anzeigen
  • deliveryobjectrequired

    One event sent (or to be sent) to one endpoint, with the outcome of the latest attempt

    • idstringrequired

      Prefixed whd_

    • webhookIdstringrequired
    • eventIdstringrequired

      Same value as the CheckCourt-Event-Id header and the body's id

    • eventTypestringrequired

      A WebhookEventType or webhook.test

    • eventCreatedAtstring (date-time)required
    • status"pending" | "succeeded" | "failed"required

      failed is final: all attempts are used up or the endpoint was disabled

    • attemptsintegerrequired
    • nextAttemptAtstring | null (date-time)required
    • lastAttemptAtstring | null (date-time)required
    • lastResponseStatusinteger | nullrequired

      HTTP status of the latest attempt; null when no response arrived

    • lastResponseBodystring | nullrequired

      First 2 KB of the latest response body

    • lastErrorstring | nullrequired

      Network or validation error of the latest attempt

    • createdAtstring (date-time)required