openapi: 3.0.4
info:
  title: SchoolsBuddy Public API
  description: SchoolsBuddy Public REST API for external integrations.
  contact:
    name: Faria Education Group Limited
    email: support@schoolsbuddy.com
  version: '1.0'
servers:
  - url: https://publicapi-eu.schoolsbuddy.net
    description: EMEA Public Api server
  - url: https://publicapi-asia.schoolsbuddy.net
    description: Asia Public Api server
  - url: https://publicapi-us.schoolsbuddy.net
    description: US Public Api server
  - url: https://publicapi.schoolsbuddy.cn
    description: China Public Api server
  - url: https://identity-eu.schoolsbuddy.net
    description: EMEA Identity server
  - url: https://identity-asia.schoolsbuddy.net
    description: Asia Identity server
  - url: https://identity-us.schoolsbuddy.net
    description: US Identity server
  - url: https://accounts.schoolsbuddy.cn
    description: China Identity server
paths:
  /api/v1/Activities:
    get:
      tags:
        - Activities
      summary: Gets a paginated list of activities configured for the calling organisation(s)
      parameters:
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActivityResponseDtoListPagedActivityFilterResponseDto'
  '/api/v1/Activities/{id}':
    get:
      tags:
        - Activities
      summary: Gets a single activity by id
      parameters:
        - name: id
          in: path
          description: The activity id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the activity up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActivityResponseDto'
  /api/v1/Groups/Class:
    get:
      tags:
        - Class
      summary: "Gets a paginated list of classes for the calling organisation(s),\nsorted by id. Archived classes are added to the result set when\nincludeArchived is true."
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClassResponseDtoListPagedClassFilterResponseDto'
    post:
      tags:
        - Class
      summary: "Creates a class. The class always starts unarchived; the Team and\nSchoolClass pair is created atomically."
      parameters:
        - name: organisationId
          in: query
          description: The organisation to create the class in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClassResponseDto'
  '/api/v1/Groups/Class/{id}':
    get:
      tags:
        - Class
      summary: Gets a single class by id.
      parameters:
        - name: id
          in: path
          description: The class id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the class up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClassResponseDto'
    put:
      tags:
        - Class
      summary: "Partially updates a class — omitted fields preserve their existing\nvalues; renames propagate to both halves of the Team + SchoolClass\npair. The URL {id} is the canonical identifier; the body carries\nno id. Sending isArchived = false unarchives an archived class\n(EC-1 as amended 2026-07-31); any other write against an archived\nclass returns 409 RESOURCE_ARCHIVED."
      parameters:
        - name: id
          in: path
          description: The class id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the class belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClassResponseDto'
  /api/v1/Groups/Class/BulkCreate:
    post:
      tags:
        - Class
      summary: "Creates classes in bulk. Items are processed independently —\nper-item failures are reported in failedItems[] and do not roll\nback the other items."
      requestBody:
        description: The bulk create envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/Class/BulkUpdate:
    put:
      tags:
        - Class
      summary: "Partially updates classes in bulk. Each item carries the target\nid; items are processed independently. An item carrying\nisArchived = false unarchives an archived class (EC-1 as amended\n2026-07-31)."
      requestBody:
        description: The bulk update envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkUpdateClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/Class/BulkArchive:
    post:
      tags:
        - Class
      summary: "Archives or unarchives classes in bulk (toggleable via the\nisArchived body flag) — both halves of the Team + SchoolClass pair\ntransition in lockstep. Alongside PUT / BulkUpdate items carrying\nisArchived = false, the write verbs allowed against\nalready-archived classes (EC-1 as amended 2026-07-31)."
      requestBody:
        description: The bulk archive envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkArchiveClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/Groups/Class/{id}/AddStudents':
    post:
      tags:
        - Class
      summary: "Adds students to a class. Already-assigned students are skipped.\nBoth membership stores are written: PersonTeamRole (the source of\ntruth) and the single-assignment PupilInformation.SchoolClassId."
      parameters:
        - name: id
          in: path
          description: The class id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the class belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClassStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClassStudentsOperationResultDto'
  '/api/v1/Groups/Class/{id}/RemoveStudents':
    post:
      tags:
        - Class
      summary: "Removes students from a class. Students not assigned to the class\nare skipped."
      parameters:
        - name: id
          in: path
          description: The class id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the class belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClassStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClassStudentsOperationResultDto'
  '/api/v1/Groups/Class/{id}/Students':
    get:
      tags:
        - Class
      summary: "Gets the student person ids currently assigned to a class.\nParent-bounded — not paged (BP8 sub-resource exemption)."
      parameters:
        - name: id
          in: path
          description: The class id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the class belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
                  format: int32
  /api/v1/Contacts:
    get:
      tags:
        - Contacts
      summary: Get contacts with filters.
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: ContactType
          in: query
          schema:
            $ref: '#/components/schemas/ContactTypeEnum'
        - name: Search
          in: query
          schema:
            type: string
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactDtoListPagedContactSearchResponseDto'
    post:
      tags:
        - Contacts
      summary: "Create a new contact, linked to between 1 and 10 active students of the\norganisation in the same call (SB-16593): a contact cannot exist without a\nstudent link. Link further students with `POST /api/v1/Students/{id}/contacts`."
      parameters:
        - name: organisationId
          in: query
          description: "The organisation to create the contact in (cross-cutting-design §3.8.1).\nOptional for a single-organisation client, required when the client holds\nmore than one organisation."
          schema:
            type: integer
            format: int32
      requestBody:
        description: The contact creation request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactCreateRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactDto'
  '/api/v1/Contacts/{id}':
    get:
      tags:
        - Contacts
      summary: Get contact by Id.
      parameters:
        - name: id
          in: path
          description: Contact Id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: Organisation Id (optional query parameter)
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactDto'
    put:
      tags:
        - Contacts
      summary: "Update an existing contact. Partial-update semantics (BP10 /\ncross-cutting-design §3.7e): an omitted field preserves the stored value."
      parameters:
        - name: id
          in: path
          description: ''
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: "The organisation the contact belongs to (cross-cutting-design §3.8.1).\nOptional for a single-organisation client, required when the client holds\nmore than one organisation."
          schema:
            type: integer
            format: int32
      requestBody:
        description: The contact update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactUpdateRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactDto'
  /api/v1/Contacts/BulkArchive:
    post:
      tags:
        - Contacts
      summary: "Bulk archive or unarchive contacts. Each id is processed independently —\none failure never rolls back or short-circuits the rest (BP4,\ncross-cutting-design §4)."
      requestBody:
        description: The bulk archive request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactBulkArchiveRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/EventCategories:
    get:
      tags:
        - EventCategories
      summary: "Gets a paginated list of the event categories configured for the\ncalling organisation(s), sorted by name."
      parameters:
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventCategoryResponseDtoListPagedEventCategoryFilterResponseDto'
  '/api/v1/EventCategories/{id}':
    get:
      tags:
        - EventCategories
      summary: "Gets a single event category by id. A deleted category, a fixture\ncategory, or one belonging to another organisation returns\n404 EVENT_CATEGORY_NOT_FOUND."
      parameters:
        - name: id
          in: path
          description: The event category id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the category up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventCategoryResponseDto'
  /api/v1/Events:
    get:
      tags:
        - Events
      summary: Get events with filters.
      parameters:
        - name: StartDateTime
          in: query
          schema:
            type: string
            format: date-time
        - name: EndDateTime
          in: query
          schema:
            type: string
            format: date-time
        - name: Search
          in: query
          schema:
            type: string
        - name: SCStudentId
          in: query
          schema:
            type: integer
            format: int32
        - name: StudentId
          in: query
          schema:
            type: string
        - name: IncludeAttendees
          in: query
          schema:
            type: boolean
        - name: EventType
          in: query
          schema:
            type: string
        - name: IsCancelled
          in: query
          schema:
            type: boolean
        - name: IsArchived
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEventResponseDtoListPagedPublicEventsSearchResponseDto'
  '/api/v1/Events/{id}':
    get:
      tags:
        - Events
      summary: Get event by Id.
      parameters:
        - name: id
          in: path
          description: Event Id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: Organisation Id (optional query parameter)
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEventResponseDto'
  '/api/v1/Events/{id}/attendance':
    get:
      tags:
        - Events
      summary: Get event attendance information.
      parameters:
        - name: id
          in: path
          description: Event Id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: Organisation Id (optional query parameter)
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/EventAttendanceDto'
    put:
      tags:
        - Events
      summary: Update event attendance information.
      parameters:
        - name: id
          in: path
          description: Id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: Organisation Id (optional query parameter)
          schema:
            type: integer
            format: int32
      requestBody:
        description: List of attendance updates
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/EventAttendanceUpdateDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/EventAttendanceDto'
  /api/v1/Events/studentAttendance:
    put:
      tags:
        - Events
      summary: Update student event attendance information.
      parameters:
        - name: organisationId
          in: query
          description: Organisation Id (optional query parameter)
          schema:
            type: integer
            format: int32
      requestBody:
        description: List of attendance updates
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EventStudentAttendanceUpdateDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/External/events:
    post:
      tags:
        - External
      summary: 'Post events from external sources (e.g., Vectare).'
      requestBody:
        description: List of events
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/EventRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
    put:
      tags:
        - External
      summary: "Update or create events from external sources (e.g., Vectare).\nThis endpoint performs an upsert operation - updates existing events or creates new ones if they don't exist."
      requestBody:
        description: List of events
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/EventRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProblemDetails'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
  /api/v1/Groups/Group:
    get:
      tags:
        - Group
      summary: "Gets a paginated list of standard groups for the calling\norganisation(s), sorted by id. Archived groups are added to the\nresult set when includeArchived is true."
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupResponseDtoListPagedGroupFilterResponseDto'
    post:
      tags:
        - Group
      summary: Creates a standard group. The group always starts unarchived.
      parameters:
        - name: organisationId
          in: query
          description: The organisation to create the group in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupResponseDto'
  '/api/v1/Groups/Group/{id}':
    get:
      tags:
        - Group
      summary: Gets a single standard group by id.
      parameters:
        - name: id
          in: path
          description: The group id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the group up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupResponseDto'
    put:
      tags:
        - Group
      summary: "Partially updates a standard group — omitted fields preserve their\nexisting values. The URL {id} is the canonical identifier; the\nbody carries no id. Sending isArchived = false unarchives an\narchived group (EC-1 as amended 2026-07-31); any other write\nagainst an archived group returns 409 RESOURCE_ARCHIVED."
      parameters:
        - name: id
          in: path
          description: The group id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the group belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupResponseDto'
  /api/v1/Groups/Group/BulkCreate:
    post:
      tags:
        - Group
      summary: "Creates standard groups in bulk. Items are processed\nindependently — per-item failures are reported in failedItems[]\nand do not roll back the other items."
      requestBody:
        description: The bulk create envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/Group/BulkUpdate:
    put:
      tags:
        - Group
      summary: "Partially updates standard groups in bulk. Each item carries the\ntarget id; items are processed independently. An item carrying\nisArchived = false unarchives an archived group (EC-1 as amended\n2026-07-31)."
      requestBody:
        description: The bulk update envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkUpdateGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/Group/BulkArchive:
    post:
      tags:
        - Group
      summary: "Archives or unarchives standard groups in bulk (toggleable via the\nisArchived body flag). Alongside PUT / BulkUpdate items carrying\nisArchived = false, the write verbs allowed against\nalready-archived groups (EC-1 as amended 2026-07-31)."
      requestBody:
        description: The bulk archive envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkArchiveGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/Groups/Group/{id}/AddStudents':
    post:
      tags:
        - Group
      summary: "Adds students to a standard group. Already-assigned students are\nskipped."
      parameters:
        - name: id
          in: path
          description: The group id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the group belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GroupStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupStudentsOperationResultDto'
  '/api/v1/Groups/Group/{id}/RemoveStudents':
    post:
      tags:
        - Group
      summary: "Removes students from a standard group. Students not assigned to\nthe group are skipped."
      parameters:
        - name: id
          in: path
          description: The group id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the group belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GroupStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GroupStudentsOperationResultDto'
  '/api/v1/Groups/Group/{id}/Students':
    get:
      tags:
        - Group
      summary: "Gets the student person ids currently assigned to a standard\ngroup. Parent-bounded — not paged (BP8 sub-resource exemption)."
      parameters:
        - name: id
          in: path
          description: The group id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the group belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
                  format: int32
  '/api/v1/Groups/Group/{id}/Events':
    get:
      tags:
        - Group
      summary: "Gets the events linked to a standard group. Parent-bounded — not\npaged (BP8 sub-resource exemption)."
      parameters:
        - name: id
          in: path
          description: The group id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the group belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
        - name: includeCancelled
          in: query
          description: Whether cancelled events are included
          schema:
            type: boolean
            default: false
        - name: includeDeleted
          in: query
          description: Whether deleted events are included
          schema:
            type: boolean
            default: false
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/GroupEventResponseDto'
  /api/v1/Groups/House:
    get:
      tags:
        - House
      summary: "Gets a paginated list of houses for the calling organisation(s),\nsorted by id. Archived houses are added to the result set when\nincludeArchived is true."
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HouseResponseDtoListPagedHouseFilterResponseDto'
    post:
      tags:
        - House
      summary: "Creates a house. The house always starts unarchived; the Team and\nSchoolHouse pair is created atomically."
      parameters:
        - name: organisationId
          in: query
          description: The organisation to create the house in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateHouseRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HouseResponseDto'
  '/api/v1/Groups/House/{id}':
    get:
      tags:
        - House
      summary: Gets a single house by id.
      parameters:
        - name: id
          in: path
          description: The house id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the house up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HouseResponseDto'
    put:
      tags:
        - House
      summary: "Partially updates a house — omitted fields preserve their existing\nvalues; renames propagate to both halves of the Team + SchoolHouse\npair. The URL {id} is the canonical identifier; the body carries\nno id. Sending isArchived = false unarchives an archived house\n(EC-1 as amended 2026-07-31); any other write against an archived\nhouse returns 409 RESOURCE_ARCHIVED."
      parameters:
        - name: id
          in: path
          description: The house id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the house belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateHouseRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HouseResponseDto'
  /api/v1/Groups/House/BulkCreate:
    post:
      tags:
        - House
      summary: "Creates houses in bulk. Items are processed independently —\nper-item failures are reported in failedItems[] and do not roll\nback the other items."
      requestBody:
        description: The bulk create envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateHouseRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/House/BulkUpdate:
    put:
      tags:
        - House
      summary: "Partially updates houses in bulk. Each item carries the target\nid; items are processed independently. An item carrying\nisArchived = false unarchives an archived house (EC-1 as amended\n2026-07-31)."
      requestBody:
        description: The bulk update envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkUpdateHouseRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/House/BulkArchive:
    post:
      tags:
        - House
      summary: "Archives or unarchives houses in bulk (toggleable via the\nisArchived body flag) — both halves of the Team + SchoolHouse pair\ntransition in lockstep. Alongside PUT / BulkUpdate items carrying\nisArchived = false, the write verbs allowed against\nalready-archived houses (EC-1 as amended 2026-07-31)."
      requestBody:
        description: The bulk archive envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkArchiveHouseRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/Groups/House/{id}/AddStudents':
    post:
      tags:
        - House
      summary: "Adds students to a house. Already-assigned students are skipped.\nBoth membership stores are written: PersonTeamRole (the source of\ntruth) and the single-assignment PupilInformation.SchoolHouseId."
      parameters:
        - name: id
          in: path
          description: The house id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the house belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HouseStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HouseStudentsOperationResultDto'
  '/api/v1/Groups/House/{id}/RemoveStudents':
    post:
      tags:
        - House
      summary: "Removes students from a house. Students not assigned to the house\nare skipped."
      parameters:
        - name: id
          in: path
          description: The house id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the house belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HouseStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HouseStudentsOperationResultDto'
  '/api/v1/Groups/House/{id}/Students':
    get:
      tags:
        - House
      summary: "Gets the student person ids currently assigned to a house.\nParent-bounded — not paged (BP8 sub-resource exemption)."
      parameters:
        - name: id
          in: path
          description: The house id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the house belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
                  format: int32
  /api/v1/CcaSignUp/IBP:
    get:
      tags:
        - Ibp
      summary: "Gets a paginated list of Instant Book & Pay signups for the\ncalling organisation(s), sorted by id. Archived signups are added\nwhen includeArchived is true; search filters on the signup name."
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: Search
          in: query
          schema:
            type: string
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IbpResponseDtoListPagedIbpFilterResponseDto'
    post:
      tags:
        - Ibp
      summary: "Creates an Instant Book & Pay signup. The container type is\nderived from the URL (the server always creates Instant Book &\nPay rows) and the preference type is server-set; the signup always\nstarts unarchived. The name must be unique among the\norganisation's active signups."
      parameters:
        - name: organisationId
          in: query
          description: The organisation to create the signup in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateIbpRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IbpResponseDto'
  '/api/v1/CcaSignUp/IBP/{id}':
    get:
      tags:
        - Ibp
      summary: "Gets a single Instant Book & Pay signup by id. Archived signups\n— and signups of any other container type (Preference, PTC) —\nreturn 404 CCASIGNUP_NOT_FOUND."
      parameters:
        - name: id
          in: path
          description: The signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the signup up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IbpResponseDto'
    put:
      tags:
        - Ibp
      summary: "Partially updates an Instant Book & Pay signup — omitted fields\npreserve their existing values (§3.7e). The URL {id} is the\ncanonical identifier; the body carries no id. The signup's archive\nstate cannot be changed here: it follows its groups — archiving\nthe last live group archives the signup, unarchiving any group\nre-activates it. Any write against an archived signup returns\n409 RESOURCE_ARCHIVED."
      parameters:
        - name: id
          in: path
          description: The signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the signup belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateIbpRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IbpResponseDto'
  '/api/v1/CcaSignUp/IBP/{id}/groups':
    get:
      tags:
        - Ibp
      summary: "Gets a paginated list of an Instant Book & Pay signup's child\ngroups, sorted by id. Archived groups are added when\nincludeArchived is true. The sub-resource list has no search\nparameter (locked 2026-06-23). The parent may be archived — its\ngroups stay listable so callers can find the ids to unarchive."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IbpGroupResponseDtoListPagedIbpGroupFilterResponseDto'
    post:
      tags:
        - Ibp
      summary: "Creates a child group under an Instant Book & Pay signup. The\nparent signup must exist as an IBP signup (404 CCASIGNUP_NOT_FOUND)\nand must not be archived (409 RESOURCE_ARCHIVED — unarchive one of\nits groups first, which re-activates the signup). The group always\nstarts unarchived. Preference-only fields (day1/day2 triples,\ncost, joinRequestsOn) are not part of the IBP group shape and are\nsilently ignored if sent."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the signup belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateIbpGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IbpGroupResponseDto'
  '/api/v1/CcaSignUp/IBP/{id}/groups/{groupId}':
    put:
      tags:
        - Ibp
      summary: "Partially updates a child group under an Instant Book & Pay\nsignup — omitted fields preserve their existing values (§3.7e);\nfor the availableTo / preRequisite / notAvailableTo lists an\nomitted field preserves the stored set while an empty array clears\nit. Setting isArchived = true archives the group — rejected with\n409 CCASIGNUP_ARCHIVE_BLOCKED_ACTIVE while the group has future\nevents; archiving the LAST live group also archives the signup.\nSending isArchived = false unarchives an archived group (EC-1 as\namended 2026-07-31, never blocked) and re-activates an archived\nsignup — subject to the signup's NAME_NOT_UNIQUE\nunarchive-into-collision guard; any other write against an\narchived group returns 409 RESOURCE_ARCHIVED."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: groupId
          in: path
          description: The child group id (Team.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the signup belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateIbpGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IbpGroupResponseDto'
  '/api/v1/CcaSignUp/IBP/{id}/groups/BulkCreate':
    post:
      tags:
        - Ibp
      summary: "Creates child groups under an Instant Book & Pay signup in\nbulk. The parent signup gates the whole request (validated before\nany per-item work); items are then processed independently."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
      requestBody:
        description: The bulk create envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateIbpGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/CcaSignUp/IBP/{id}/groups/BulkUpdate':
    put:
      tags:
        - Ibp
      summary: "Partially updates child groups under an Instant Book & Pay\nsignup in bulk. The parent signup gates the whole request\n(validated before any per-item work); each item carries the target\ngroup id and items are processed independently. Archive semantics\nper item match the single-resource PUT: isArchived = true is\ngated on no future events and can archive the signup via the\nlast-live-group cascade; isArchived = false unarchives (EC-1 as\namended 2026-07-31) and re-activates an archived signup."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
      requestBody:
        description: The bulk update envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkUpdateIbpGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/CcaSignUp/IBP/{id}/groups/BulkArchive':
    post:
      tags:
        - Ibp
      summary: "Archives or unarchives child groups under an Instant Book &\nPay signup in bulk (toggleable via the isArchived body flag).\nArchiving is rejected per item (CCASIGNUP_ARCHIVE_BLOCKED_ACTIVE)\nwhile a group has future events; archiving the LAST live group\nalso archives the signup. Unarchiving is never blocked and\nre-activates an archived signup — subject to the signup's\nNAME_NOT_UNIQUE unarchive-into-collision guard. Alongside PUT /\nBulkUpdate items carrying isArchived = false, the write verbs\nallowed against already-archived groups (EC-1 as amended\n2026-07-31)."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
      requestBody:
        description: The bulk archive envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkArchiveIbpGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/Integrations/isams/{organisationId}':
    get:
      tags:
        - Integrations
      summary: Gets the iSAMS integration configuration for an organisation.
      parameters:
        - name: organisationId
          in: path
          description: Organisation identifier (route segment).
          required: true
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IsamsConfigResponseDto'
    patch:
      tags:
        - Integrations
      summary: Updates one or more iSAMS integration configuration settings for an organisation.
      parameters:
        - name: organisationId
          in: path
          description: Organisation identifier (route segment).
          required: true
          schema:
            type: integer
            format: int32
      requestBody:
        description: The partial-update payload.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IsamsConfigPatchRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IsamsConfigResponseDto'
  /api/v1/Locations:
    get:
      tags:
        - Locations
      summary: Gets a paginated list of locations
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: Search
          in: query
          schema:
            maxLength: 200
            type: string
        - name: IsHome
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LocationDtoListPagedLocationFilterResponseDto'
    post:
      tags:
        - Locations
      summary: Creates a new location
      parameters:
        - name: organisationId
          in: query
          description: "The organisation to create the location in (cross-cutting-design §3.8.1 — the\nPublic API's single-resource write convention). Optional for a single-organisation\nclient. The legacy `organisationId` request-body field is still honoured for\nexisting callers; when both are supplied they must agree."
          schema:
            type: integer
            format: int32
      requestBody:
        description: The location creation request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateLocationRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LocationDto'
  /api/v1/CcaSignUp/Pref:
    get:
      tags:
        - Pref
      summary: "Gets a paginated list of Preference signups for the calling\norganisation(s), sorted by id. Archived signups are added when\nincludeArchived is true; search filters on the signup name."
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: Search
          in: query
          schema:
            type: string
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrefResponseDtoListPagedPrefFilterResponseDto'
    post:
      tags:
        - Pref
      summary: "Creates a Preference signup. The container type and the preference\ntype are both derived from the URL — the server always creates\nPreference rows. preferenceSelectionScope chooses whether a pupil's\n1-5 ranking restarts each day (Daily, the default) or runs across\nthe whole week (Weekly); it accepts the name or its ordinal. The\nsignup always starts unarchived. The name must be unique among the\norganisation's active signups."
      parameters:
        - name: organisationId
          in: query
          description: The organisation to create the signup in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePrefRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrefResponseDto'
  '/api/v1/CcaSignUp/Pref/{id}':
    get:
      tags:
        - Pref
      summary: "Gets a single Preference signup by id. Archived signups — and\nsignups of any other container type (Instant Book & Pay, PTC) —\nreturn 404 CCASIGNUP_NOT_FOUND."
      parameters:
        - name: id
          in: path
          description: The signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the signup up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrefResponseDto'
    put:
      tags:
        - Pref
      summary: "Partially updates a Preference signup — omitted fields preserve\ntheir existing values (§3.7e). The URL {id} is the canonical\nidentifier; the body carries no id. The signup's\narchive state cannot be changed here: it follows its groups —\narchiving the last live group archives the signup, unarchiving any\ngroup re-activates it. Any write against an archived signup returns\n409 RESOURCE_ARCHIVED."
      parameters:
        - name: id
          in: path
          description: The signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the signup belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdatePrefRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrefResponseDto'
  '/api/v1/CcaSignUp/Pref/{id}/groups':
    get:
      tags:
        - Pref
      summary: "Gets a paginated list of a Preference signup's child groups, sorted\nby id. Archived groups are added when includeArchived is true. The\nsub-resource list has no search parameter (locked 2026-06-23). The\nparent may be archived — its groups stay listable so callers can\nfind the ids to unarchive."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrefGroupResponseDtoListPagedPrefGroupFilterResponseDto'
    post:
      tags:
        - Pref
      summary: "Creates a child group under a Preference signup. The parent signup\nmust exist as a Preference signup (404 CCASIGNUP_NOT_FOUND) and\nmust not be archived (409 RESOURCE_ARCHIVED — unarchive one of its\ngroups first, which re-activates the signup). The day1 triple\n(day1, day1StartTime, day1EndTime) is required; supplying the day2\ntriple adds a second weekly session. Day times are\norganisation-local and are interpreted via the timeZone on the\nresponse. costType is derived from cost and is ignored if sent.\njoinRequestsOn defaults to true when omitted. The group always\nstarts unarchived."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the signup belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePrefGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrefGroupResponseDto'
  '/api/v1/CcaSignUp/Pref/{id}/groups/{groupId}':
    put:
      tags:
        - Pref
      summary: "Partially updates a child group under a Preference signup — omitted\nfields preserve their existing values (§3.7e). Each day triple is\natomic: send all three of its fields to change that session, or\nnone to leave it as it is (omitting them does not clear the\nsession). cost re-derives costType only when it is present and\nnon-null. For the availableTo / preRequisite / notAvailableTo lists\nan omitted field preserves the stored set while an empty array\nclears it. Setting isArchived = true archives the group — rejected\nwith 409 CCASIGNUP_ARCHIVE_BLOCKED_ACTIVE while the group has\nfuture events; archiving the LAST live group also archives the\nsignup. Sending isArchived = false unarchives an archived group\n(EC-1 as amended 2026-07-31, never blocked) and re-activates an\narchived signup — subject to the signup's NAME_NOT_UNIQUE\nunarchive-into-collision guard; any other write against an archived\ngroup returns 409 RESOURCE_ARCHIVED."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
        - name: groupId
          in: path
          description: The child group id (Team.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the signup belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdatePrefGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PrefGroupResponseDto'
  '/api/v1/CcaSignUp/Pref/{id}/groups/BulkCreate':
    post:
      tags:
        - Pref
      summary: "Creates child groups under a Preference signup in bulk. The parent\nsignup gates the whole request (validated before any per-item\nwork); items are then processed independently."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
      requestBody:
        description: The bulk create envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreatePrefGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/CcaSignUp/Pref/{id}/groups/BulkUpdate':
    put:
      tags:
        - Pref
      summary: "Partially updates child groups under a Preference signup in bulk.\nThe parent signup gates the whole request (validated before any\nper-item work); each item carries the target group id and items are\nprocessed independently. Day-triple, cost and archive semantics per\nitem match the single-resource PUT."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
      requestBody:
        description: The bulk update envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkUpdatePrefGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/CcaSignUp/Pref/{id}/groups/BulkArchive':
    post:
      tags:
        - Pref
      summary: "Archives or unarchives child groups under a Preference signup in\nbulk (toggleable via the isArchived body flag). Archiving is\nrejected per item (CCASIGNUP_ARCHIVE_BLOCKED_ACTIVE) while a group\nhas future events; archiving the LAST live group also archives the\nsignup. Unarchiving is never blocked and re-activates an archived\nsignup — subject to the signup's NAME_NOT_UNIQUE\nunarchive-into-collision guard. Alongside PUT / BulkUpdate items\ncarrying isArchived = false, the write verbs allowed against\nalready-archived groups (EC-1 as amended 2026-07-31)."
      parameters:
        - name: id
          in: path
          description: The parent signup id (CcaSignUp.CcaSignUpId)
          required: true
          schema:
            type: integer
            format: int32
      requestBody:
        description: The bulk archive envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkArchivePrefGroupRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Staff:
    get:
      tags:
        - Staff
      summary: Gets a paginated list of staff members
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: Search
          in: query
          schema:
            maxLength: 200
            type: string
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StaffDataDtoListPagedStaffFilterResponseDto'
    post:
      tags:
        - Staff
      summary: "Create a new staff member. `isArchived` is not part of the create\ncontract (BP2) — a staff member is always created active and any value\nsent for it is silently ignored."
      parameters:
        - name: organisationId
          in: query
          description: The organisation to create the staff member in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StaffCreateRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StaffCoreDto'
  '/api/v1/Staff/{id}':
    get:
      tags:
        - Staff
      summary: Get staff by Id (full details).
      parameters:
        - name: id
          in: path
          description: The staff member id (Person.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the staff member up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StaffCoreDto'
    put:
      tags:
        - Staff
      summary: "Partially updates a staff member — omitted (or explicitly null) fields\npreserve their stored values (BP10 / §3.7e, D14). Sending\n`isArchived` archives or unarchives; omitting it leaves the\narchive state alone. An archived staff member accepts only a PUT carrying\n`isArchived: false`. The response is the staff member as stored after\nthe write — including when the PUT has just archived it."
      parameters:
        - name: id
          in: path
          description: The staff member id (Person.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the staff member belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StaffUpdateRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StaffCoreDto'
  /api/v1/Staff/BulkUpdateOnlineMeetingId:
    patch:
      tags:
        - Staff
      summary: "Bulk update OnlineMeetingId for staff members.\n\n<b>Breaking (SB-15677, hard cut):</b> the request body was a bare JSON\narray of items and is now the `{ \"items\": [ ... ] }` envelope; the\nold shape returns `400 VALIDATION_FAILED`. The response was an\nempty `200` and is now the standard bulk envelope.\nItems are processed independently (BP4), like every other bulk endpoint: an\ninvalid item fails with `VALIDATION_FAILED`, an id that is not an active\nstaff member of the organisation with `STAFF_NOT_FOUND`, a SchoolsBuddy\nsupport user with `CONFLICT` — each in `failedItems` at its own index —\nwhile every valid item is written and the whole call returns `200`. A staff\nmember with no meeting id yet can be given one. When an id appears more than\nonce, the last occurrence is the value stored."
      parameters:
        - name: organisationId
          in: query
          description: The organisation the staff members belong to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The bulk update envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StaffBulkUpdateOnlineMeetingIdRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Staff/BulkArchive:
    post:
      tags:
        - Staff
      summary: "Bulk archive or unarchive staff.\n\n<b>Breaking (SB-15677):</b> the response was an empty `200` and is\nnow the standard bulk envelope. The request body and the\n`organisationId` query parameter are unchanged. Items are\nprocessed independently (BP4) — an id that is not a staff member of\nthe organisation fails only its own item with\n`STAFF_NOT_FOUND`, and the whole call still returns `200`.\nSchoolsBuddy support users were silently skipped before and now fail\ntheir item with `CONFLICT`."
      parameters:
        - name: organisationId
          in: query
          description: The organisation the staff members belong to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The bulk archive request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StaffBulkArchiveRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Students:
    get:
      tags:
        - Students
      summary: Gets a paginated list of students
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: Search
          in: query
          schema:
            maxLength: 200
            type: string
        - name: Grade
          in: query
          schema:
            maxLength: 100
            type: string
        - name: HomeroomClass
          in: query
          schema:
            maxLength: 100
            type: string
        - name: House
          in: query
          schema:
            maxLength: 100
            type: string
        - name: HomeroomAdvisorId
          in: query
          schema:
            type: string
        - name: SCStudentIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
        - name: StudentIds
          in: query
          schema:
            type: array
            items:
              type: string
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StudentPublicDataDtoListPagedStudentFilterResponseDto'
    post:
      tags:
        - Students
      summary: Create a new student.
      parameters:
        - name: organisationId
          in: query
          schema:
            type: integer
            format: int32
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StudentCreateRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StudentCoreDto'
  '/api/v1/Students/{id}':
    get:
      tags:
        - Students
      summary: Get student by Id (full details).
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StudentCoreDto'
    put:
      tags:
        - Students
      summary: Update an existing student.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          schema:
            type: integer
            format: int32
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StudentUpdateRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: string
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StudentCoreDto'
        '409':
          description: Conflict
          content:
            application/json:
              schema:
                type: string
  /api/v1/Students/BulkArchive:
    post:
      tags:
        - Students
      summary: Bulk archive or unarchive students.
      parameters:
        - name: organisationId
          in: query
          description: ''
          schema:
            type: integer
            format: int32
      requestBody:
        description: The bulk archive request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StudentBulkArchiveRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
  '/api/v1/Students/{id}/health':
    get:
      tags:
        - Students
      summary: Gets student health information by student identifier
      parameters:
        - name: id
          in: path
          description: The student identifier
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: ''
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: string
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/StudentHealthResponseDto'
    patch:
      tags:
        - Students
      summary: Updates student health information
      parameters:
        - name: id
          in: path
          description: The person identifier
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: ''
          schema:
            type: integer
            format: int32
      requestBody:
        description: The health update request
        content:
          application/json:
            schema:
              type: array
              items:
                $ref: '#/components/schemas/StudentHealthUpdateRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: string
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/StudentHealthResponseDto'
  '/api/v1/Students/{id}/contacts':
    post:
      tags:
        - Students
      summary: "Add contacts to a student. Links never cross organisations (SB-16593): the student\nmust be a student of the organisation and every contact an existing contact of it,\nor nothing is written."
      parameters:
        - name: id
          in: path
          description: Student ID
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: Organisation Id (optional query parameter)
          schema:
            type: integer
            format: int32
      requestBody:
        description: List of contact IDs to add
        content:
          application/json:
            schema:
              type: array
              items:
                type: integer
                format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: string
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StudentCoreDto'
    delete:
      tags:
        - Students
      summary: Remove contacts from a student.
      parameters:
        - name: id
          in: path
          description: Student ID
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: Organisation Id (optional query parameter)
          schema:
            type: integer
            format: int32
      requestBody:
        description: List of contact IDs to remove
        content:
          application/json:
            schema:
              type: array
              items:
                type: integer
                format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: string
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StudentCoreDto'
  /api/v1/Groups/Subject:
    get:
      tags:
        - Subject
      summary: "Gets a paginated list of Subjects for the calling organisation(s),\nsorted by id. Archived Subjects are added when includeArchived is true."
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectResponseDtoListPagedSubjectFilterResponseDto'
    post:
      tags:
        - Subject
      summary: "Creates a Subject. The Subject always starts unarchived and is never\nimport-managed (ThirdPartyId is not set)."
      parameters:
        - name: organisationId
          in: query
          description: The organisation to create the Subject in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSubjectRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectResponseDto'
  '/api/v1/Groups/Subject/{id}':
    get:
      tags:
        - Subject
      summary: "Gets a single Subject by id. Archived Subjects return\n404 SUBJECT_NOT_FOUND (§11)."
      parameters:
        - name: id
          in: path
          description: The Subject id (Subject.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the Subject up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectResponseDto'
    put:
      tags:
        - Subject
      summary: "Partially updates a Subject — omitted fields preserve their existing\nvalues (§3.7e). The URL {id} is the canonical identifier; the body\ncarries no id. Setting isArchived = true cascade-archives the\nSubject's active SubjectClasses. Sending isArchived = false\nunarchives an archived Subject with no class cascade (EC-1 as\namended 2026-07-31); any other write against an archived Subject\nreturns 409 RESOURCE_ARCHIVED."
      parameters:
        - name: id
          in: path
          description: The Subject id (Subject.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the Subject belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSubjectRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectResponseDto'
  /api/v1/Groups/Subject/BulkCreate:
    post:
      tags:
        - Subject
      summary: "Creates Subjects in bulk. Items are processed independently — per-item\nfailures are reported in failedItems[] and do not roll back the\nother items."
      requestBody:
        description: The bulk create envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateSubjectRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/Subject/BulkUpdate:
    put:
      tags:
        - Subject
      summary: "Partially updates Subjects in bulk. Each item carries the target id;\nitems are processed independently. An item carrying\nisArchived = false unarchives an archived Subject (EC-1 as amended\n2026-07-31)."
      requestBody:
        description: The bulk update envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkUpdateSubjectRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/Subject/BulkArchive:
    post:
      tags:
        - Subject
      summary: "Archives or unarchives Subjects in bulk (toggleable via the isArchived\nbody flag). Archiving cascade-archives each Subject's active\nSubjectClasses; unarchiving restores the Subject only. Alongside\nPUT / BulkUpdate items carrying isArchived = false, the write verbs\nallowed against already-archived Subjects (EC-1 as amended\n2026-07-31)."
      requestBody:
        description: The bulk archive envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkArchiveSubjectRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/SubjectClass:
    get:
      tags:
        - SubjectClass
      summary: "Gets a paginated list of Subject Classes for the calling\norganisation(s), sorted by id. Archived Subject Classes are added\nwhen includeArchived is true."
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectClassResponseDtoListPagedSubjectClassFilterResponseDto'
    post:
      tags:
        - SubjectClass
      summary: "Creates a Subject Class. The Subject Class always starts unarchived\nand is never import-managed (ThirdPartyId is not set). The\nreferenced Subject, Year Group and lead staff must all be active in\nthe requesting organisation."
      parameters:
        - name: organisationId
          in: query
          description: The organisation to create the Subject Class in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSubjectClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectClassResponseDto'
  '/api/v1/Groups/SubjectClass/{id}':
    get:
      tags:
        - SubjectClass
      summary: "Gets a single Subject Class by id. Archived Subject Classes return\n404 SUBJECTCLASS_NOT_FOUND (§11)."
      parameters:
        - name: id
          in: path
          description: The Subject Class id (SubjectClass.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the Subject Class up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectClassResponseDto'
    put:
      tags:
        - SubjectClass
      summary: "Partially updates a Subject Class — omitted fields preserve their\nexisting values (§3.7e). The URL {id} is the canonical identifier;\nthe body carries no id. subjectId / schoolYearGroupId re-parenting\nis allowed. Setting isArchived = true archives the row; the parent\nSubject is unaffected. Sending isArchived = false unarchives an\narchived Subject Class (EC-1 as amended 2026-07-31), restoring an\narchived parent Subject in the same transaction (upward cascade);\nany other write against an archived Subject Class returns\n409 RESOURCE_ARCHIVED."
      parameters:
        - name: id
          in: path
          description: The Subject Class id (SubjectClass.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the Subject Class belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSubjectClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectClassResponseDto'
  /api/v1/Groups/SubjectClass/BulkCreate:
    post:
      tags:
        - SubjectClass
      summary: "Creates Subject Classes in bulk. Items are processed independently —\nper-item failures are reported in failedItems[] and do not roll\nback the other items."
      requestBody:
        description: The bulk create envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateSubjectClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/SubjectClass/BulkUpdate:
    put:
      tags:
        - SubjectClass
      summary: "Partially updates Subject Classes in bulk. Each item carries the\ntarget id; items are processed independently. An item carrying\nisArchived = false unarchives an archived Subject Class (EC-1 as\namended 2026-07-31)."
      requestBody:
        description: The bulk update envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkUpdateSubjectClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/SubjectClass/BulkArchive:
    post:
      tags:
        - SubjectClass
      summary: "Archives or unarchives Subject Classes in bulk (toggleable via the\nisArchived body flag). Archiving leaves the parent Subject\nuntouched; unarchiving a Subject Class whose parent Subject is\narchived also restores the parent (upward cascade). Alongside\nPUT / BulkUpdate items carrying isArchived = false, the write verbs\nallowed against already-archived Subject Classes (EC-1 as amended\n2026-07-31)."
      requestBody:
        description: The bulk archive envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkArchiveSubjectClassRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/Groups/SubjectClass/{id}/AddStudents':
    post:
      tags:
        - SubjectClass
      summary: "Adds students to a Subject Class (SubjectClassPupil membership).\nAlready-assigned students are skipped."
      parameters:
        - name: id
          in: path
          description: The Subject Class id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the Subject Class belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubjectClassStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectClassStudentsOperationResultDto'
  '/api/v1/Groups/SubjectClass/{id}/RemoveStudents':
    post:
      tags:
        - SubjectClass
      summary: "Removes students from a Subject Class. Students not assigned to the\nSubject Class are skipped."
      parameters:
        - name: id
          in: path
          description: The Subject Class id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the Subject Class belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubjectClassStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubjectClassStudentsOperationResultDto'
  '/api/v1/Groups/SubjectClass/{id}/Students':
    get:
      tags:
        - SubjectClass
      summary: "Gets the student person ids currently assigned to a Subject Class.\nParent-bounded — not paged (BP8 sub-resource exemption)."
      parameters:
        - name: id
          in: path
          description: The Subject Class id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the Subject Class belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
                  format: int32
  /api/v1/Groups/Year:
    get:
      tags:
        - Year
      summary: "Gets a paginated list of Years for the calling organisation(s),\nsorted by id. The \"Whole school\" row is always present in the active\nset; archived Years are added when includeArchived is true."
      parameters:
        - name: IncludeArchived
          in: query
          schema:
            type: boolean
        - name: PageNumber
          in: query
          schema:
            maximum: 2147483647
            minimum: 1
            type: integer
            format: int32
        - name: PageSize
          in: query
          schema:
            maximum: 2000
            minimum: 1
            type: integer
            format: int32
        - name: OrganisationIds
          in: query
          schema:
            type: array
            items:
              type: integer
              format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YearResponseDtoListPagedYearFilterResponseDto'
    post:
      tags:
        - Year
      summary: "Creates a Year. The Year always starts unarchived; the SchoolYearGroup\nand Club pair is created atomically, with server-managed\ndescription = name and a server-allocated schoolYearGroupId."
      parameters:
        - name: organisationId
          in: query
          description: The organisation to create the Year in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The create request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateYearRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YearResponseDto'
  '/api/v1/Groups/Year/{id}':
    get:
      tags:
        - Year
      summary: Gets a single Year by id. Reads are allowed on the "Whole school" row.
      parameters:
        - name: id
          in: path
          description: The Year id (Club.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation to look the Year up in — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YearResponseDto'
    put:
      tags:
        - Year
      summary: "Partially updates a Year — omitted fields preserve their existing\nvalues; renames propagate to both halves of the SchoolYearGroup +\nClub pair and re-mirror description. The URL {id} is the canonical\nidentifier; the body carries no id. Sending isArchived = false\nunarchives an archived Year (EC-1 as amended 2026-07-31); any other\nwrite against an archived Year returns 409 RESOURCE_ARCHIVED.\nWrites against the \"Whole school\" row return\n409 YEAR_WHOLE_SCHOOL_NOT_EDITABLE."
      parameters:
        - name: id
          in: path
          description: The Year id (Club.Id)
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the Year belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The update request
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateYearRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YearResponseDto'
  /api/v1/Groups/Year/BulkCreate:
    post:
      tags:
        - Year
      summary: "Creates Years in bulk. Items are processed independently — per-item\nfailures are reported in failedItems[] and do not roll back the\nother items."
      requestBody:
        description: The bulk create envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkCreateYearRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/Year/BulkUpdate:
    put:
      tags:
        - Year
      summary: "Partially updates Years in bulk. Each item carries the target id;\nitems are processed independently. An item carrying\nisArchived = false unarchives an archived Year (EC-1 as amended\n2026-07-31)."
      requestBody:
        description: The bulk update envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkUpdateYearRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  /api/v1/Groups/Year/BulkArchive:
    post:
      tags:
        - Year
      summary: "Archives or unarchives Years in bulk (toggleable via the isArchived\nbody flag) — both halves of the SchoolYearGroup + Club pair\ntransition in lockstep. Alongside PUT / BulkUpdate items carrying\nisArchived = false, the write verbs allowed against\nalready-archived Years (EC-1 as amended 2026-07-31). The\n\"Whole school\" row fails per-item with\nYEAR_WHOLE_SCHOOL_NOT_EDITABLE."
      requestBody:
        description: The bulk archive envelope
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkArchiveYearRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Int32BulkOperationResult'
  '/api/v1/Groups/Year/{id}/AddStudents':
    post:
      tags:
        - Year
      summary: "Adds students to a Year — a single-store write to\nPupilInformation.SchoolYearGroupId. Already-assigned students are\nskipped. Membership writes against the \"Whole school\" row return\n409 YEAR_WHOLE_SCHOOL_NOT_EDITABLE."
      parameters:
        - name: id
          in: path
          description: The Year id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the Year belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/YearStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YearStudentsOperationResultDto'
  '/api/v1/Groups/Year/{id}/RemoveStudents':
    post:
      tags:
        - Year
      summary: "Removes students from a Year. Students not assigned to the Year are\nskipped."
      parameters:
        - name: id
          in: path
          description: The Year id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the Year belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      requestBody:
        description: The student ids
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/YearStudentsRequestDto'
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YearStudentsOperationResultDto'
  '/api/v1/Groups/Year/{id}/Students':
    get:
      tags:
        - Year
      summary: "Gets the student person ids currently assigned to a Year.\nParent-bounded — not paged (BP8 sub-resource exemption)."
      parameters:
        - name: id
          in: path
          description: The Year id
          required: true
          schema:
            type: integer
            format: int32
        - name: organisationId
          in: query
          description: The organisation the Year belongs to — required when the client has access to multiple organisations
          schema:
            type: integer
            format: int32
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: integer
                  format: int32
components:
  schemas:
    ActivityResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        sortPrefix:
          type: integer
          format: int32
        name:
          type: string
          nullable: true
        isForAllGroups:
          type: boolean
        isSport:
          type: boolean
        isTrip:
          type: boolean
        isOther:
          type: boolean
      additionalProperties: false
    ActivityResponseDtoListPagedActivityFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/ActivityResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    AttendeeRegisterStateEnum:
      enum:
        - Unset
        - Present
        - Absent
        - Late
        - Excused
      type: string
    AttendeeStatusEnum:
      enum:
        - ToBeConfirmed
        - Yes
        - No
        - IfRequired
        - Confirmed
      type: string
    BulkArchiveClassRequestDto:
      required:
        - ids
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
          description: "Gets or sets the ids of the classes to transition. Id validity is\nchecked per item (EC-7) — 0 / negative ids fail that item only."
        isArchived:
          type: boolean
          description: "Gets or sets a value indicating whether the classes are archived\n(true, default) or unarchived (false)."
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/Class/BulkArchive (SB-15447).\nToggleable: isArchived true archives, false unarchives (BulkArchive and\na PUT / BulkUpdate item carrying isArchived: false are the verbs allowed\nto operate on already-archived rows — EC-1 as amended 2026-07-31).\nBoth halves of the Team + SchoolClass pair transition in lockstep."
    BulkArchiveGroupRequestDto:
      required:
        - ids
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
          description: "Gets or sets the ids of the groups to transition. Id validity is\nchecked per item (EC-7) — 0 / negative ids fail that item only."
        isArchived:
          type: boolean
          description: "Gets or sets a value indicating whether the groups are archived\n(true, default) or unarchived (false)."
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/Group/BulkArchive (SB-15446).\nToggleable: isArchived true archives, false unarchives (BulkArchive and\na PUT / BulkUpdate item carrying isArchived: false are the verbs allowed\nto operate on already-archived rows — EC-1 as amended 2026-07-31)."
    BulkArchiveHouseRequestDto:
      required:
        - ids
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
          description: "Gets or sets the ids of the houses to transition. Id validity is\nchecked per item (EC-7) — 0 / negative ids fail that item only."
        isArchived:
          type: boolean
          description: "Gets or sets a value indicating whether the houses are archived\n(true, default) or unarchived (false)."
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/House/BulkArchive (SB-15448).\nToggleable: isArchived true archives, false unarchives (BulkArchive and\na PUT / BulkUpdate item carrying isArchived: false are the verbs allowed\nto operate on already-archived rows — EC-1 as amended 2026-07-31).\nBoth halves of the Team + SchoolHouse pair transition in lockstep."
    BulkArchiveIbpGroupRequestDto:
      required:
        - ids
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
          description: "Gets or sets the ids (Team.Id) of the child groups to transition.\nId validity is checked per item (EC-7) — 0 / negative ids fail\nthat item only."
        isArchived:
          type: boolean
          description: "Gets or sets a value indicating whether the groups are archived\n(true, default) or unarchived (false)."
      additionalProperties: false
      description: "Request body for POST /api/v1/CcaSignUp/IBP/{id}/groups/BulkArchive\n(SB-15665 §10 C3). Toggleable: isArchived true archives each group\n(Team.StatusId = Archive) — blocked per item with\nCCASIGNUP_ARCHIVE_BLOCKED_ACTIVE while the group has future events\n(§10 D2); false unarchives (StatusId = Active, never blocked). The\ncontainer cascade runs per item: archiving the last live group\narchives the container (CcaSignUp.Status = 4); unarchiving any group\nre-activates it. The parent signup id in the URL gates the whole\nrequest (CCASIGNUP_NOT_FOUND, validated before any per-item work) —\nan ARCHIVED parent is allowed here, since unarchiving a group is the\ncontainer's recovery path (§10 D5)."
    BulkArchivePrefGroupRequestDto:
      required:
        - ids
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
          description: "Gets or sets the ids (Team.Id) of the child groups to transition.\nId validity is checked per item (EC-7) — 0 / negative ids fail\nthat item only."
        isArchived:
          type: boolean
          description: "Gets or sets a value indicating whether the groups are archived\n(true, default) or unarchived (false)."
      additionalProperties: false
      description: "Request body for POST /api/v1/CcaSignUp/Pref/{id}/groups/BulkArchive\n(SB-15666, mirroring SB-15665 §10 C3). Toggleable: isArchived true\narchives each group (Team.StatusId = Archive) — blocked per item with\nCCASIGNUP_ARCHIVE_BLOCKED_ACTIVE while the group has future events\n(§10 D2); false unarchives (StatusId = Active, never blocked). The\ncontainer cascade runs per item: archiving the last live group\narchives the container (CcaSignUp.Status = 4); unarchiving any group\nre-activates it. The parent signup id in the URL gates the whole\nrequest (CCASIGNUP_NOT_FOUND, validated before any per-item work) —\nan ARCHIVED parent is allowed here, since unarchiving a group is the\ncontainer's recovery path (§10 D5)."
    BulkArchiveSubjectClassRequestDto:
      required:
        - ids
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
          description: "Gets or sets the ids (SubjectClass.Id) of the Subject Classes to\ntransition. Id validity is checked per item (EC-7) — 0 / negative\nids fail that item only."
        isArchived:
          type: boolean
          description: "Gets or sets a value indicating whether the Subject Classes are\narchived (true, default) or unarchived (false)."
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/SubjectClass/BulkArchive\n(SB-15451). Toggleable: isArchived true archives (the parent Subject is\nunaffected, archive-strategy §2.5); false unarchives, and when the\nparent Subject is archived also restores it in the same transaction\n(upward cascade). BulkArchive and a PUT / BulkUpdate item carrying\nisArchived: false are the verbs allowed to operate on already-archived\nrows (EC-1 as amended 2026-07-31)."
    BulkArchiveSubjectRequestDto:
      required:
        - ids
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
          description: "Gets or sets the ids (Subject.Id) of the Subjects to transition. Id\nvalidity is checked per item (EC-7) — 0 / negative ids fail that\nitem only."
        isArchived:
          type: boolean
          description: "Gets or sets a value indicating whether the Subjects are archived\n(true, default) or unarchived (false)."
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/Subject/BulkArchive (SB-15450).\nToggleable: isArchived true archives (and cascade-archives each Subject's\nactive SubjectClasses, archive-strategy §2.6), false unarchives the\nSubject only (no class cascade). BulkArchive and a PUT / BulkUpdate\nitem carrying isArchived: false are the verbs allowed to operate on\nalready-archived rows (EC-1 as amended 2026-07-31)."
    BulkArchiveYearRequestDto:
      required:
        - ids
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
          description: "Gets or sets the ids (Club.Id) of the Years to transition. Id\nvalidity is checked per item (EC-7) — 0 / negative ids fail that\nitem only."
        isArchived:
          type: boolean
          description: "Gets or sets a value indicating whether the Years are archived\n(true, default) or unarchived (false)."
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/Year/BulkArchive (SB-15449).\nToggleable: isArchived true archives, false unarchives (BulkArchive and\na PUT / BulkUpdate item carrying isArchived: false are the verbs allowed\nto operate on already-archived rows — EC-1 as amended 2026-07-31).\nBoth halves of the Club + SchoolYearGroup pair transition in lockstep.\nThe Whole school row rejects the transition per-item\n(YEAR_WHOLE_SCHOOL_NOT_EDITABLE)."
    BulkCreateClassItemDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 240
          minLength: 1
          type: string
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkCreateClassRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkCreateClassItemDto'
          description: "Gets or sets the classes to create. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\ninstead of failing the whole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/Class/BulkCreate (SB-15447).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1) — items are not individually org-addressable."
    BulkCreateGroupItemDto:
      required:
        - activityId
        - description
        - leadStaffId
        - name
      type: object
      properties:
        name:
          maxLength: 240
          minLength: 1
          type: string
        description:
          minLength: 1
          type: string
        activityId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        showInSportsPortal:
          type: boolean
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkCreateGroupRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkCreateGroupItemDto'
          description: "Gets or sets the groups to create. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\ninstead of failing the whole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/Group/BulkCreate (SB-15446).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1) — items are not individually org-addressable."
    BulkCreateHouseItemDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 240
          minLength: 1
          type: string
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkCreateHouseRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkCreateHouseItemDto'
          description: "Gets or sets the houses to create. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\ninstead of failing the whole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/House/BulkCreate (SB-15448).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1) — items are not individually org-addressable."
    BulkCreateIbpGroupItemDto:
      required:
        - activityId
        - availableTo
        - description
        - groupName
        - leadStaffId
      type: object
      properties:
        groupName:
          maxLength: 255
          minLength: 1
          type: string
        description:
          minLength: 1
          type: string
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        showInSportsPortal:
          type: boolean
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
          nullable: true
        maximumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        minimumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkCreateIbpGroupRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkCreateIbpGroupItemDto'
          description: "Gets or sets the child groups to create. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\n(cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for POST /api/v1/CcaSignUp/IBP/{id}/groups/BulkCreate\n(SB-15665). The parent signup id in the URL gates the whole request\n(CCASIGNUP_NOT_FOUND, validated before any per-item work — closes\nSB-15244 / SB-15245)."
    BulkCreatePrefGroupItemDto:
      required:
        - activityId
        - availableTo
        - day1
        - day1EndTime
        - day1StartTime
        - description
        - groupName
        - leadStaffId
      type: object
      properties:
        groupName:
          maxLength: 255
          minLength: 1
          type: string
        description:
          minLength: 1
          type: string
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        showInSportsPortal:
          type: boolean
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
          nullable: true
        day1:
          $ref: '#/components/schemas/DayOfWeekType'
        day1StartTime:
          type: string
          format: partial-time
          example: '16:00:00'
        day1EndTime:
          type: string
          format: partial-time
          example: '16:00:00'
        day2:
          $ref: '#/components/schemas/DayOfWeekType'
        day2StartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day2EndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        maximumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        minimumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        cost:
          type: number
          format: double
          nullable: true
        joinRequestsOn:
          type: boolean
          nullable: true
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkCreatePrefGroupRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkCreatePrefGroupItemDto'
          description: "Gets or sets the child groups to create. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\n(cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for POST /api/v1/CcaSignUp/Pref/{id}/groups/BulkCreate\n(SB-15666). The parent signup id in the URL gates the whole request\n(CCASIGNUP_NOT_FOUND, validated before any per-item work — closes\nSB-15244 / SB-15245)."
    BulkCreateSubjectClassItemDto:
      required:
        - leadStaffId
        - schoolYearGroupId
        - subjectId
        - title
      type: object
      properties:
        title:
          maxLength: 250
          minLength: 1
          type: string
        subjectId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        schoolYearGroupId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkCreateSubjectClassRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkCreateSubjectClassItemDto'
          description: "Gets or sets the Subject Classes to create. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\ninstead of failing the whole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/SubjectClass/BulkCreate (SB-15451).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1) — items are not individually org-addressable."
    BulkCreateSubjectItemDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 200
          minLength: 1
          type: string
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkCreateSubjectRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkCreateSubjectItemDto'
          description: "Gets or sets the Subjects to create. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\ninstead of failing the whole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/Subject/BulkCreate (SB-15450).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1) — items are not individually org-addressable."
    BulkCreateYearItemDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 150
          minLength: 1
          type: string
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkCreateYearRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkCreateYearItemDto'
          description: "Gets or sets the Years to create. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\ninstead of failing the whole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for POST /api/v1/Groups/Year/BulkCreate (SB-15449).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1) — items are not individually org-addressable."
    BulkFailedItem:
      type: object
      properties:
        index:
          type: integer
          description: "Gets or sets the zero-based index of the failed item within the\nrequest array, so callers keeping request order can map it back."
          format: int32
        clientReferenceId:
          type: string
          description: "Gets or sets the optional opaque client-supplied reference echoed\nback from the request item. Null when the caller did not supply one."
          nullable: true
        name:
          type: string
          description: "Gets or sets the name of the entity the failed item referred to,\nfor at-a-glance identification in the response."
          nullable: true
        code:
          type: string
          description: "Gets or sets the machine-readable error code (e.g.\n`VALIDATION_FAILED`, `GROUP_IMPORTED_READ_ONLY`) per\ncross-cutting-design.md §5.1."
          nullable: true
        error:
          type: string
          description: Gets or sets the human-readable error message.
          nullable: true
      additionalProperties: false
      description: "A single per-item failure entry in a SchoolsBuddy.PublicAPI.Models.BulkOperationResult`1\nenvelope. Mirrors the structured error body (cross-cutting-design.md §5.3):\na machine-readable SchoolsBuddy.PublicAPI.Models.BulkFailedItem.Code plus a human-readable SchoolsBuddy.PublicAPI.Models.BulkFailedItem.Error."
    BulkUpdateClassItemDto:
      type: object
      properties:
        name:
          maxLength: 240
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        isArchived:
          type: boolean
          nullable: true
        id:
          type: integer
          format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkUpdateClassRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkUpdateClassItemDto'
          description: "Gets or sets the class updates. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations (including missing / 0 / negative id,\nEC-7) surface per item in failedItems[] instead of failing the\nwhole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for PUT /api/v1/Groups/Class/BulkUpdate (SB-15447).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1)."
    BulkUpdateGroupItemDto:
      type: object
      properties:
        name:
          maxLength: 240
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        activityId:
          type: integer
          format: int32
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        showInSportsPortal:
          type: boolean
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        isArchived:
          type: boolean
          nullable: true
        id:
          type: integer
          format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkUpdateGroupRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkUpdateGroupItemDto'
          description: "Gets or sets the group updates. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations (including missing / 0 / negative id,\nEC-7) surface per item in failedItems[] instead of failing the\nwhole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for PUT /api/v1/Groups/Group/BulkUpdate (SB-15446).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1)."
    BulkUpdateHouseItemDto:
      type: object
      properties:
        name:
          maxLength: 240
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        isArchived:
          type: boolean
          nullable: true
        id:
          type: integer
          format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkUpdateHouseRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkUpdateHouseItemDto'
          description: "Gets or sets the house updates. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations (including missing / 0 / negative id,\nEC-7) surface per item in failedItems[] instead of failing the\nwhole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for PUT /api/v1/Groups/House/BulkUpdate (SB-15448).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1)."
    BulkUpdateIbpGroupItemDto:
      type: object
      properties:
        groupName:
          maxLength: 255
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          type: integer
          format: int32
          nullable: true
        showInSportsPortal:
          type: boolean
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
          nullable: true
        maximumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        minimumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
        id:
          type: integer
          format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkUpdateIbpGroupRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkUpdateIbpGroupItemDto'
          description: "Gets or sets the child groups to update. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\n(cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for PUT /api/v1/CcaSignUp/IBP/{id}/groups/BulkUpdate\n(SB-15665). The parent signup id in the URL gates the whole request\n(CCASIGNUP_NOT_FOUND, validated before any per-item work); each item\ncarries its target group Id (EC-7)."
    BulkUpdatePrefGroupItemDto:
      type: object
      properties:
        groupName:
          maxLength: 255
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          type: integer
          format: int32
          nullable: true
        showInSportsPortal:
          type: boolean
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
          nullable: true
        day1:
          $ref: '#/components/schemas/DayOfWeekType'
        day1StartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day1EndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day2:
          $ref: '#/components/schemas/DayOfWeekType'
        day2StartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day2EndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        maximumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        minimumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        cost:
          type: number
          format: double
          nullable: true
        joinRequestsOn:
          type: boolean
          nullable: true
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
        id:
          type: integer
          format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkUpdatePrefGroupRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkUpdatePrefGroupItemDto'
          description: "Gets or sets the child groups to update. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations surface per item in failedItems[]\n(cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for PUT /api/v1/CcaSignUp/Pref/{id}/groups/BulkUpdate\n(SB-15666). The parent signup id in the URL gates the whole request\n(CCASIGNUP_NOT_FOUND, validated before any per-item work); each item\ncarries its target group Id (EC-7)."
    BulkUpdateSubjectClassItemDto:
      type: object
      properties:
        title:
          maxLength: 250
          type: string
          nullable: true
        subjectId:
          type: integer
          format: int32
          nullable: true
        schoolYearGroupId:
          type: integer
          format: int32
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        isArchived:
          type: boolean
          nullable: true
        id:
          type: integer
          format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkUpdateSubjectClassRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkUpdateSubjectClassItemDto'
          description: "Gets or sets the Subject Class updates. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations (including missing / 0 / negative id, EC-7)\nsurface per item in failedItems[] instead of failing the whole\nrequest (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for PUT /api/v1/Groups/SubjectClass/BulkUpdate (SB-15451).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1)."
    BulkUpdateSubjectItemDto:
      type: object
      properties:
        name:
          maxLength: 200
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
        id:
          type: integer
          format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkUpdateSubjectRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkUpdateSubjectItemDto'
          description: "Gets or sets the Subject updates. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations (including missing / 0 / negative id, EC-7)\nsurface per item in failedItems[] instead of failing the whole\nrequest (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for PUT /api/v1/Groups/Subject/BulkUpdate (SB-15450).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1)."
    BulkUpdateYearItemDto:
      type: object
      properties:
        name:
          maxLength: 150
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
        id:
          type: integer
          format: int32
          nullable: true
        clientReferenceId:
          maxLength: 100
          type: string
          nullable: true
      additionalProperties: false
    BulkUpdateYearRequestDto:
      type: object
      properties:
        organisationId:
          type: integer
          description: "Gets or sets the organisation the batch operates on. Optional\nwhen the calling client has access to a single organisation;\nrequired for multi-org clients."
          format: int32
          nullable: true
        items:
          type: array
          items:
            $ref: '#/components/schemas/BulkUpdateYearItemDto'
          description: "Gets or sets the Year updates. Each item is processed\nindependently; one failure does not roll back the others.\nItem-level validation deliberately bypasses automatic model\nvalidation — violations (including missing / 0 / negative id,\nEC-7, and the Whole school guard) surface per item in failedItems[]\ninstead of failing the whole request (cross-cutting §6.1)."
          nullable: true
      additionalProperties: false
      description: "Request body for PUT /api/v1/Groups/Year/BulkUpdate (SB-15449).\nThe envelope-level organisationId scopes every item in the batch\n(cross-cutting §3.8.1)."
    CcaCostTypeEnum:
      enum:
        - FreeOfCharge
        - PerTermOrSeason
        - PerSession
        - OneOff
      type: string
    CcaGroupAvailabilityDto:
      required:
        - groupId
        - requirementGroupId
        - requirementGroupType
      type: object
      properties:
        groupId:
          type: integer
          format: int32
        requirementGroupId:
          $ref: '#/components/schemas/RequirementType'
        requirementGroupType:
          $ref: '#/components/schemas/RequirementGroupType'
        name:
          type: string
          nullable: true
      additionalProperties: false
    CcaGroupReferenceDto:
      required:
        - type
      type: object
      properties:
        id:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
        type:
          $ref: '#/components/schemas/CcaGroupReferenceType'
      additionalProperties: false
    CcaGroupReferenceType:
      enum:
        - Group
        - Class
        - House
        - Year
        - SubjectClass
      type: string
    CcaSignupResponsibility:
      enum:
        - None
        - PupilsOrParents
        - ParentsOnly
        - PupilsOnly
      type: string
    ClassResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        name:
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        isArchived:
          type: boolean
        createdAtUtc:
          type: string
          format: date-time
        updatedAtUtc:
          type: string
          format: date-time
        thirdPartyId:
          type: string
          nullable: true
        isImported:
          type: boolean
      additionalProperties: false
    ClassResponseDtoListPagedClassFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/ClassResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    ClassStudentsOperationResultDto:
      type: object
      properties:
        studentsProcessed:
          type: integer
          format: int32
        totalRequested:
          type: integer
          format: int32
      additionalProperties: false
    ClassStudentsRequestDto:
      required:
        - studentIds
      type: object
      properties:
        studentIds:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
      additionalProperties: false
    ContactBulkArchiveRequestDto:
      required:
        - ids
      type: object
      properties:
        organisationId:
          type: integer
          format: int32
          nullable: true
        archive:
          type: boolean
        ids:
          maxItems: 1000
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
      additionalProperties: false
    ContactCreateRelatedPersonRequestDto:
      required:
        - id
      type: object
      properties:
        id:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
      additionalProperties: false
    ContactCreateRequestDto:
      required:
        - emailAddress
        - firstName
        - lastName
        - relatedPeople
      type: object
      properties:
        contactId:
          type: string
          nullable: true
        title:
          type: string
          nullable: true
        mobilePhoneNumber:
          type: string
          nullable: true
        phoneNumber:
          type: string
          nullable: true
        streetAddress:
          type: string
          nullable: true
        streetAddress2:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        state:
          type: string
          nullable: true
        country:
          type: string
          nullable: true
        postalCode:
          type: string
          nullable: true
        relatedPeople:
          maxItems: 10
          minItems: 1
          type: array
          items:
            $ref: '#/components/schemas/ContactCreateRelatedPersonRequestDto'
        lastName:
          minLength: 1
          type: string
        firstName:
          minLength: 1
          type: string
        emailAddress:
          minLength: 1
          type: string
          format: email
      additionalProperties: false
    ContactDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        contactId:
          type: string
          nullable: true
        title:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        firstName:
          type: string
          nullable: true
        emailAddress:
          type: string
          nullable: true
        mobilePhoneNumber:
          type: string
          nullable: true
        phoneNumber:
          type: string
          nullable: true
        streetAddress:
          type: string
          nullable: true
        streetAddress2:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        state:
          type: string
          nullable: true
        country:
          type: string
          nullable: true
        postalCode:
          type: string
          nullable: true
        relatedPeople:
          type: array
          items:
            $ref: '#/components/schemas/ContactRelatedPersonDto'
          nullable: true
        createdAtUtc:
          type: string
          format: date-time
        updatedAtUtc:
          type: string
          format: date-time
          nullable: true
        isArchived:
          type: boolean
        updatable:
          type: boolean
      additionalProperties: false
    ContactDtoListPagedContactSearchResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/ContactDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    ContactRelatedPersonDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        firstName:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        isArchived:
          type: boolean
        vban:
          type: string
          nullable: true
        isParent:
          type: boolean
        isBillingContact:
          type: boolean
        isReportContact:
          type: boolean
        isCommunicationContact:
          type: boolean
        isEmergencyContact:
          type: boolean
      additionalProperties: false
    ContactTypeEnum:
      enum:
        - IsParent
        - IsEmergencyContact
        - IsBillingContact
        - IsReportContact
        - IsCommunicationContact
      type: string
    ContactUpdateRequestDto:
      type: object
      properties:
        contactId:
          type: string
          nullable: true
        title:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        firstName:
          type: string
          nullable: true
        emailAddress:
          type: string
          format: email
          nullable: true
        mobilePhoneNumber:
          type: string
          nullable: true
        phoneNumber:
          type: string
          nullable: true
        streetAddress:
          type: string
          nullable: true
        streetAddress2:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        state:
          type: string
          nullable: true
        country:
          type: string
          nullable: true
        postalCode:
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    CreateClassRequestDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 240
          minLength: 1
          type: string
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
      additionalProperties: false
    CreateGroupRequestDto:
      required:
        - activityId
        - description
        - leadStaffId
        - name
      type: object
      properties:
        name:
          maxLength: 240
          minLength: 1
          type: string
        description:
          minLength: 1
          type: string
        activityId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        showInSportsPortal:
          type: boolean
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
      additionalProperties: false
    CreateHouseRequestDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 240
          minLength: 1
          type: string
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
      additionalProperties: false
    CreateIbpGroupRequestDto:
      required:
        - activityId
        - availableTo
        - description
        - groupName
        - leadStaffId
      type: object
      properties:
        groupName:
          maxLength: 255
          minLength: 1
          type: string
        description:
          minLength: 1
          type: string
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        showInSportsPortal:
          type: boolean
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
          nullable: true
        maximumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        minimumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
      additionalProperties: false
    CreateIbpRequestDto:
      required:
        - activitiesEndDate
        - activitiesStartDate
        - description
        - name
        - signupCloses
        - signupOpens
      type: object
      properties:
        name:
          maxLength: 255
          minLength: 1
          type: string
        description:
          minLength: 1
          type: string
        activitiesStartDate:
          type: string
          format: date
        activitiesEndDate:
          type: string
          format: date
        activitiesDefaultStartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        activitiesDefaultEndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        responsibilityForConfirmation:
          $ref: '#/components/schemas/CcaSignupResponsibility'
        signupOpens:
          type: string
          format: date-time
        signupCloses:
          type: string
          format: date-time
        termsAndConditions:
          type: string
          nullable: true
        additionalInfoUrl:
          type: string
          nullable: true
      additionalProperties: false
    CreateLocationRequestDto:
      required:
        - locationName
      type: object
      properties:
        organisationId:
          type: integer
          format: int32
          nullable: true
        locationName:
          maxLength: 100
          minLength: 1
          type: string
        locationDescription:
          type: string
          nullable: true
        isHome:
          type: boolean
        locationTypeId:
          type: integer
          format: int32
        city:
          maxLength: 100
          type: string
          nullable: true
        state:
          maxLength: 100
          type: string
          nullable: true
        postCode:
          maxLength: 20
          type: string
          nullable: true
        telephone:
          maxLength: 50
          type: string
          nullable: true
        streetAddress:
          maxLength: 200
          type: string
          nullable: true
      additionalProperties: false
    CreatePrefGroupRequestDto:
      required:
        - activityId
        - availableTo
        - day1
        - day1EndTime
        - day1StartTime
        - description
        - groupName
        - leadStaffId
      type: object
      properties:
        groupName:
          maxLength: 255
          minLength: 1
          type: string
        description:
          minLength: 1
          type: string
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        showInSportsPortal:
          type: boolean
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
          nullable: true
        day1:
          $ref: '#/components/schemas/DayOfWeekType'
        day1StartTime:
          type: string
          format: partial-time
          example: '16:00:00'
        day1EndTime:
          type: string
          format: partial-time
          example: '16:00:00'
        day2:
          $ref: '#/components/schemas/DayOfWeekType'
        day2StartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day2EndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        maximumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        minimumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        cost:
          type: number
          format: double
          nullable: true
        joinRequestsOn:
          type: boolean
          nullable: true
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
      additionalProperties: false
    CreatePrefRequestDto:
      required:
        - activitiesEndDate
        - activitiesStartDate
        - description
        - eventCategoryId
        - name
        - signupCloses
        - signupOpens
      type: object
      properties:
        name:
          maxLength: 255
          minLength: 1
          type: string
        description:
          minLength: 1
          type: string
        preferenceSelectionScope:
          $ref: '#/components/schemas/PreferenceSelectionScopeEnum'
        eventCategoryId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        activitiesStartDate:
          type: string
          format: date
        activitiesEndDate:
          type: string
          format: date
        activitiesDefaultStartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        activitiesDefaultEndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        responsibilityForConfirmation:
          $ref: '#/components/schemas/CcaSignupResponsibility'
        signupOpens:
          type: string
          format: date-time
        signupCloses:
          type: string
          format: date-time
        termsAndConditions:
          type: string
          nullable: true
        additionalInfoUrl:
          type: string
          nullable: true
      additionalProperties: false
    CreateSubjectClassRequestDto:
      required:
        - leadStaffId
        - schoolYearGroupId
        - subjectId
        - title
      type: object
      properties:
        title:
          maxLength: 250
          minLength: 1
          type: string
        subjectId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        schoolYearGroupId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
        leadStaffId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
      additionalProperties: false
    CreateSubjectRequestDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 200
          minLength: 1
          type: string
      additionalProperties: false
    CreateYearRequestDto:
      required:
        - name
      type: object
      properties:
        name:
          maxLength: 150
          minLength: 1
          type: string
      additionalProperties: false
    DayOfWeekType:
      enum:
        - Monday
        - Tuesday
        - Wednesday
        - Thursday
        - Friday
        - Saturday
        - Sunday
      type: string
    ErrorResponse:
      type: object
      properties:
        code:
          type: string
          description: "Gets or sets the machine-readable error code (e.g.\n`VALIDATION_FAILED`, `RESOURCE_NOT_FOUND`,\n`INTERNAL_ERROR`) per cross-cutting-design.md §5.1."
          nullable: true
        error:
          type: string
          description: Gets or sets the human-readable error message.
          nullable: true
      additionalProperties: false
      description: "Structured body for 4xx / 5xx responses on the new Public API surface:\na machine-readable SchoolsBuddy.PublicAPI.Models.ErrorResponse.Code plus a human-readable\nSchoolsBuddy.PublicAPI.Models.ErrorResponse.Error. See cross-cutting-design.md §5.3. This is additive —\nexisting endpoints continue returning their legacy plain-string /\nModelState shapes until migrated by their per-controller ticket."
    EventAttendanceDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        calendarEventId:
          type: integer
          format: int32
        registerStatus:
          $ref: '#/components/schemas/AttendeeRegisterStateEnum'
        firstName:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        registerUpdatedAt:
          type: string
          format: date-time
          nullable: true
        registerUpdatedBy:
          type: integer
          format: int32
          nullable: true
        registerUpdatedByName:
          type: string
          nullable: true
        attendanceNote:
          type: string
          nullable: true
      additionalProperties: false
    EventAttendanceUpdateDto:
      required:
        - id
        - registerStatus
      type: object
      properties:
        id:
          type: integer
          format: int32
        registerStatus:
          $ref: '#/components/schemas/AttendeeRegisterStateEnum'
        attendanceNote:
          type: string
          nullable: true
      additionalProperties: false
    EventCategoryResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        name:
          type: string
          nullable: true
        summaryDescription:
          type: string
          nullable: true
        colour:
          type: string
          nullable: true
        displayOrder:
          type: integer
          format: int32
        isCca:
          type: boolean
      additionalProperties: false
    EventCategoryResponseDtoListPagedEventCategoryFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/EventCategoryResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    EventParticipantDto:
      required:
        - attendeeStatus
        - misId
        - registerStatus
      type: object
      properties:
        misId:
          minLength: 1
          type: string
        attendanceNote:
          type: string
          nullable: true
        attendeeStatus:
          $ref: '#/components/schemas/ExternalAttendeeStatus'
        registerStatus:
          $ref: '#/components/schemas/ExternalRegisterStatus'
      additionalProperties: false
    EventRequestDto:
      required:
        - endDateTime
        - id
        - name
        - organisationId
        - source
        - startDateTime
      type: object
      properties:
        organisationId:
          type: integer
          format: int32
        id:
          minLength: 1
          type: string
        source:
          $ref: '#/components/schemas/ExternalSource'
        name:
          minLength: 1
          type: string
        startDateTime:
          type: string
          format: date-time
        endDateTime:
          type: string
          format: date-time
        participants:
          type: array
          items:
            $ref: '#/components/schemas/EventParticipantDto'
          nullable: true
      additionalProperties: false
    EventStudentAttendanceUpdateDto:
      required:
        - attendanceStatus
        - endDateTime
        - startDateTime
      type: object
      properties:
        id:
          type: integer
          format: int32
          nullable: true
        studentId:
          type: string
          nullable: true
        startDateTime:
          type: string
          format: date-time
        endDateTime:
          type: string
          format: date-time
        attendanceStatus:
          $ref: '#/components/schemas/AttendeeStatusEnum'
        attendanceNote:
          type: string
          nullable: true
      additionalProperties: false
    ExternalAttendeeStatus:
      enum:
        - NotExpected
        - Expected
      type: string
    ExternalRegisterStatus:
      enum:
        - Unset
        - Present
        - Absent
      type: string
    ExternalSource:
      enum:
        - Vectare
      type: string
    GenderTypeEnum:
      enum:
        - Female
        - Male
        - Unspecified
      type: string
    GroupEventResponseDto:
      type: object
      properties:
        eventId:
          type: integer
          format: int32
        eventName:
          type: string
          nullable: true
        eventStartTime:
          type: string
          format: date-time
        eventEndTime:
          type: string
          format: date-time
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        locationId:
          type: integer
          format: int32
          nullable: true
        numberOfPlaces:
          type: integer
          format: int32
          nullable: true
        eventTypeId:
          type: integer
          format: int32
          nullable: true
        eventType:
          type: string
          nullable: true
        isCancelled:
          type: boolean
        isDeleted:
          type: boolean
        updatedAt:
          type: string
          format: date-time
          nullable: true
        timeZone:
          type: string
          nullable: true
      additionalProperties: false
    GroupExtendedDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        groupId:
          type: integer
          format: int32
          nullable: true
        organisationId:
          type: integer
          format: int32
        name:
          type: string
          nullable: true
        groupCode:
          type: string
          nullable: true
        billingCode:
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
        leadStaffName:
          type: string
          nullable: true
        signupId:
          type: integer
          format: int32
          nullable: true
        signupName:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
          nullable: true
        updatedAt:
          type: string
          format: date-time
          nullable: true
        isArchived:
          type: boolean
        taxCode:
          type: string
          nullable: true
        shortName:
          type: string
          nullable: true
        dayOfWeek:
          $ref: '#/components/schemas/DayOfWeekType'
        ccaStartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        ccaEndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        size:
          type: integer
          format: int32
          nullable: true
        minSize:
          type: integer
          format: int32
          nullable: true
        ccaPrice:
          type: string
          nullable: true
        allowJoinRequests:
          type: boolean
          nullable: true
        linkedParentTeamId:
          type: integer
          format: int32
          nullable: true
        availability:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupAvailabilityDto'
          nullable: true
        teamTypeId:
          type: integer
          format: int32
          nullable: true
        description:
          type: string
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        defaultLocation:
          type: integer
          format: int32
          nullable: true
        activityId:
          type: integer
          format: int32
          nullable: true
        showInSportsPortal:
          type: boolean
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        genderName:
          type: string
          nullable: true
        defaultLocationName:
          type: string
          nullable: true
        activityName:
          type: string
          nullable: true
      additionalProperties: false
    GroupResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        activityId:
          type: integer
          format: int32
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        groupCode:
          type: string
          nullable: true
        billingCode:
          type: string
          nullable: true
        shortName:
          type: string
          nullable: true
        taxCode:
          type: string
          nullable: true
        showInSportsPortal:
          type: boolean
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        locationId:
          type: integer
          format: int32
          nullable: true
        isArchived:
          type: boolean
        createdAtUtc:
          type: string
          format: date-time
        updatedAtUtc:
          type: string
          format: date-time
        thirdPartyId:
          type: string
          nullable: true
        isImported:
          type: boolean
      additionalProperties: false
    GroupResponseDtoListPagedGroupFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/GroupResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    GroupStudentsOperationResultDto:
      type: object
      properties:
        studentsProcessed:
          type: integer
          format: int32
        totalRequested:
          type: integer
          format: int32
      additionalProperties: false
    GroupStudentsRequestDto:
      required:
        - studentIds
      type: object
      properties:
        studentIds:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
      additionalProperties: false
    HouseResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        name:
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        isArchived:
          type: boolean
        createdAtUtc:
          type: string
          format: date-time
        updatedAtUtc:
          type: string
          format: date-time
        thirdPartyId:
          type: string
          nullable: true
        isImported:
          type: boolean
      additionalProperties: false
    HouseResponseDtoListPagedHouseFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/HouseResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    HouseStudentsOperationResultDto:
      type: object
      properties:
        studentsProcessed:
          type: integer
          format: int32
        totalRequested:
          type: integer
          format: int32
      additionalProperties: false
    HouseStudentsRequestDto:
      required:
        - studentIds
      type: object
      properties:
        studentIds:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
      additionalProperties: false
    IbpGroupResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        groupName:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        groupCode:
          type: string
          nullable: true
        billingCode:
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          type: integer
          format: int32
          nullable: true
        showInSportsPortal:
          type: boolean
        locationId:
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
        maximumPlaces:
          type: integer
          format: int32
        minimumPlaces:
          type: integer
          format: int32
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          type: string
          nullable: true
        shortName:
          type: string
          nullable: true
        isArchived:
          type: boolean
        createdAtUtc:
          type: string
          format: date-time
          nullable: true
        updatedAtUtc:
          type: string
          format: date-time
      additionalProperties: false
    IbpGroupResponseDtoListPagedIbpGroupFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/IbpGroupResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    IbpResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        containerTypeId:
          type: integer
          format: int32
        preferenceTypeId:
          type: integer
          format: int32
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        activitiesStartDate:
          type: string
          format: date
        activitiesEndDate:
          type: string
          format: date
        activitiesDefaultStartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        activitiesDefaultEndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        responsibilityForConfirmation:
          $ref: '#/components/schemas/CcaSignupResponsibility'
        signupOpens:
          type: string
          format: date-time
          nullable: true
        signupCloses:
          type: string
          format: date-time
          nullable: true
        useOrganisationBlockDates:
          type: boolean
          nullable: true
        termsAndConditions:
          type: string
          nullable: true
        additionalInfoUrl:
          type: string
          nullable: true
        isArchived:
          type: boolean
        timeZone:
          type: string
          nullable: true
        createdAtUtc:
          type: string
          format: date-time
          nullable: true
        updatedAtUtc:
          type: string
          format: date-time
          nullable: true
      additionalProperties: false
    IbpResponseDtoListPagedIbpFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/IbpResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    Int32BulkOperationResult:
      type: object
      properties:
        successfulIds:
          type: array
          items:
            type: integer
            format: int32
          description: "Gets or sets the ids of the items that were processed successfully.\nOn BulkCreate these are the newly-created ids."
          nullable: true
        failedItems:
          type: array
          items:
            $ref: '#/components/schemas/BulkFailedItem'
          description: "Gets or sets the per-item failures, each carrying its request index,\noptional client reference, name, machine-readable code, and message."
          nullable: true
        totalRequested:
          type: integer
          description: "Gets or sets the total number of items in the request. Set by the\ncaller (it is not derivable from the success/failure lists alone —\nitems rejected before per-item processing may appear in neither)."
          format: int32
        totalSuccessful:
          type: integer
          description: Gets the number of items processed successfully (computed).
          format: int32
          readOnly: true
        totalFailed:
          type: integer
          description: Gets the number of items that failed (computed).
          format: int32
          readOnly: true
      additionalProperties: false
      description: "Standard envelope returned by every Public API bulk endpoint\n(BulkCreate / BulkUpdate / BulkArchive). Each item in the request is\nprocessed independently — one item failing does not roll back the\nothers — and the envelope reports per-item outcome. See\ncross-cutting-design.md §4."
    IsamsConfigPatchRequestDto:
      type: object
      properties:
        importEnabled:
          type: boolean
          nullable: true
        url:
          type: string
          nullable: true
        parentContactTypes:
          type: array
          items:
            type: string
          nullable: true
        importFlags:
          $ref: '#/components/schemas/IsamsImportFlagsPatchDto'
      additionalProperties: false
    IsamsConfigResponseDto:
      type: object
      properties:
        orgId:
          type: string
          nullable: true
        importEnabled:
          type: boolean
        url:
          type: string
          nullable: true
        parentContactTypes:
          type: array
          items:
            type: string
          nullable: true
        importFlags:
          $ref: '#/components/schemas/IsamsImportFlagsDto'
      additionalProperties: false
    IsamsImportFlagsDto:
      type: object
      properties:
        allMergesCorrespondenceOnly:
          type: boolean
        billingOrAllMergesOnly:
          type: boolean
        ignoreForms:
          type: boolean
        ignoreHouses:
          type: boolean
        ignoreSubjects:
          type: boolean
        ignoreYears:
          type: boolean
        parentalResponsibilityOnly:
          type: boolean
      additionalProperties: false
    IsamsImportFlagsPatchDto:
      type: object
      properties:
        allMergesCorrespondenceOnly:
          type: boolean
          nullable: true
        billingOrAllMergesOnly:
          type: boolean
          nullable: true
        ignoreForms:
          type: boolean
          nullable: true
        ignoreHouses:
          type: boolean
          nullable: true
        ignoreSubjects:
          type: boolean
          nullable: true
        ignoreYears:
          type: boolean
          nullable: true
        parentalResponsibilityOnly:
          type: boolean
          nullable: true
      additionalProperties: false
    LocationDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        locationName:
          type: string
          nullable: true
        locationDescription:
          type: string
          nullable: true
        isHome:
          type: boolean
        locationType:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        state:
          type: string
          nullable: true
        streetAddress:
          type: string
          nullable: true
        postCode:
          type: string
          nullable: true
        telephone:
          type: string
          nullable: true
        isDeleted:
          type: boolean
        updatedAtUtc:
          type: string
          format: date-time
          nullable: true
      additionalProperties: false
    LocationDtoListPagedLocationFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/LocationDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    PrefGroupResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        groupName:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        groupCode:
          type: string
          nullable: true
        billingCode:
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          type: integer
          format: int32
          nullable: true
        showInSportsPortal:
          type: boolean
        locationId:
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
        day1:
          $ref: '#/components/schemas/DayOfWeekType'
        day1StartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day1EndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day2:
          $ref: '#/components/schemas/DayOfWeekType'
        day2StartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day2EndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        maximumPlaces:
          type: integer
          format: int32
        minimumPlaces:
          type: integer
          format: int32
        cost:
          type: number
          format: double
        costType:
          $ref: '#/components/schemas/CcaCostTypeEnum'
        joinRequestsOn:
          type: boolean
          nullable: true
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          type: string
          nullable: true
        shortName:
          type: string
          nullable: true
        isArchived:
          type: boolean
        timeZone:
          type: string
          nullable: true
        createdAtUtc:
          type: string
          format: date-time
          nullable: true
        updatedAtUtc:
          type: string
          format: date-time
      additionalProperties: false
    PrefGroupResponseDtoListPagedPrefGroupFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/PrefGroupResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    PrefResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        containerTypeId:
          type: integer
          format: int32
        preferenceTypeId:
          type: integer
          format: int32
        preferenceSelectionScope:
          $ref: '#/components/schemas/PreferenceSelectionScopeEnum'
        eventCategoryId:
          type: integer
          format: int32
          nullable: true
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        activitiesStartDate:
          type: string
          format: date
        activitiesEndDate:
          type: string
          format: date
        activitiesDefaultStartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        activitiesDefaultEndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        responsibilityForConfirmation:
          $ref: '#/components/schemas/CcaSignupResponsibility'
        signupOpens:
          type: string
          format: date-time
          nullable: true
        signupCloses:
          type: string
          format: date-time
          nullable: true
        useOrganisationBlockDates:
          type: boolean
          nullable: true
        termsAndConditions:
          type: string
          nullable: true
        additionalInfoUrl:
          type: string
          nullable: true
        isArchived:
          type: boolean
        timeZone:
          type: string
          nullable: true
        createdAtUtc:
          type: string
          format: date-time
          nullable: true
        updatedAtUtc:
          type: string
          format: date-time
          nullable: true
      additionalProperties: false
    PrefResponseDtoListPagedPrefFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/PrefResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    PreferenceSelectionScopeEnum:
      enum:
        - Daily
        - Weekly
      type: string
    ProblemDetails:
      type: object
      properties:
        type:
          type: string
          nullable: true
        title:
          type: string
          nullable: true
        status:
          type: integer
          format: int32
          nullable: true
        detail:
          type: string
          nullable: true
        instance:
          type: string
          nullable: true
      additionalProperties: { }
    PublicApiOrganisationRole:
      enum:
        - Staff
        - ExternalCoach
        - BusMonitor
      type: string
    PublicBusStopResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        stopName:
          type: string
          nullable: true
        streetAddress:
          type: string
          nullable: true
        streetAddress2:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        county:
          type: string
          nullable: true
        postcode:
          type: string
          nullable: true
        isActive:
          type: boolean
        isDeleted:
          type: boolean
        updatedAt:
          type: string
          format: date-time
          nullable: true
      additionalProperties: false
    PublicEventResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        isSeries:
          type: boolean
        parentEventId:
          type: integer
          format: int32
          nullable: true
        allowJoiningPartWayThrough:
          type: boolean
        eventName:
          type: string
          nullable: true
        opponent:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        vitalInformation:
          type: string
          nullable: true
        groupId:
          type: integer
          format: int32
        groupName:
          type: string
          nullable: true
        yearId:
          type: integer
          format: int32
          nullable: true
        yearName:
          type: string
          nullable: true
        ccaSignUpId:
          type: integer
          format: int32
          nullable: true
        eventTypeId:
          type: integer
          format: int32
          nullable: true
        eventType:
          type: string
          nullable: true
        eventStartTime:
          type: string
          format: date-time
        eventEndTime:
          type: string
          format: date-time
        leadStaffMember:
          type: string
          nullable: true
        cost:
          type: number
          format: double
        percentageToPayDeposit:
          type: number
          format: double
          nullable: true
        alwaysChargeFullPrice:
          type: boolean
        includesTax:
          type: boolean
        paymentDueDate:
          type: string
          format: date
          nullable: true
        location:
          type: string
          nullable: true
        meetingLocation:
          type: string
          nullable: true
        meetingTime:
          type: string
          format: date-time
          nullable: true
        pickupLocation:
          type: string
          nullable: true
        pickupTime:
          type: string
          format: date-time
          nullable: true
        numberOfPlaces:
          type: integer
          format: int32
          nullable: true
        consentRequired:
          type: boolean
        consentDueDate:
          type: string
          format: date-time
          nullable: true
        consentMessage:
          type: string
          nullable: true
        termsAndConditions:
          type: string
          nullable: true
        orgId:
          type: integer
          format: int32
        isBlocked:
          type: boolean
        isCancelled:
          type: boolean
        isArchived:
          type: boolean
        updatedAt:
          type: string
          format: date-time
          nullable: true
        timeZone:
          type: string
          nullable: true
        attendees:
          type: array
          items:
            $ref: '#/components/schemas/EventAttendanceDto'
          nullable: true
      additionalProperties: false
    PublicEventResponseDtoListPagedPublicEventsSearchResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/PublicEventResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    RequirementGroupType:
      enum:
        - Group
        - Club
        - SubjectClass
      type: string
    RequirementType:
      enum:
        - AvailableTo
        - PreRequisite
        - NotAvailableTo
      type: string
    StaffBulkArchiveRequestDto:
      required:
        - ids
      type: object
      properties:
        archive:
          type: boolean
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
      additionalProperties: false
    StaffBulkUpdateOnlineMeetingIdRequestDto:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/StaffOnlineMeetingIdItemDto'
          nullable: true
      additionalProperties: false
    StaffCoreDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
          nullable: true
        organisationId:
          type: integer
          format: int32
          nullable: true
        staffId:
          type: string
          nullable: true
        title:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        firstName:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        role:
          $ref: '#/components/schemas/PublicApiOrganisationRole'
        onlineMeetingId:
          type: string
          nullable: true
        isArchived:
          type: boolean
        mobilePhone:
          type: string
          nullable: true
        phoneNumber:
          type: string
          nullable: true
        createdAtUtc:
          type: string
          format: date-time
          nullable: true
        updatedAtUtc:
          type: string
          format: date-time
          nullable: true
        updatable:
          type: boolean
      additionalProperties: false
    StaffCreateRequestDto:
      type: object
      properties:
        staffId:
          maxLength: 50
          type: string
          nullable: true
        title:
          maxLength: 10
          type: string
          nullable: true
        lastName:
          maxLength: 50
          type: string
          nullable: true
        firstName:
          maxLength: 50
          type: string
          nullable: true
        email:
          maxLength: 250
          type: string
          nullable: true
        onlineMeetingId:
          maxLength: 250
          type: string
          nullable: true
        mobilePhone:
          maxLength: 250
          type: string
          nullable: true
        phoneNumber:
          maxLength: 250
          type: string
          nullable: true
        updateable:
          type: boolean
        role:
          $ref: '#/components/schemas/PublicApiOrganisationRole'
      additionalProperties: false
    StaffDataDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
          nullable: true
        staffId:
          type: string
          nullable: true
        firstName:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        role:
          $ref: '#/components/schemas/PublicApiOrganisationRole'
        createdAtUtc:
          type: string
          format: date-time
        updatedAtUtc:
          type: string
          format: date-time
        isArchived:
          type: boolean
        updatable:
          type: boolean
      additionalProperties: false
    StaffDataDtoListPagedStaffFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/StaffDataDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    StaffOnlineMeetingIdItemDto:
      required:
        - id
        - onlineMeetingId
      type: object
      properties:
        id:
          type: integer
          format: int32
        onlineMeetingId:
          maxLength: 250
          minLength: 1
          type: string
      additionalProperties: false
    StaffUpdateRequestDto:
      type: object
      properties:
        staffId:
          maxLength: 50
          type: string
          nullable: true
        title:
          maxLength: 10
          type: string
          nullable: true
        lastName:
          maxLength: 50
          type: string
          nullable: true
        firstName:
          maxLength: 50
          type: string
          nullable: true
        email:
          maxLength: 250
          type: string
          nullable: true
        onlineMeetingId:
          maxLength: 250
          type: string
          nullable: true
        mobilePhone:
          maxLength: 250
          type: string
          nullable: true
        phoneNumber:
          maxLength: 250
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    StringStringKeyValuePair:
      type: object
      properties:
        key:
          type: string
          nullable: true
        value:
          type: string
          nullable: true
      additionalProperties: false
    StudentBulkArchiveRequestDto:
      required:
        - ids
      type: object
      properties:
        archive:
          type: boolean
        ids:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
      additionalProperties: false
    StudentCoreDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
          nullable: true
        studentId:
          type: string
          nullable: true
        studentDisplayId:
          type: string
          nullable: true
        qrCode:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        firstName:
          type: string
          nullable: true
        middleName:
          type: string
          nullable: true
        otherName:
          type: string
          nullable: true
        gender:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        dateOfBirth:
          type: string
          format: date
          nullable: true
        house:
          type: string
          nullable: true
        grade:
          type: string
          nullable: true
        homeroomClass:
          type: string
          nullable: true
        homeroomAdvisorId:
          type: integer
          format: int32
          nullable: true
        homeroomAdvisor:
          type: string
          nullable: true
        sen:
          type: boolean
          nullable: true
        relatedPeople:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        isArchived:
          type: boolean
        createdAt:
          type: string
          format: date-time
          nullable: true
        updatedAt:
          type: string
          format: date-time
          nullable: true
        updatable:
          type: boolean
      additionalProperties: false
    StudentCreateRequestDto:
      required:
        - firstName
        - gender
        - grade
        - lastName
      type: object
      properties:
        studentId:
          maxLength: 50
          type: string
          nullable: true
        studentDisplayId:
          maxLength: 200
          type: string
          nullable: true
        qrCode:
          maxLength: 50
          type: string
          nullable: true
        lastName:
          maxLength: 50
          minLength: 1
          type: string
        firstName:
          maxLength: 50
          minLength: 1
          type: string
        middleName:
          maxLength: 100
          type: string
          nullable: true
        gender:
          $ref: '#/components/schemas/GenderTypeEnum'
        otherName:
          maxLength: 100
          type: string
          nullable: true
        email:
          maxLength: 256
          type: string
          format: email
          nullable: true
        dateOfBirth:
          type: string
          format: date
          nullable: true
        house:
          maxLength: 100
          type: string
          nullable: true
        grade:
          maxLength: 100
          minLength: 1
          type: string
        homeroomClass:
          maxLength: 100
          type: string
          nullable: true
        sen:
          type: boolean
          nullable: true
      additionalProperties: false
    StudentHealthResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        description:
          type: string
          nullable: true
        notes:
          type: string
          nullable: true
        updatedAt:
          type: string
          format: date-time
          nullable: true
      additionalProperties: false
    StudentHealthUpdateRequestDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        description:
          type: string
          nullable: true
        notes:
          type: string
          nullable: true
      additionalProperties: false
    StudentPublicDataDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        studentId:
          type: string
          nullable: true
        studentDisplayId:
          type: string
          nullable: true
        lastName:
          type: string
          nullable: true
        firstName:
          type: string
          nullable: true
        middleName:
          type: string
          nullable: true
        otherName:
          type: string
          nullable: true
        dateOfBirth:
          type: string
          format: date
          nullable: true
        email:
          type: string
          nullable: true
        gender:
          type: string
          nullable: true
        house:
          type: string
          nullable: true
        grade:
          type: string
          nullable: true
        homeroomClass:
          type: string
          nullable: true
        homeroomAdvisorId:
          type: integer
          format: int32
          nullable: true
        homeroomAdvisor:
          type: string
          nullable: true
        relatedPeople:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        createdAt:
          type: string
          format: date-time
          nullable: true
        updatedAt:
          type: string
          format: date-time
          nullable: true
        isArchived:
          type: boolean
        updatable:
          type: boolean
      additionalProperties: false
    StudentPublicDataDtoListPagedStudentFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/StudentPublicDataDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    StudentUpdateRequestDto:
      required:
        - firstName
        - gender
        - grade
        - lastName
      type: object
      properties:
        studentId:
          maxLength: 50
          type: string
          nullable: true
        studentDisplayId:
          maxLength: 200
          type: string
          nullable: true
        qrCode:
          maxLength: 50
          type: string
          nullable: true
        lastName:
          maxLength: 50
          minLength: 1
          type: string
        firstName:
          maxLength: 50
          minLength: 1
          type: string
        middleName:
          maxLength: 100
          type: string
          nullable: true
        gender:
          $ref: '#/components/schemas/GenderTypeEnum'
        otherName:
          maxLength: 100
          type: string
          nullable: true
        email:
          maxLength: 256
          type: string
          format: email
          nullable: true
        dateOfBirth:
          type: string
          format: date
          nullable: true
        house:
          maxLength: 100
          type: string
          nullable: true
        grade:
          maxLength: 100
          minLength: 1
          type: string
        homeroomClass:
          maxLength: 100
          type: string
          nullable: true
        sen:
          type: boolean
          nullable: true
        isArchived:
          type: boolean
      additionalProperties: false
    SubjectClassResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        title:
          type: string
          nullable: true
        subjectId:
          type: integer
          format: int32
        schoolYearGroupId:
          type: integer
          format: int32
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        isArchived:
          type: boolean
        createdAtUtc:
          type: string
          format: date-time
        updatedAtUtc:
          type: string
          format: date-time
        thirdPartyId:
          type: string
          nullable: true
        isImported:
          type: boolean
      additionalProperties: false
    SubjectClassResponseDtoListPagedSubjectClassFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/SubjectClassResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    SubjectClassStudentsOperationResultDto:
      type: object
      properties:
        studentsProcessed:
          type: integer
          format: int32
        totalRequested:
          type: integer
          format: int32
      additionalProperties: false
    SubjectClassStudentsRequestDto:
      required:
        - studentIds
      type: object
      properties:
        studentIds:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
      additionalProperties: false
    SubjectResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        name:
          type: string
          nullable: true
        isArchived:
          type: boolean
        createdAtUtc:
          type: string
          format: date-time
        updatedAtUtc:
          type: string
          format: date-time
        thirdPartyId:
          type: string
          nullable: true
        isImported:
          type: boolean
      additionalProperties: false
    SubjectResponseDtoListPagedSubjectFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/SubjectResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    TeamGenderType:
      enum:
        - Female
        - Male
        - Mixed
      type: string
    TeamTypeFilter:
      enum:
        - Group
        - Homeroom
        - SubjectClass
        - Grade
        - House
      type: string
    UpdateClassRequestDto:
      type: object
      properties:
        name:
          maxLength: 240
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    UpdateGroupRequestDto:
      type: object
      properties:
        name:
          maxLength: 240
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        activityId:
          type: integer
          format: int32
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        showInSportsPortal:
          type: boolean
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    UpdateHouseRequestDto:
      type: object
      properties:
        name:
          maxLength: 240
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    UpdateIbpGroupRequestDto:
      type: object
      properties:
        groupName:
          maxLength: 255
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          type: integer
          format: int32
          nullable: true
        showInSportsPortal:
          type: boolean
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
          nullable: true
        maximumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        minimumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    UpdateIbpRequestDto:
      type: object
      properties:
        name:
          maxLength: 255
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        activitiesStartDate:
          type: string
          format: date
          nullable: true
        activitiesEndDate:
          type: string
          format: date
          nullable: true
        activitiesDefaultStartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        activitiesDefaultEndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        responsibilityForConfirmation:
          $ref: '#/components/schemas/CcaSignupResponsibility'
        signupOpens:
          type: string
          format: date-time
          nullable: true
        signupCloses:
          type: string
          format: date-time
          nullable: true
        termsAndConditions:
          type: string
          nullable: true
        additionalInfoUrl:
          type: string
          nullable: true
      additionalProperties: false
    UpdatePrefGroupRequestDto:
      type: object
      properties:
        groupName:
          maxLength: 255
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        groupCode:
          maxLength: 50
          type: string
          nullable: true
        billingCode:
          maxLength: 50
          type: string
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        staffIds:
          type: array
          items:
            type: integer
            format: int32
          nullable: true
        activityId:
          type: integer
          format: int32
          nullable: true
        showInSportsPortal:
          type: boolean
          nullable: true
        locationId:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        informationOnly:
          type: boolean
          nullable: true
        day1:
          $ref: '#/components/schemas/DayOfWeekType'
        day1StartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day1EndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day2:
          $ref: '#/components/schemas/DayOfWeekType'
        day2StartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        day2EndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        maximumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        minimumPlaces:
          maximum: 2147483647
          minimum: 0
          type: integer
          format: int32
          nullable: true
        cost:
          type: number
          format: double
          nullable: true
        joinRequestsOn:
          type: boolean
          nullable: true
        availableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        preRequisite:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        notAvailableTo:
          type: array
          items:
            $ref: '#/components/schemas/CcaGroupReferenceDto'
          nullable: true
        genderAvailableTo:
          $ref: '#/components/schemas/TeamGenderType'
        taxCode:
          maxLength: 10
          type: string
          nullable: true
        shortName:
          maxLength: 30
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    UpdatePrefRequestDto:
      type: object
      properties:
        name:
          maxLength: 255
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        preferenceSelectionScope:
          $ref: '#/components/schemas/PreferenceSelectionScopeEnum'
        eventCategoryId:
          maximum: 2147483647
          minimum: 1
          type: integer
          format: int32
          nullable: true
        activitiesStartDate:
          type: string
          format: date
          nullable: true
        activitiesEndDate:
          type: string
          format: date
          nullable: true
        activitiesDefaultStartTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        activitiesDefaultEndTime:
          type: string
          format: partial-time
          nullable: true
          example: '16:00:00'
        responsibilityForConfirmation:
          $ref: '#/components/schemas/CcaSignupResponsibility'
        signupOpens:
          type: string
          format: date-time
          nullable: true
        signupCloses:
          type: string
          format: date-time
          nullable: true
        termsAndConditions:
          type: string
          nullable: true
        additionalInfoUrl:
          type: string
          nullable: true
      additionalProperties: false
    UpdateSubjectClassRequestDto:
      type: object
      properties:
        title:
          maxLength: 250
          type: string
          nullable: true
        subjectId:
          type: integer
          format: int32
          nullable: true
        schoolYearGroupId:
          type: integer
          format: int32
          nullable: true
        leadStaffId:
          type: integer
          format: int32
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    UpdateSubjectRequestDto:
      type: object
      properties:
        name:
          maxLength: 200
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    UpdateYearRequestDto:
      type: object
      properties:
        name:
          maxLength: 150
          type: string
          nullable: true
        isArchived:
          type: boolean
          nullable: true
      additionalProperties: false
    YearResponseDto:
      type: object
      properties:
        id:
          type: integer
          format: int32
        organisationId:
          type: integer
          format: int32
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        schoolYearGroupId:
          type: integer
          format: int32
        isArchived:
          type: boolean
        createdAtUtc:
          type: string
          format: date-time
        updatedAtUtc:
          type: string
          format: date-time
        thirdPartyId:
          type: string
          nullable: true
        isImported:
          type: boolean
      additionalProperties: false
    YearResponseDtoListPagedYearFilterResponseDto:
      type: object
      properties:
        isSuccess:
          type: boolean
        errors:
          type: array
          items:
            type: string
          nullable: true
        messageTranslationParameters:
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/YearResponseDto'
          nullable: true
        pageNumber:
          type: integer
          format: int32
        pageSize:
          type: integer
          format: int32
        firstPage:
          type: string
          format: uri
          nullable: true
        lastPage:
          type: string
          format: uri
          nullable: true
        totalPages:
          type: integer
          format: int32
        totalRecords:
          type: integer
          format: int32
        nextPage:
          type: string
          format: uri
          nullable: true
        previousPage:
          type: string
          format: uri
          nullable: true
        baseUri:
          type: string
          format: uri
          nullable: true
        searchParameters:
          type: array
          items:
            $ref: '#/components/schemas/StringStringKeyValuePair'
          nullable: true
      additionalProperties: false
    YearStudentsOperationResultDto:
      type: object
      properties:
        studentsProcessed:
          type: integer
          format: int32
        totalRequested:
          type: integer
          format: int32
      additionalProperties: false
    YearStudentsRequestDto:
      required:
        - studentIds
      type: object
      properties:
        studentIds:
          minItems: 1
          type: array
          items:
            type: integer
            format: int32
      additionalProperties: false
  securitySchemes:
    oauth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://accounts1.schoolsbuddy.net/connect/token
          scopes: { }
    Bearer:
      type: apiKey
      description: Type "Bearer" followed by a space and a token.
      name: Authorization
      in: header
security:
  - Bearer: [ ]
tags:
  - name: Activities
  - name: Class
  - name: Contacts
  - name: EventCategories
  - name: Events
  - name: External
  - name: Group
  - name: Groups
  - name: HealthCheck
  - name: House
  - name: Ibp
  - name: Integrations
  - name: Locations
  - name: Pref
  - name: Staff
  - name: Students
  - name: Subject
  - name: SubjectClass
  - name: Transport
  - name: Year