openapi: 3.0.0 info: title: Tovuti REST API version: 1.66.3 termsOfService: https://www.tovutilms.com/terms contact: name: Tovuti Support Page url: https://help.tovutilms.com email: support@tovutiteam.com license: name: Tovuti LMS End User License url: https://www.tovutilms.com/end-user-license servers: - url: https://{host}/api/v1 variables: host: default: api.tovuti.io security: - sanctumToken: [] tags: - name: Assignments - name: Assessments - name: Assessment Question Banks - name: Assessment Questions - name: Audit - name: Awards - name: Checklists - name: Community Groups - name: Courses - name: Course Categories - name: Course Progress - name: Custom Fields - name: Events - name: Instructors - name: Learning Paths - name: Learning Path Categories - name: Learning Path Progress - name: Learning Path Subcategories - name: Lessons - name: Media Categories - name: Media Items - name: Meetings - name: Objects - name: Object Types - name: Payments - name: Profile Fields - name: Promo Codes - name: Purchase Orders - name: Quizzes - name: Reports - name: Subscriptions - name: Surveys - name: Teams - name: Transactions - name: Users - name: User Groups paths: /audit/admin: get: tags: - Audit summary: Read Admin Audit Log parameters: - in: query schema: type: integer name: cursor description: > Retrieve all log entries after this ID. Cursor paging walks entries in ascending id order, so it cannot be combined with `sortBy` / `sortDir`; a request that sends both is rejected with HTTP 400. - in: query schema: type: string format: date description: Limit results to log entries before this date example: 2023-01-12 name: before - in: query schema: type: string format: date description: Limit results to log entries after this date example: 2023-01-12 name: after - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query name: auditTypeId schema: type: integer description: Filter to entries whose audit type id (foreign_table) matches this value. Required when itemId is supplied. - in: query name: itemId schema: type: integer description: Filter to entries whose target record id (foreign_id) matches this value. Must be paired with auditTypeId since item ids are only unique within a single audit type. - in: query name: userId schema: type: integer description: Filter to entries logged for actions performed by this user id. - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Audit" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_admin_audit_log /audit/auth: get: tags: - Audit summary: Read User Authentication log parameters: - in: query schema: type: integer name: cursor description: > Retrieve all log entries after this ID. Cursor paging walks entries in ascending id order, so it cannot be combined with `sortBy` / `sortDir`; a request that sends both is rejected with HTTP 400. - in: query schema: type: string format: date description: Limit results to log entries before this date example: 2023-01-12 name: before - in: query schema: type: string format: date description: Limit results to log entries after this date example: 2023-01-12 name: after - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/AuthAudit" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_user_authentication_log /audit/types: get: tags: - Audit summary: Read Audit Action Types parameters: - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/AuditActionType" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' description: 'Pagination note: this endpoint never returns total or last_page (includeTotal is not supported).' operationId: read_audit_action_types /assignment: post: tags: - Assignments summary: Create Assignment requestBody: content: application/json: schema: $ref: "#/components/schemas/Assignment" responses: '201': description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Assignment" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_assignment /assignment/{id}: get: tags: - Assignments summary: Read Assignment parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Assignment" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_assignment patch: tags: - Assignments summary: Update Assignment parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/AssignmentUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Assignment' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_assignment delete: tags: - Assignments summary: Delete Assignment parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_assignment /assignments: get: tags: - Assignments summary: Read Assignments parameters: - in: query schema: type: string example: 1,2,3 name: assignmentIds description: Comma separated list of assignment ids. - in: query name: startBefore schema: type: string format: date - in: query name: startAfter schema: type: string format: date - in: query name: endBefore schema: type: string format: date - in: query name: endAfter schema: type: string format: date - in: query name: dueBefore schema: type: string format: date - in: query name: dueAfter schema: type: string format: date - in: query name: createdBefore schema: type: string format: date - in: query name: createdAfter schema: type: string format: date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/userIdsParam" - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/teamIdsParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: title required: false schema: type: string description: Filter by assignment title. Exact match unless % wildcards are included. - in: query name: assignmentFilterType required: false schema: type: string enum: - users - groups description: Filter by assignment target type. responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Assignment" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_assignments /award: post: tags: - Awards summary: Create Award requestBody: content: application/json: schema: $ref: "#/components/schemas/Award" responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Award' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_award /award/{id}: get: tags: - Awards summary: Read Award parameters: - in: path name: id required: true schema: type: integer responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Award" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_award patch: tags: - Awards summary: Update Award parameters: - in: path name: id required: true schema: type: integer requestBody: content: application/json: schema: $ref: '#/components/schemas/AwardUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Award" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_award delete: tags: - Awards summary: Delete Award parameters: - in: path name: id required: true schema: type: integer responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_award /award/{id}/deleteEarned: delete: tags: - Awards summary: Delete Earned Awards parameters: - in: path name: id required: true schema: type: integer responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_earned_awards /awards: get: tags: - Awards summary: Read Awards parameters: - in: query name: awardIds schema: type: string - in: query name: title schema: type: string description: Filter by title. Exact match unless % wildcards are included. - in: query name: type schema: type: string enum: - badge - milestone - certificate - in: query name: createdBefore schema: type: string format: date - in: query name: createdAfter schema: type: string format: date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Award" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_awards /awards/sync: patch: tags: - Awards summary: Sync Awards requestBody: content: application/json: schema: allOf: - $ref: "#/components/schemas/AwardSyncRequest" anyOf: - required: - user_id - required: - award_id description: At least one of user_id or award_id is required. responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/AwardSyncRequest" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: sync_awards /checklist: post: tags: - Checklists summary: Create Checklist requestBody: content: application/json: schema: allOf: - $ref: "#/components/schemas/Checklist" required: - title - due_date responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Checklist' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_checklist /checklist/{id}: get: tags: - Checklists summary: Read Checklist parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Checklist" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_checklist patch: tags: - Checklists summary: Update Checklist description: 'Checklist items can be updated by passing the id of the checklist item in the patch, for example: { "id": "1689003604CWilGr", "title": "Updated Title" }. If a checklist item needs to be deleted, include the delete flag and set it to true, for example: { "id": "1689003604CWilGr", "delete": true }.' parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: "#/components/schemas/Checklist" responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Checklist' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_checklist delete: tags: - Checklists summary: Delete Checklist parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_checklist /checklist/{checklistId}/user/{userId}/item/{itemId}: patch: tags: - Checklists summary: Update Checklist Item Completion description: 'Marks a single checklist item complete or incomplete for a user. When completing the final required item, the parent checklist is marked complete and any configured admin and user "checklist completed" notifications are sent. Item points are awarded (or reversed). Awards/badges tied to checklist completion are NOT granted by this call — call PATCH /awards/sync with the user_id afterward to evaluate them.' parameters: - in: path name: checklistId schema: type: integer required: true - in: path name: userId schema: type: integer required: true - in: path name: itemId description: The checklist item identifier (the item "id" from GET /checklist/{id}). schema: type: integer required: true requestBody: required: true content: application/json: schema: type: object required: - is_complete properties: is_complete: type: boolean example: true responses: "200": description: Successful Response. content: application/json: schema: type: object properties: data: type: object properties: id: type: integer user_id: type: integer checklist_id: type: integer item_id: type: string item_name: type: string nullable: true is_complete: type: boolean completed_at: type: string nullable: true updated_at: type: string nullable: true checklist_progress: type: integer "400": description: Validation error (e.g. is_complete missing or not a boolean). content: application/json: {} "404": description: User, checklist, or checklist item not found. content: application/json: {} '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: update_checklist_item_completion /checklists: get: tags: - Checklists summary: Read Checklists parameters: - in: query schema: type: string description: Comma separated list of checklist ids. example: 1,2,3 name: checklistIds - in: query schema: type: string example: ChecklistTitle name: title description: Filter by title. Exact match unless % wildcards are included. - in: query name: dueBefore schema: type: string format: date - in: query name: dueAfter schema: type: string format: date - in: query name: createdBefore schema: type: string format: date - in: query name: createdAfter schema: type: string format: date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Checklist" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_checklists /communityGroup: post: tags: - Community Groups summary: Create Community Group requestBody: content: application/json: schema: $ref: "#/components/schemas/CommunityGroup" responses: "201": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/CommunityGroup' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_community_group /communityGroup/{id}: get: tags: - Community Groups summary: Read Community Group parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/CommunityGroup" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_community_group patch: tags: - Community Groups summary: Update Community Group parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/CommunityGroupUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/CommunityGroup' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_community_group delete: tags: - Community Groups summary: Delete Community Group parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_community_group /communityGroups: get: tags: - Community Groups summary: Read Community Groups parameters: - name: id in: query schema: type: integer - name: name in: query schema: type: string - name: groupId in: query schema: type: integer description: A User group ID - in: query name: createdBefore schema: type: string format: date - in: query name: createdAfter schema: type: string format: date - name: published in: query schema: type: boolean default: true description: Filter by published state. Defaults to true - unpublished groups are hidden unless published=false is passed. - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/CommunityGroup" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_community_groups /communityGroup/{id}/posts: get: tags: - Community Groups summary: Read Community Group Posts description: | Returns the top-level content of a community group, newest first: wall posts (`type=post`), discussion topics (`type=discussion`) and published announcements (`type=announcement`). Archived wall posts are excluded. Ids are only unique within a `type`; pass both to the comments endpoint. Timestamps are UTC with one-second precision. **Polling:** `timestampCreatedAfter` is exclusive, and several items can share a `created_at` second (an item can also become visible slightly after the second it is stamped with). So don't pass the latest `created_at` you have seen as-is: pass it minus an overlap window (60 seconds is enough), and skip items you have already processed, keyed on `type` + `id`. Passing the latest `created_at` unchanged will silently miss items created in that same second. parameters: - in: path name: id required: true schema: type: integer description: Community Group ID - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/CommunityGroupPost" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_community_group_posts /communityGroup/post/{id}/comments: get: tags: - Community Groups summary: Read Community Group Post Comments description: | Returns the comments on a community group post, newest first. For a discussion these are its replies. Announcements in private groups cannot be commented on and return an empty page. Timestamps are UTC. To poll, use the same overlap-and-dedupe pattern as the posts endpoint, keyed on the comment `id`. parameters: - in: path name: id required: true schema: type: integer description: Post ID, as returned by the posts endpoint - in: query name: type description: The `type` of the post the ID refers to. schema: type: string enum: [post, discussion, announcement] default: post - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/CommunityGroupComment" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_community_group_post_comments /course: post: tags: - Courses summary: Create Course requestBody: content: application/json: schema: $ref: "#/components/schemas/Course" responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Course' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_course /course/{id}: get: tags: - Courses summary: Read Course parameters: - in: path name: id schema: type: integer required: true - in: query name: excludeRegistrants schema: type: boolean description: When true, omits the registrants array from the response to improve performance. - in: query $ref: "#/components/parameters/excludeParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/Course" - type: object properties: locked: type: integer description: 0 - Course is Unlocked, 1 - Course is Locked '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_course patch: tags: - Courses summary: Update Course parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/CourseUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Course" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_course delete: tags: - Courses summary: Delete Course parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_course /courses: get: tags: - Courses summary: Read Courses parameters: - name: courseIds in: query schema: type: string - name: title in: query schema: type: string description: Filter by title. Exact match unless % wildcards are included. - name: subCategoryIds in: query schema: type: string description: List of sub categories to search for. example: "1,2,104" - name: finalCourseSurveyId in: query schema: type: integer description: Id of the final course survey for this course. - name: published in: query schema: type: boolean - in: query name: createdBefore schema: type: string format: date - in: query name: createdAfter schema: type: string format: date - in: query name: modifiedBefore schema: type: string format: date - in: query name: modifiedAfter schema: type: string format: date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - name: modifyDate in: query description: Options include lt, gt, le, and ge for <, >, <=, and >=. Leave blank for =. schema: type: string example: lt2022-16-15 - name: excludeRegistrants in: query schema: type: boolean description: When true, omits the registrants array from the response to improve performance. - in: query $ref: "#/components/parameters/excludeParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Course" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_courses /courseCategory: post: tags: - Course Categories summary: Create Course Category requestBody: content: application/json: schema: $ref: "#/components/schemas/CourseCategory" responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/CourseCategory' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_course_category /courseCategory/{id}: get: tags: - Course Categories summary: Read Course Category parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/CourseCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_course_category patch: tags: - Course Categories summary: Edit Course Category parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/CourseCategoryUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/CourseCategory' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: edit_course_category delete: tags: - Course Categories summary: Delete Course Category parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_course_category /courseCategories: get: tags: - Course Categories summary: Read Course Categories parameters: - name: courseCategoryIds in: query schema: type: string example: 1,2,3 - name: title in: query schema: type: string example: Course Title description: Filter by title. Exact match unless % wildcards are included. - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/CourseCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_course_categories /courseProgress: post: tags: - Course Progress summary: Create Course Progress requestBody: content: application/json: schema: allOf: - $ref: "#/components/schemas/CourseProgress" required: - user_id - course_id - language responses: '201': description: Successfully created user course progress. content: application/json: schema: $ref: '#/components/schemas/CourseProgress' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_course_progress /courseProgress/{id}: get: tags: - Course Progress summary: Read Course Progress parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Course progress record. content: application/json: schema: $ref: '#/components/schemas/CourseProgress' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_course_progress patch: tags: - Course Progress summary: Update Course Progress parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: "#/components/schemas/CourseProgress" responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/CourseProgress' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_course_progress delete: tags: - Course Progress summary: Delete Course Progress parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successfully deleted user course progress. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_course_progress /courseProgresses: get: tags: - Course Progress summary: Read Course Progresses description: All parameters can be used in either the query or the request body. parameters: - in: query name: userId schema: type: integer description: Search by user id. - in: query name: courseId schema: type: integer description: Search by course id. - in: query name: lessonId schema: type: integer - in: query name: startBefore schema: type: string - in: query name: startAfter schema: type: string - in: query name: lastActivityBefore schema: type: string - in: query name: lastActivityAfter schema: type: string - in: query name: completedBefore schema: type: string - in: query name: completedAfter schema: type: string description: Search by lesson id. - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/CourseProgress" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_course_progresses /customField/{id}: get: deprecated: true tags: - Profile Fields summary: "Read Profile Field - Deprecated, use /metadata/customFields?objectType=users&customFieldIds={id} instead" description: > Deprecated. User profile field definitions are now read from the Custom Fields routes: GET /metadata/customFields?objectType=users&customFieldIds={id} returns the same definition in the CustomFieldDefinition shape. parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/CustomField" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_profile_field /customFields: get: deprecated: true tags: - Profile Fields summary: "Read Profile Fields - Deprecated, use /metadata/customFields?objectType=users instead" description: > Deprecated. User profile field definitions are now read from the Custom Fields routes: GET /metadata/customFields?objectType=users returns the same definitions in the CustomFieldDefinition shape, with that endpoint's full filter set (type, enabled and the timestamp filters) and its ordering. parameters: - in: query name: customFieldIds schema: type: string - in: query name: name schema: type: string - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: '#/components/schemas/CustomField' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_profile_fields /event: post: tags: - Events summary: Create Event requestBody: content: application/json: schema: $ref: "#/components/schemas/Event" multipart/form-data: schema: $ref: "#/components/schemas/EventWithImage" responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Event' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_event /event/{id}: get: tags: - Events summary: Read Event parameters: - in: path name: id schema: type: integer required: true - in: query $ref: "#/components/parameters/excludeParam" responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Event" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_event post: tags: - Events summary: Update Event (multipart) parameters: - in: path name: id schema: type: integer required: true requestBody: content: multipart/form-data: schema: $ref: '#/components/schemas/EventWithImageUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Event' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_event_multipart patch: tags: - Events summary: Update Event. parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/EventUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Event' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_event /event/{id}/register: post: tags: - Events summary: Register for Event description: Only free events, with registration type = 0 or registration_type = 1 can be registered for at this time. Users are registered as individuals. Users must already exist in the system in order to be registered for an event. parameters: - in: path name: id schema: type: integer required: true - in: query name: userIds required: true schema: type: string example: 1620265,1620266 description: Comma-separated list of user ids. - in: query name: checkedIn required: false schema: type: integer enum: - 0 - 1 description: Set to 1 to also check the users in while registering them. responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: register_for_event /event/{id}/checkin: post: tags: - Events summary: Check Users into Event parameters: - in: path name: id schema: type: integer required: true - in: query name: userIds required: true schema: type: string example: 1620265,1620266 description: Comma-separated list of user ids. - in: query name: cancel schema: type: boolean description: if set to true, checked_in will be set to 0. responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: check_users_into_event /events: get: tags: - Events summary: Read Events parameters: - in: query name: eventIds schema: type: string - in: query name: title schema: type: string description: Filter by title. Exact match unless % wildcards are included. - in: query name: languages schema: type: string description: Comma-separated list of languages. Event languages default to '*' which is all languages. - in: query name: startBefore schema: type: string format: date - in: query name: startAfter schema: type: string format: date - in: query name: endBefore schema: type: string format: date - in: query name: endAfter schema: type: string format: date - in: query name: registrationStartDateBefore schema: type: string format: date - in: query name: registrationStartDateAfter schema: type: string format: date - in: query name: cutoffDateBefore schema: type: string format: date - in: query name: cutoffDateAfter schema: type: string format: date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/excludeParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Event" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_events /locations: get: tags: - Events summary: Read - Locations parameters: - in: query name: eventIds schema: type: string - in: query name: locationIds schema: type: string - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Location" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_locations /events/categories: get: tags: - Events summary: Read Event Categories parameters: - in: query name: parentId schema: type: integer description: Filter by parent category ID - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/EventCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_event_categories /event/category/{id}: get: tags: - Events summary: Read Event Category parameters: - in: path name: id required: true schema: type: integer description: Event Category ID responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/EventCategory" "404": description: Event Category not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_event_category /instructors: get: tags: - Instructors summary: Read Instructors parameters: - name: userId in: query description: Filter by user ID. schema: type: integer example: 123 - name: title in: query description: Filter by instructor display name (matches the response `name` field). Exact match unless % wildcards are included. schema: type: string example: John Doe - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Instructor" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_instructors /learningPath: post: tags: - Learning Paths summary: Create a Learning Path requestBody: content: application/json: schema: $ref: "#/components/schemas/LearningPath" multipart/form-data: schema: $ref: "#/components/schemas/LearningPathWithImage" responses: "201": description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPath" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_a_learning_path /learningPath/{id}: get: tags: - Learning Paths summary: Read Learning Path parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPath" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_learning_path patch: tags: - Learning Paths summary: Update Learning Path parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/LearningPathUpdate' responses: '201': description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPath" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_learning_path post: tags: - Learning Paths summary: Update Learning Path (multipart) parameters: - in: path name: id schema: type: integer required: true requestBody: content: multipart/form-data: schema: $ref: '#/components/schemas/LearningPathWithImageUpdate' responses: '201': description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPath" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_learning_path_multipart delete: tags: - Learning Paths summary: Delete Learning Path parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_learning_path /learningPathProgress: post: tags: - Learning Path Progress summary: Create Learning Path Progress description: >- Completion side effects: when `progress` reaches 100% the learning path is marked complete — `date_completed` is stamped automatically (and cleared if it later drops below 100%; a caller-supplied `date_completed` is only retained at 100%), and learning-path completion **points** are awarded automatically (and reversed if it drops below 100%). Completion **badges/awards are NOT granted by this endpoint**: to grant a badge whose requirement is learning-path completion, call `PATCH /v1/awards/sync` for the user after the path reaches 100%. requestBody: content: application/json: schema: allOf: - $ref: "#/components/schemas/LearningPathProgress" required: - user_id - learning_path_id responses: "201": description: Learning path progress created successfully. content: application/json: schema: $ref: "#/components/schemas/LearningPathProgress" "400": description: >- Validation error (e.g. missing/invalid user_id or learning_path_id), or an active progress record already exists for this user and learning path. "403": description: Access denied. '401': $ref: '#/components/responses/Unauthorized' operationId: create_learning_path_progress /learningPathProgress/{id}: get: tags: - Learning Path Progress summary: Read Learning Path Progress parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Learning path progress record. content: application/json: schema: $ref: "#/components/schemas/LearningPathProgress" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_learning_path_progress patch: tags: - Learning Path Progress summary: Update Learning Path Progress description: >- Completion side effects: when `progress` reaches 100% the learning path is marked complete — `date_completed` is stamped automatically (and cleared if it later drops below 100%; a caller-supplied `date_completed` is only retained at 100%), and learning-path completion **points** are awarded automatically (and reversed if it drops below 100%). Completion **badges/awards are NOT granted by this endpoint**: to grant a badge whose requirement is learning-path completion, call `PATCH /v1/awards/sync` for the user after the path reaches 100%. parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: "#/components/schemas/LearningPathProgress" responses: "200": description: Updated learning path progress record. content: application/json: schema: $ref: "#/components/schemas/LearningPathProgress" "400": description: Validation error. "403": description: Access denied. "404": description: Learning path progress record not found. '401': $ref: '#/components/responses/Unauthorized' operationId: update_learning_path_progress delete: tags: - Learning Path Progress summary: Delete Learning Path Progress parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successfully deleted learning path progress. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_learning_path_progress /learningPathProgresses: get: tags: - Learning Path Progress summary: Read Learning Path Progresses parameters: - in: query name: userIds schema: type: string description: Comma separated list of user IDs. example: "1,2,3" - in: query name: learningPathIds schema: type: string description: Comma separated list of learning path IDs. example: "1,2,3" - in: query name: startBefore schema: type: string format: date description: Limit results to those started before this date (Y-m-d). example: "2023-01-12" - in: query name: startAfter schema: type: string format: date description: Limit results to those started after this date (Y-m-d). example: "2023-01-12" - in: query name: lastActivityBefore schema: type: string format: date description: Limit results to those with last activity before this date (Y-m-d). example: "2023-01-12" - in: query name: lastActivityAfter schema: type: string format: date description: Limit results to those with last activity after this date (Y-m-d). example: "2023-01-12" - in: query name: completedBefore schema: type: string format: date description: Limit results to those completed before this date (Y-m-d). example: "2023-01-12" - in: query name: completedAfter schema: type: string format: date description: Limit results to those completed after this date (Y-m-d). example: "2023-01-12" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/LearningPathProgress" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_learning_path_progresses /learningPaths: get: tags: - Learning Paths summary: Read Learning Paths parameters: - name: title in: query schema: type: string example: All About Tovuti description: "Exact match unless % wildcards are included." - name: id in: query schema: type: integer example: 1 - name: user in: query schema: type: integer example: 1 description: Show learning paths that include the given user id in the view permission - name: usergroup in: query schema: type: integer example: 1 description: Show learning paths that include the given user group id in the view permission - name: accesslevel in: query schema: type: integer example: 1 description: Show learning paths that include the given access level id in the view permission - name: courses in: query schema: type: string example: 1,3 description: "Comma separated list of course IDs" - name: tags in: query schema: type: string example: 1,3 description: "Comma separated list of Tag IDs" - name: subcategories in: query schema: type: string example: 1,3 description: "Comma separated list of subcategory IDs" - in: query schema: type: string format: date description: Limit results to those created before this date example: 2023-01-12 name: createdBefore - in: query schema: type: string format: date description: Limit results to those created after this date example: 2023-01-12 name: createdAfter - in: query schema: type: string format: date description: Limit results to those created modified this date example: 2023-01-12 name: modifiedBefore - in: query schema: type: string format: date description: Limit results to those created modified this date example: 2023-01-12 name: modifiedAfter - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: published required: false schema: type: boolean description: Filter by published state. responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/LearningPath" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_learning_paths /learningPaths/tags: get: tags: - Learning Paths summary: Read Learning Path Tags parameters: - name: title in: query schema: type: string example: A title description: "Exact match unless % wildcards are included." - name: id in: query schema: type: integer example: 1 - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Tag" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_learning_path_tags /learningPathCategory: post: tags: - Learning Path Categories summary: Create a Learning Path Category requestBody: content: application/json: schema: $ref: "#/components/schemas/LearningPathCategory" responses: "201": description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPathCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_a_learning_path_category /learningPathCategory/{id}: get: tags: - Learning Path Categories summary: Read Learning Path Category parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPathCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_learning_path_category patch: tags: - Learning Path Categories summary: Update Learning Path Category parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/LearningPathCategoryUpdate' responses: '201': description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPathCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_learning_path_category delete: tags: - Learning Path Categories summary: Delete Learning Path Category parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_learning_path_category /learningPathCategories: get: tags: - Learning Path Categories summary: Read Learning Path Categories parameters: - name: title in: query schema: type: string example: All About Tovuti description: "Exact match unless % wildcards are included." - name: id in: query schema: type: integer example: 1 - name: subcategories in: query schema: type: string example: 1,3 description: "Comma separated list of subcategory IDs" - in: query schema: type: string format: date description: Limit results to those created before this date example: 2023-01-12 name: createdBefore - in: query schema: type: string format: date description: Limit results to those created after this date example: 2023-01-12 name: createdAfter - in: query schema: type: string format: date description: Limit results to those modified before this date example: 2023-01-12 name: modifiedBefore - in: query schema: type: string format: date description: Limit results to those modified after this date example: 2023-01-12 name: modifiedAfter - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: published required: false schema: type: boolean description: Filter by published state. responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/LearningPathCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_learning_path_categories /learningPathSubcategory: post: tags: - Learning Path Subcategories summary: Create a Learning Path Subcategory requestBody: content: application/json: schema: $ref: "#/components/schemas/LearningPathSubcategory" multipart/form-data: schema: $ref: "#/components/schemas/LearningPathSubcategoryWithImage" responses: "201": description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPathSubcategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_a_learning_path_subcategory /learningPathSubcategory/{id}: get: tags: - Learning Path Subcategories summary: Read Learning Path Subcategory parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPathSubcategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_learning_path_subcategory patch: tags: - Learning Path Subcategories summary: Update Learning Path Subcategory parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/LearningPathSubcategoryUpdate' responses: '201': description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPathSubcategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_learning_path_subcategory post: tags: - Learning Path Subcategories summary: Update Learning Path Subcategory (multipart) parameters: - in: path name: id schema: type: integer required: true requestBody: content: multipart/form-data: schema: $ref: '#/components/schemas/LearningPathSubcategoryWithImageUpdate' responses: '201': description: Successful Response content: application/json: schema: $ref: "#/components/schemas/LearningPathSubcategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_learning_path_subcategory_multipart delete: tags: - Learning Path Subcategories summary: Delete Learning Path Subcategory parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_learning_path_subcategory /learningPathSubcategories: get: tags: - Learning Path Subcategories summary: Read Learning Path Subcategories parameters: - name: title in: query schema: type: string example: All About Tovuti description: "Exact match unless % wildcards are included." - name: id in: query schema: type: integer example: 1 - name: categories in: query schema: type: string example: 1,3 description: "Comma separated list of category IDs" - name: learningPaths in: query schema: type: string example: 1,3 description: "Comma separated list of learning path IDs" - in: query schema: type: string format: date description: Limit results to those created before this date example: 2023-01-12 name: createdBefore - in: query schema: type: string format: date description: Limit results to those created after this date example: 2023-01-12 name: createdAfter - in: query schema: type: string format: date description: Limit results to those created modified this date example: 2023-01-12 name: modifiedBefore - in: query schema: type: string format: date description: Limit results to those created modified this date example: 2023-01-12 name: modifiedAfter - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: published required: false schema: type: boolean description: Filter by published state. responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/LearningPathSubcategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_learning_path_subcategories /lesson: post: tags: - Lessons summary: Create Lesson requestBody: content: application/json: schema: $ref: "#/components/schemas/LessonInsert" responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Lesson' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_lesson /lesson/{id}: get: tags: - Lessons summary: Read Lesson parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Lesson" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_lesson patch: tags: - Lessons summary: Update Lesson parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/LessonInsertUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Lesson" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_lesson delete: tags: - Lessons summary: Delete Lesson parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_lesson /lessons: get: tags: - Lessons summary: Read Lessons parameters: - name: courseTitle in: query schema: type: string example: All About Tovuti description: "" - in: query $ref: "#/components/parameters/courseIdsParam" - name: language in: query schema: type: string example: en-GB description: "" - name: lessonIds in: query schema: type: string example: 1,3 description: "" - name: lessonTitle in: query schema: type: string example: About Tovuti description: "" - name: published in: query schema: type: boolean example: 0|1 description: "" - name: modifyDate in: query description: Options include lt, gt, le, and ge for <, >, <=, and >=. Leave blank for =. schema: type: string example: lt2022-16-15 - name: teacherName in: query schema: type: string example: Salomon Arthur description: "" - name: isFinalCourseSurvey in: query schema: type: boolean - in: query name: createdBefore schema: type: string format: date - in: query name: createdAfter schema: type: string format: date - in: query name: modifiedBefore schema: type: string format: date - in: query name: modifiedAfter schema: type: string format: date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: title required: false schema: type: string description: Filter by lesson title. Exact match unless % wildcards are included. - in: query name: createDate required: false schema: type: string format: date description: Filter by creation date (YYYY-MM-DD). responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Lesson" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' description: Unlike sibling endpoints, invalid query parameters here return 422 with {"message", "errors"} rather than 400. operationId: read_lessons /mediaCategory: post: tags: - Media Categories summary: Create Media Category requestBody: content: application/json: schema: $ref: "#/components/schemas/MediaCategory" responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/MediaCategory' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_media_category /mediaCategory/{id}: get: tags: - Media Categories summary: Read Media Category parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/MediaCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_media_category patch: tags: - Media Categories summary: Update Media Category parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/MediaCategoryUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/MediaCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_media_category delete: tags: - Media Categories summary: Delete Media Category parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_media_category /mediaCategories: get: tags: - Media Categories summary: Read Media Categories parameters: - name: title in: query schema: type: string example: category name description: "" description: Filter by title. Exact match unless % wildcards are included. - name: mediaCategoryIds in: query schema: type: string example: 1,3 description: "" - name: published in: query schema: type: boolean example: 0|1 description: "" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/MediaCategory" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_media_categories /mediaItem: post: tags: - Media Items summary: Create Media Item requestBody: content: multipart/form-data: schema: $ref: "#/components/schemas/MediaItem" application/json: schema: $ref: '#/components/schemas/MediaItemNoData' responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/MediaItem' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_media_item /mediaItem/{id}: post: tags: - Media Items summary: Update Media Item With File Upload parameters: - in: path name: id schema: type: integer required: true requestBody: content: multipart/form-data: schema: $ref: '#/components/schemas/MediaItemUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/MediaItem' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_media_item_with_file_upload get: tags: - Media Items summary: Read Media Item parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/MediaItem" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_media_item patch: tags: - Media Items summary: Update Media Item Without File Upload parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/MediaItemNoDataUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/MediaItem" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_media_item_without_file_upload delete: tags: - Media Items summary: Delete Media Item parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_media_item /mediaItems: get: tags: - Media Items summary: Read Media Items parameters: - name: title in: query schema: type: string example: my video description: "" description: Filter by title. Exact match unless % wildcards are included. - name: mediaItemIds in: query schema: type: string example: 1,3 description: "" - name: published in: query schema: type: boolean example: 0|1 description: "" - in: query name: createdBefore schema: type: string format: date - in: query name: createdAfter schema: type: string format: date - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/MediaItem" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_media_items /meeting: post: tags: - Meetings summary: Create Meeting requestBody: content: application/json: schema: $ref: "#/components/schemas/Meeting" responses: '201': description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Meeting" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_meeting /meeting/{id}: get: tags: - Meetings summary: Read Meeting parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Meeting" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_meeting patch: tags: - Meetings summary: Update Meeting description: > Not a partial update: `meetingName`, `meetingType`, `date` and `timezone` must be sent on every request, even when they are not changing, or the request is rejected with HTTP 400. parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: "#/components/schemas/Meeting" responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Meeting" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_meeting delete: tags: - Meetings summary: Delete Meeting parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_meeting /meetings: get: tags: - Meetings summary: Read Meetings parameters: - in: query name: meetingIds schema: type: string - in: query name: meetingName schema: type: string - in: query name: meetingType schema: type: string enum: - tovuti - zoom - webex - gotomeeting - google - joinme - other example: tovuti|zoom|webex|gotomeeting|google|joinme|other - in: query schema: type: string format: date name: dateBefore - in: query schema: type: string format: date name: dateAfter - in: query schema: type: string format: date name: createdBefore - in: query schema: type: string format: date name: createdAfter - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Meeting" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_meetings /metadata/customField/{id}: get: tags: - Custom Fields summary: Read Custom Field description: > A single custom field definition. Custom fields carry extra structured data on courses, events, purchase orders and user objects. `{id}` is always a metadata custom field id: user profile field definitions have no single-record route here - list them with GET /metadata/customFields?objectType=users, narrowing with customFieldIds when one specific definition is wanted. parameters: - in: path name: id required: true schema: type: integer responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/CustomFieldDefinition" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_custom_field /metadata/customField/{id}/values: get: tags: - Custom Fields summary: Read Values For Custom Field description: > Values recorded for a single custom field. Equivalent to /metadata/customFields/values?fieldIds={id}, with one exception: this route resolves the id first and returns 404 when the field definition has been deleted, whereas the fieldIds filter returns the orphaned value rows. Results are ordered by timestamp_modified, then id - descending by default, ascending with sortBy=timestampModified&sortDir=asc. Rows whose timestamp is NULL are excluded by any timestamp filter. parameters: - in: path name: id required: true schema: type: integer - in: query $ref: "#/components/parameters/objectIdsParam" - in: query name: objectType description: > Filter to values attached to this kind of object. Required whenever objectIds is supplied, because object_id is only unique within an object type - course 91 and event 91 are different objects. schema: type: string enum: [courses, events, "purchase order", "user objects"] example: courses - in: query name: type description: Filter to values whose field definition has this type. schema: type: string example: text - in: query name: enabled description: > Filter to values whose field definition has this enabled flag. Accepts `1`/`0` or `true`/`false`. Omit to return both. Values whose definition has been deleted match neither enabled state and are only returned when this filter is omitted. schema: type: boolean - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/CustomFieldValueDetail" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_custom_field_values /metadata/customFields: get: tags: - Custom Fields summary: Read Custom Fields description: > Custom field definitions for courses, events, purchase orders, user objects and users. Results are ordered by timestamp_modified, then id - descending by default, ascending with sortBy=timestampModified&sortDir=asc. Rows whose timestamp is NULL are excluded by any timestamp filter. `objectType=users` returns user profile field definitions - the definitions behind the values that GET /metadata/customFields/values?objectType=users reports. Omitting objectType keeps the endpoint's original meaning: metadata custom field definitions only, without user profile fields. parameters: - in: query name: customFieldIds description: > Comma separated list of custom field ids. Field definitions are numbered independently per object type family: with `objectType=users` these are user field definition ids; otherwise they are metadata custom field ids. schema: type: string example: 44,45 - in: query name: name description: Partial, case-insensitive match on the field name. schema: type: string example: Cost Center - in: query name: type description: > Field type. With `objectType=users` this matches user profile field types (text, textarea, select, list, radio, checkbox, country, gender, email, time, date, url, birthdate, and `group` for section headers). schema: type: string example: text - in: query name: objectType description: > Filter to definitions for this kind of object. `users` selects user profile field definitions, which are stored separately from the other object types and are only returned when requested explicitly. schema: type: string enum: [courses, events, "purchase order", "user objects", users] example: courses - in: query name: enabled description: > Filter on the field's enabled flag. Accepts `1`/`0` or `true`/`false`. Omit to return both. schema: type: boolean - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/CustomFieldDefinition" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_custom_fields /metadata/customFields/values: get: tags: - Custom Fields summary: Read Custom Field Values description: > Values recorded against custom fields, across all fields. object_id refers to a course, event, purchase order, user object or user id, per object_type. Results are ordered by timestamp_modified, then id - descending by default, ascending with sortBy=timestampModified&sortDir=asc. Rows whose timestamp is NULL are excluded by any timestamp filter. `objectType=users` returns user profile custom field values - the data embedded as `customFields` in user payloads (presented here in this endpoint's detail shape, not the trimmed embed shape) - and is the way to fetch it independently when calling the Users endpoints with `exclude=customFields`. parameters: - in: query name: fieldIds description: > Comma separated list of custom field ids. Field definitions are numbered independently per object type family: for `objectType=users` these are user field definition ids (as returned by GET /metadata/customFields?objectType=users); for every other objectType they are metadata custom field ids (GET /metadata/customFields). objectType is therefore required whenever fieldIds is supplied. schema: type: string example: 44,45 - in: query $ref: "#/components/parameters/objectIdsParam" - in: query name: objectType description: > Filter to values attached to this kind of object. For `users`, objectIds takes user ids. Required whenever objectIds or fieldIds is supplied: object_id is only unique within an object type - course 91 and event 91 are different objects - and field definitions are numbered independently per object type family. schema: type: string enum: [courses, events, "purchase order", "user objects", users] example: courses - in: query name: type description: Filter to values whose field definition has this type. schema: type: string example: text - in: query name: enabled description: > Filter to values whose field definition has this enabled flag. Accepts `1`/`0` or `true`/`false`. Omit to return both. Values whose definition has been deleted match neither enabled state and are only returned when this filter is omitted. schema: type: boolean - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/CustomFieldValueDetail" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_custom_fields_values /object: post: tags: - Objects summary: Create Object requestBody: content: application/json: schema: allOf: - $ref: "#/components/schemas/Object" required: - title - type_id responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Object' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_object /object/{id}: get: tags: - Objects summary: Read Object parameters: - in: path name: id schema: type: integer required: true - in: query $ref: "#/components/parameters/excludeParam" responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Object" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_object patch: tags: - Objects summary: Update Object parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: "#/components/schemas/Object" responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Object" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_object delete: tags: - Objects summary: Delete Object parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_object /objects: get: tags: - Objects summary: Read Objects parameters: - name: title in: query schema: type: string example: MyOrganization description: "" description: Filter by title. Exact match unless % wildcards are included. - in: query $ref: "#/components/parameters/customFieldsParam" - in: query name: objectIds schema: type: string example: 1,2,3 - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query $ref: "#/components/parameters/excludeParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Object" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_objects /objectType: post: tags: - Object Types summary: Create Object Type requestBody: content: application/json: schema: allOf: - $ref: "#/components/schemas/ObjectType" required: - title responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/ObjectType' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_object_type /objectType/{id}: get: tags: - Object Types summary: Read Object Type parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/ObjectType" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_object_type patch: tags: - Object Types summary: Update Object Type parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: "#/components/schemas/ObjectType" responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/ObjectType" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_object_type delete: tags: - Object Types summary: Delete Object Type parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_object_type /objectTypes: get: tags: - Object Types summary: Read Object Types parameters: - name: title in: query schema: type: string example: MyOrganization description: "" description: Filter by title. Exact match unless % wildcards are included. - in: query name: objectTypeIds schema: type: string example: 3,4,5 - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/ObjectType" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_object_types /profileField: post: tags: - Profile Fields summary: Create Custom Profile Field requestBody: content: application/json: schema: $ref: "#/components/schemas/ProfileField" responses: "201": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/ProfileField" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' description: Type-specific keys (options, date_format, min_characters, ...) are only honored for the matching field type; mismatched keys are silently dropped. operationId: create_custom_profile_field /profileField/{id}: get: tags: - Profile Fields summary: Read Custom Profile Field parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/ProfileField" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_custom_profile_field patch: tags: - Profile Fields summary: Update Custom Profile Field parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/ProfileFieldUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/ProfileField" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' description: The field type cannot be changed after creation (400). Type-specific keys are only honored for the matching field type. operationId: update_custom_profile_field delete: tags: - Profile Fields summary: Delete Custom Profile Field parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_custom_profile_field /profileFields: get: tags: - Profile Fields summary: Read Custom Profile Fields parameters: - in: query name: profileFieldIds schema: type: string description: A comma separated list of profile field ids example: 10,80,219 - in: query name: name schema: type: string - in: query name: type schema: type: string enum: [text, textarea, select, list, radio, checkbox, country, gender, email, time, date, url, birthdate] example: '[text, textarea, select, list, radio, checkbox, country, gender, email, time, date, url, birthdate]' - in: query name: visibility schema: type: string example: '[personal, all, admin]' enum: [personal, all, admin] - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: '#/components/schemas/ProfileField' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_custom_profile_fields /profileFields/group: post: tags: - Profile Fields summary: Create Custom Profile Field Group requestBody: content: application/json: schema: $ref: "#/components/schemas/ProfileFieldGroup" responses: "201": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/ProfileFieldGroup" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_custom_profile_field_group /profileFields/group/{id}: get: tags: - Profile Fields summary: Read Custom Profile Field Group parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/ProfileFieldGroup" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_custom_profile_field_group patch: tags: - Profile Fields summary: Update Custom Profile Field Group parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/ProfileFieldGroupUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/ProfileFieldGroup" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_custom_profile_field_group delete: tags: - Profile Fields summary: Delete Custom Profile Field Group parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_custom_profile_field_group /profileFields/groups: get: tags: - Profile Fields summary: Read Custom Profile Field Groups parameters: - in: query name: name schema: type: string - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: '#/components/schemas/ProfileFieldGroup' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_custom_profile_field_groups /profileFields/userGroupMapping: post: tags: - Profile Fields summary: Create Custom Profile Field Mapping requestBody: content: application/json: schema: $ref: "#/components/schemas/UserGroupMapping" responses: "201": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/UserGroupMappingResponse" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_custom_profile_field_mapping /profileFields/userGroupMapping/{id}: get: tags: - Profile Fields summary: Read Custom Profile Field Mapping parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/UserGroupMappingResponse" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_custom_profile_field_mapping patch: tags: - Profile Fields summary: Update Custom Profile Field Mapping parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/UserGroupMappingUpdate' responses: '201': description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/UserGroupMappingResponse" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_custom_profile_field_mapping delete: tags: - Profile Fields summary: Delete Custom Profile Field Mapping parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_custom_profile_field_mapping /profileFields/userGroupMappings: get: tags: - Profile Fields summary: Read Custom Profile Field Mappings parameters: - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: '#/components/schemas/UserGroupMappingResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_custom_profile_field_mappings /purchaseOrder/{id}: get: tags: - Purchase Orders summary: Read Purchase Order parameters: - in: path name: id required: true schema: type: integer description: Purchase Order ID - in: query $ref: "#/components/parameters/excludeParam" responses: "200": description: Successful response content: application/json: schema: $ref: '#/components/schemas/PurchaseOrder' "404": description: Purchase Order not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_purchase_order /purchaseOrders: get: tags: - Purchase Orders summary: Read Purchase Orders parameters: - in: query name: purchaseOrderIds schema: type: string description: Comma-separated list of purchase order IDs - in: query name: title schema: type: string description: Filter by title Exact match unless % wildcards are included. - in: query name: purchaseOrderNumber schema: type: string description: Filter by purchase order number - in: query name: enabled schema: type: boolean description: Filter by enabled status - in: query name: createdBefore schema: type: string format: date description: Filter by purchase orders created before this date (YYYY-MM-DD) - in: query name: createdAfter schema: type: string format: date description: Filter by purchase orders created after this date (YYYY-MM-DD) - in: query name: modifiedBefore schema: type: string format: date description: Filter by purchase orders modified before this date (YYYY-MM-DD) - in: query name: modifiedAfter schema: type: string format: date description: Filter by purchase orders modified after this date (YYYY-MM-DD) - in: query name: expiresBefore schema: type: string format: date description: Filter by purchase orders expiring before this date (YYYY-MM-DD) - in: query name: expiresAfter schema: type: string format: date description: Filter by purchase orders expiring after this date (YYYY-MM-DD) - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/excludeParam" - in: query $ref: '#/components/parameters/pageParam' - in: query $ref: '#/components/parameters/pageSizeParam' - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful response content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: '#/components/schemas/PurchaseOrder' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_purchase_orders /promoCodes: get: tags: - Promo Codes summary: Read Promo Codes parameters: - name: title in: query schema: type: string description: Filter by promo code title Exact match unless % wildcards are included. - name: promoCodeIds in: query schema: type: string description: Comma separated list of promo code IDs. - name: code in: query schema: type: string description: Filter by promo code - name: courseIds in: query schema: type: string description: Comma separated list of course IDs. - name: planIds in: query schema: type: string description: Comma separated list of subscription plan IDs. - in: query name: activeBefore schema: type: string format: date description: Filter by active date before specified date - in: query name: activeAfter schema: type: string format: date description: Filter by active date after specified date - in: query name: expiredBefore schema: type: string format: date description: Filter by expiration date before specified date - in: query name: expiredAfter schema: type: string format: date description: Filter by expiration date after specified date - in: query name: createdBefore schema: type: string format: date description: Filter by creation date before specified date - in: query name: createdAfter schema: type: string format: date description: Filter by creation date after specified date - in: query name: modifiedBefore schema: type: string format: date description: Filter by modification date before specified date - in: query name: modifiedAfter schema: type: string format: date description: Filter by modification date after specified date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - name: excludeCourseIds in: query schema: type: boolean description: When true, omits the course_ids array from the response to improve performance. - name: excludePlanIds in: query schema: type: boolean description: When true, omits the plan_ids array from the response to improve performance. responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: '#/components/schemas/PromoCode' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_promo_codes /promoCode/{id}: get: tags: - Promo Codes summary: Read Promo Code parameters: - in: path name: id schema: type: integer required: true description: Promo code ID responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/PromoCode" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_promo_code /quiz: post: tags: - Quizzes summary: Create Quiz requestBody: content: application/json: schema: $ref: "#/components/schemas/Quiz" responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Quiz' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_quiz /quiz/{id}: get: deprecated: true tags: - Quizzes summary: "Read Quiz - Deprecated, use /assessment/{id} instead" parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Quiz" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_quiz_deprecated_use_assessment_id_instead patch: tags: - Quizzes summary: Update Quiz parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/QuizUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Quiz' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_quiz delete: tags: - Quizzes summary: Delete Quiz parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_quiz /quizzes: get: deprecated: true tags: - Quizzes summary: "Read Quizzes - Deprecated, use /assessments instead" parameters: - in: query schema: type: string description: Comma separated list of quiz ids. example: 1,2,3 name: quizIds - in: query schema: type: string description: Comma separated list of course ids. example: 1,2,3 name: courseIds - in: query schema: type: string description: Comma separated list of lesson ids. example: 1,2,3 name: lessonIds - in: query schema: type: string name: title description: Filter by title. Exact match unless % wildcards are included. - in: query name: createdBefore schema: type: string format: date - in: query name: createdAfter schema: type: string format: date - in: query name: modifiedBefore schema: type: string format: date - in: query name: modifiedAfter schema: type: string format: date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: lessonTitle required: false schema: type: string description: Filter by lesson title. responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Quiz" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_quizzes_deprecated_use_assessments_instead /assessment/{id}: get: tags: - Assessments summary: Read Assessment description: Returns full assessment detail including questions with type-specific data (choices for multiple choice, keywords for free text). parameters: - in: path name: id required: true schema: type: integer description: Assessment ID responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/AssessmentDetail" "404": description: Assessment not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_assessment /assessments: get: tags: - Assessments summary: Read Assessments parameters: - in: query name: assessmentIds schema: type: string description: Comma separated list of assessment IDs - in: query name: courseIds schema: type: string description: Comma separated list of course IDs - in: query name: lessonIds schema: type: string description: Comma separated list of lesson IDs - in: query name: title schema: type: string description: Filter by title. Exact match unless % wildcards are included. - in: query name: enabled schema: type: boolean - in: query name: type schema: type: string enum: - quiz - survey description: Filter by assessment type - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/AssessmentDetail" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' description: List items do not include questions, course or lesson - use GET /assessment/{id} for the full shape. operationId: read_assessments /assessments/results: get: tags: - Assessments summary: Read Assessment Results description: Returns a lean summary of assessment results without embedded quiz or answer details. Use /assessments/result/{id} for full answer breakdown. parameters: - in: query name: ids schema: type: string description: Comma separated list of result IDs - in: query name: assessmentIds schema: type: string description: Comma separated list of assessment IDs - in: query $ref: "#/components/parameters/userNameParam" - in: query $ref: "#/components/parameters/userIdsParam" - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/teamIdsParam" - in: query name: lessonId schema: type: integer - in: query name: archived description: If true, show only archived data. schema: type: boolean - in: query name: submittedBefore schema: type: string format: date description: "Filter by submitted date before this date (YYYY-MM-DD)" - in: query name: submittedAfter schema: type: string format: date description: "Filter by submitted date after this date (YYYY-MM-DD)" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: lessonTitle required: false schema: type: string description: Filter by lesson title. - in: query name: courseTitle required: false schema: type: string description: Filter by course title. responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/AssessmentResultSummary" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_assessment_results /assessments/result/{id}: get: tags: - Assessments summary: Read Assessment Result description: Returns full assessment result detail including answer breakdown. parameters: - in: path name: id required: true schema: type: integer description: Assessment Result ID responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/AssessmentResultDetail" "404": description: Assessment Result not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_assessment_result /assessment/{id}/results: get: tags: - Assessments summary: Read Results for Assessment description: Returns results scoped to a specific assessment/quiz. parameters: - in: path name: id required: true schema: type: integer description: Assessment/Quiz ID - in: query $ref: "#/components/parameters/userIdsParam" - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/teamIdsParam" - in: query name: archived description: If true, show only archived data. schema: type: boolean - in: query name: submittedBefore schema: type: string format: date description: "Filter by submitted date before this date (YYYY-MM-DD)" - in: query name: submittedAfter schema: type: string format: date description: "Filter by submitted date after this date (YYYY-MM-DD)" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/AssessmentResultSummary" # ========================================== # Assessment Question Banks # ========================================== '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_results_for_assessment /assessments/questionBank: post: tags: - Assessment Question Banks summary: Create Question Bank requestBody: content: application/json: schema: $ref: "#/components/schemas/QuestionBankCreate" responses: "201": description: Question Bank created successfully content: application/json: schema: $ref: "#/components/schemas/QuestionBank" '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' operationId: create_question_bank /assessments/questionBanks: get: tags: - Assessment Question Banks summary: List Question Banks parameters: - in: query name: enabled schema: type: boolean description: Filter by enabled status - in: query name: label schema: type: string description: Search by label (partial match) - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query name: page schema: type: integer minimum: 1 description: Page number for pagination - in: query name: pageSize schema: type: integer enum: [10, 25, 50, 100, 250] description: Number of results per page - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/QuestionBank" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' description: List items do not include questions - use GET /assessments/questionBank/{id} for the full shape. operationId: list_question_banks /assessments/questionBank/{id}: get: tags: - Assessment Question Banks summary: Get Question Bank parameters: - in: path name: id schema: type: integer required: true description: Question Bank ID responses: "200": description: Successful Response content: application/json: schema: $ref: "#/components/schemas/QuestionBank" "404": description: Question Bank not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: get_question_bank patch: tags: - Assessment Question Banks summary: Update Question Bank parameters: - in: path name: id schema: type: integer required: true description: Question Bank ID requestBody: content: application/json: schema: $ref: "#/components/schemas/QuestionBankUpdate" responses: "200": description: Question Bank updated successfully content: application/json: schema: $ref: "#/components/schemas/QuestionBank" "404": description: Question Bank not found '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: update_question_bank delete: tags: - Assessment Question Banks summary: Delete Question Bank parameters: - in: path name: id schema: type: integer required: true description: Question Bank ID responses: "200": description: Question Bank deleted successfully content: application/json: schema: $ref: '#/components/schemas/Message' "404": description: Question Bank not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: delete_question_bank /assessments/questionBank/{id}/questions: get: tags: - Assessment Question Banks summary: List Questions in Question Bank parameters: - in: path name: id schema: type: integer required: true description: Question Bank ID - in: query name: timestampModifiedBefore schema: type: string format: date-time pattern: '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?$' example: "2023-01-12 15:30:00" description: "Filter to questions whose timestamp_modified (the question bank's modified timestamp, shared by all its questions) is before this datetime. Format: YYYY-MM-DD HH:MM:SS (date-only YYYY-MM-DD also accepted)." - in: query name: timestampModifiedAfter schema: type: string format: date-time pattern: '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?$' example: "2023-01-12 15:30:00" description: "Filter to questions whose timestamp_modified (the question bank's modified timestamp, shared by all its questions) is after this datetime. Format: YYYY-MM-DD HH:MM:SS (date-only YYYY-MM-DD also accepted)." - in: query name: page schema: type: integer minimum: 1 description: Page number for pagination - in: query name: pageSize schema: type: integer enum: [10, 25, 50, 100, 250] description: Number of results per page - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Question" "404": description: Question Bank not found '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: list_questions_in_question_bank post: tags: - Assessment Question Banks summary: Create Multiple Questions in Question Bank (Batch) parameters: - in: path name: id schema: type: integer required: true description: Question Bank ID requestBody: content: application/json: schema: type: object required: - questions properties: questions: type: array items: $ref: "#/components/schemas/QuestionCreate" responses: "201": description: Questions created successfully content: application/json: schema: type: object properties: message: type: string example: "5 questions created" question_ids: type: array items: type: integer "404": description: Question Bank not found '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_multiple_questions_in_question_bank_batch /assessments/questionBank/{id}/question: post: tags: - Assessment Question Banks summary: Create Single Question in Question Bank parameters: - in: path name: id schema: type: integer required: true description: Question Bank ID requestBody: content: application/json: schema: $ref: "#/components/schemas/QuestionCreate" responses: "201": description: Question created successfully content: application/json: schema: $ref: "#/components/schemas/Question" "404": description: Question Bank not found # ========================================== # Assessment Questions # ========================================== '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_single_question_in_question_bank /assessments/question: post: tags: - Assessment Questions summary: Create Question (Independent) description: Create a question with either assessment_id or question_bank_id (mutually exclusive, one required) requestBody: content: application/json: schema: $ref: "#/components/schemas/QuestionCreateIndependent" responses: "201": description: Question created successfully content: application/json: schema: $ref: "#/components/schemas/Question" "400": description: Neither assessment_id nor question_bank_id was supplied. content: application/json: schema: $ref: '#/components/schemas/ValidationError' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '422': $ref: '#/components/responses/UnprocessableEntity' operationId: create_question_independent /assessments/questions: get: tags: - Assessment Questions summary: List Questions description: List all questions (excludes orphaned questions with both IDs null) parameters: - in: query name: assessmentId schema: type: integer description: Filter by assessment ID - in: query name: questionBankId schema: type: integer description: Filter by question bank ID - in: query name: typeId schema: type: integer description: Filter by question type ID - in: query name: timestampModifiedBefore schema: type: string format: date-time pattern: '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?$' example: "2023-01-12 15:30:00" description: "Filter to questions whose timestamp_modified (the parent assessment / question bank's modified timestamp) is before this datetime. Format: YYYY-MM-DD HH:MM:SS (date-only YYYY-MM-DD also accepted)." - in: query name: timestampModifiedAfter schema: type: string format: date-time pattern: '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?$' example: "2023-01-12 15:30:00" description: "Filter to questions whose timestamp_modified (the parent assessment / question bank's modified timestamp) is after this datetime. Format: YYYY-MM-DD HH:MM:SS (date-only YYYY-MM-DD also accepted)." - in: query name: page schema: type: integer minimum: 1 description: Page number for pagination - in: query name: pageSize schema: type: integer enum: [10, 25, 50, 100, 250] description: Number of results per page - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Question" '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: list_questions /assessments/question/{id}: get: tags: - Assessment Questions summary: Get Question parameters: - in: path name: id schema: type: integer required: true description: Question ID responses: "200": description: Successful Response content: application/json: schema: $ref: "#/components/schemas/Question" "404": description: Question not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: get_question patch: tags: - Assessment Questions summary: Update Question description: Update question properties (cannot change assessment_id or question_bank_id) parameters: - in: path name: id schema: type: integer required: true description: Question ID requestBody: content: application/json: schema: $ref: "#/components/schemas/QuestionUpdate" responses: "200": description: Question updated successfully content: application/json: schema: $ref: "#/components/schemas/Question" "404": description: Question not found '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: update_question delete: tags: - Assessment Questions summary: Remove Question from Container description: Clears the active parent ID (question_bank_id or assessment_id), orphaning the question parameters: - in: path name: id schema: type: integer required: true description: Question ID responses: "200": description: Question removed from container successfully content: application/json: schema: $ref: '#/components/schemas/Message' "404": description: Question not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: remove_question_from_container /assessments/question/{id}/choices: get: tags: - Assessment Questions summary: List Question Choices parameters: - in: path name: id schema: type: integer required: true description: Question ID responses: "200": description: Successful Response content: application/json: schema: type: array items: $ref: "#/components/schemas/QuestionChoice" "404": description: Question not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: list_question_choices /assessments/question/{id}/choice: post: tags: - Assessment Questions summary: Create Question Choice parameters: - in: path name: id schema: type: integer required: true description: Question ID requestBody: content: application/json: schema: $ref: "#/components/schemas/QuestionChoiceCreate" responses: "201": description: Choice created successfully content: application/json: schema: $ref: "#/components/schemas/QuestionChoice" "404": description: Question not found '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_question_choice /assessments/question/{questionId}/choice/{choiceId}: patch: tags: - Assessment Questions summary: Update Question Choice parameters: - in: path name: questionId schema: type: integer required: true description: Question ID - in: path name: choiceId schema: type: integer required: true description: Choice ID requestBody: content: application/json: schema: $ref: "#/components/schemas/QuestionChoiceUpdate" responses: "200": description: Choice updated successfully content: application/json: schema: $ref: "#/components/schemas/QuestionChoice" "404": description: Question or Choice not found '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: update_question_choice delete: tags: - Assessment Questions summary: Delete Question Choice parameters: - in: path name: questionId schema: type: integer required: true description: Question ID - in: path name: choiceId schema: type: integer required: true description: Choice ID responses: "200": description: Choice deleted successfully content: application/json: schema: $ref: '#/components/schemas/Message' "404": description: Question or Choice not found '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: delete_question_choice /assessments/assessment/{id}/question: post: tags: - Assessments summary: Create Single Question in Assessment parameters: - in: path name: id schema: type: integer required: true description: Assessment ID requestBody: content: application/json: schema: $ref: "#/components/schemas/QuestionCreate" responses: "201": description: Question created successfully content: application/json: schema: $ref: "#/components/schemas/Question" "404": description: Assessment not found '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_single_question_in_assessment /assessments/assessment/{id}/questions: post: tags: - Assessments summary: Create Multiple Questions in Assessment (Batch) parameters: - in: path name: id schema: type: integer required: true description: Assessment ID requestBody: content: application/json: schema: type: object required: - questions properties: questions: type: array items: $ref: "#/components/schemas/QuestionCreate" responses: "201": description: Questions created successfully content: application/json: schema: type: object properties: message: type: string example: "5 questions created" question_ids: type: array items: type: integer "404": description: Assessment not found '422': $ref: '#/components/responses/UnprocessableEntity' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_multiple_questions_in_assessment_batch /reports/checklists: get: tags: - Reports summary: Get metrics on number of checklists started and completed description: |- Requires a date range (maximum 1 year), groupBy is optional.

For example `?groupBy=usergroup` will result in ``` { "18": { "group_title": "Usergroup A", "started_count": 42, "completed_count": 12 } } ``` Date ranges over one year are rejected with HTTP 200 and a body of {"errors": ["Max date range is one year"]}. parameters: - in: query name: groupBy schema: type: string example: user, usergroup, checklist enum: - user - usergroup - checklist - in: query name: startDate schema: type: string example: 2024-01-01 required: true - in: query name: endDate schema: type: string example: 2024-12-01 required: true responses: "200": description: Successful Response. content: application/json: schema: oneOf: - $ref: "#/components/schemas/ReportsChecklists" - $ref: "#/components/schemas/ReportsChecklistsGroupedByUser" - $ref: "#/components/schemas/ReportsChecklistsGroupedByUsergroup" - $ref: "#/components/schemas/ReportsChecklistsGroupedByChecklist" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: get_metrics_on_number_of_checklists_started_and_completed /reports/courses: get: tags: - Reports summary: Get metrics on number of courses started and completed description: |- Requires a date range (maximum 1 year), groupBy is optional.

For example `?groupBy=usergroup` will result in ``` { "18": { "group_title": "Usergroup A", "started_count": 42, "completed_count": 12 } } ``` Date ranges over one year are rejected with HTTP 200 and a body of {"errors": ["Max date range is one year"]}. parameters: - in: query name: groupBy schema: type: string example: user, usergroup, course enum: - user - usergroup - course - in: query name: startDate schema: type: string example: 2024-01-01 required: true - in: query name: endDate schema: type: string example: 2024-12-01 required: true responses: "200": description: Successful Response. content: application/json: schema: oneOf: - $ref: "#/components/schemas/ReportsCourses" - $ref: "#/components/schemas/ReportsCoursesGroupedByUser" - $ref: "#/components/schemas/ReportsCoursesGroupedByUsergroup" - $ref: "#/components/schemas/ReportsCoursesGroupedByCourse" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: get_metrics_on_number_of_courses_started_and_completed /reports/users: get: tags: - Reports summary: Get metrics on number of active users and user logins parameters: - in: query name: groupBy schema: type: string example: usergroup enum: - usergroup - in: query name: startDate schema: type: string example: 2024-01-01 required: true - in: query name: endDate schema: type: string example: 2024-12-01 required: true responses: "200": description: Successful Response. content: application/json: schema: oneOf: - $ref: "#/components/schemas/ReportsUsers" - $ref: "#/components/schemas/ReportsUsersGroupedByUsergroup" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' description: 'Date ranges over one year are rejected with HTTP 200 and a body of {"errors": ["Max date range is one year"]}.' operationId: get_metrics_on_number_of_active_users_and_user_logins /submitQuiz: post: tags: - Quizzes summary: Submit quiz answers requestBody: content: application/json: schema: type: object $ref: "#/components/schemas/QuizResponsePayload" responses: "200": description: Successful Response. content: application/json: schema: type: object properties: attempt: type: integer result: $ref: '#/components/schemas/QuizResult' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: submit_quiz_answers /subscription: post: tags: - Subscriptions summary: Create Subscription requestBody: content: application/json: schema: $ref: "#/components/schemas/Subscription" responses: '201': description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Subscription" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_subscription /subscription/{id}: get: tags: - Subscriptions summary: Read Subscription #TODO add parameters for updating user groups parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Subscription" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_subscription patch: tags: - Subscriptions summary: Edit Subscription #TODO add parameters for updating user groups parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/SubscriptionUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Subscription" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: edit_subscription delete: tags: - Subscriptions summary: Delete Subscription #TODO add parameters for updating user groups parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_subscription /subscriptions: get: tags: - Subscriptions summary: Read Subscriptions parameters: - in: query name: subscriptionIds schema: type: string - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: title required: false schema: type: string description: Filter by subscription title. Exact match unless % wildcards are included. responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Subscription" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_subscriptions /subscription/{id}/subscribe: post: tags: - Subscriptions summary: Subscribe User(s) to a Subscription Plan description: | Subscribe one or more existing users to a subscription plan. Users must already exist in the system. ## Free subscriptions (default) Omit the body entirely. `userIds` may contain one OR many ids — each user is subscribed to the plan in a single call. The plan must have `default_amount == 0.00`; otherwise the call returns 400. Each subscription is created with a covering period derived from the plan's configuration: `period_start`/`period_end` from the request body win when supplied; otherwise the period runs from now until now + the plan's `default_sub_length` (or until the plan's fixed-term end date). A plan with no configured length (or a lifetime fixed-term plan) yields an open-ended lifetime period. This period drives the subscription's timeframe on the LMS User Manager timeline and its expiration by the daily cron. ## Paid subscriptions (single-user only) When `gateway_transaction_id` is supplied in the request body, this endpoint records an externally-processed payment (e.g. Stripe `payment_intent_id`) alongside subscribing the user. This is the only way to register a user on a paid plan from this endpoint. **In paid mode, `userIds` MUST contain exactly one id.** Multi-user calls are rejected with 400 — one gateway transaction cannot be split across multiple subscribers, so each paid signup is its own request. For subsequent (renewal) payments on an existing subscription, use `POST /v1/user/{userId}/subscription/{subId}/payment` instead. Additional requirements when supplying `gateway_transaction_id`: - Caller must hold one of: `all`, `all:create`, `payments:all`, `payments:create` (in addition to the subscribe permissions). - `amount`, `paid_at`, and `currency` are required alongside `gateway_transaction_id`. - The subscription is created in `INAC` state and flipped to `ACT` only after the payment row commits successfully. The subscription save and the payment recording run in a single `tovuti_rds` transaction — if recording fails, the subscription is rolled back. - `gateway_transaction_id` must be globally unique across this tenant's `axs_pay_transactions.trxn_id`. parameters: - in: path name: id schema: type: integer required: true description: Subscription plan id. Must be numeric. requestBody: required: true description: | `userIds` is always required (as an **array**, even for a single user). When supplying `gateway_transaction_id` (paid flow), `userIds` must contain exactly one id and the four payment fields are also required. See `SubscribeRequest` for the full shape. content: application/json: schema: $ref: "#/components/schemas/SubscribeRequest" responses: "200": description: Successful Response. When paid, the body includes `subscription_id` and `payment_id`. content: application/json: schema: $ref: '#/components/schemas/SubscribeResult' "400": description: Validation failure (missing/empty `userIds`, plan is paid but no `gateway_transaction_id` supplied, `userIds` has more than one entry in paid mode, user already subscribed, `gateway_transaction_id` already used globally, etc.). "403": description: Forbidden — token lacks the required permissions. Paid mode additionally requires one of `payments:create`/`payments:all`/`all:create`/`all`. "404": description: Subscription plan not found. "409": description: "`gateway_transaction_id` already recorded against a different subscription or purchase type (paid mode only)." '401': $ref: '#/components/responses/Unauthorized' operationId: subscribe_user_s_to_a_subscription_plan /subscription/{id}/unsubscribe: post: tags: - Subscriptions summary: Unsubscribe User(s) from a Subscription Plan description: Only free subscriptions are supported at this time. parameters: - in: path name: id schema: type: integer required: true description: Subscription plan id. Must be numeric. requestBody: required: true description: | `userIds` is an array (always — even for a single user) of LMS user ids to unsubscribe. content: application/json: schema: type: object required: [userIds] properties: userIds: type: array minItems: 1 items: type: integer example: [1620265, 1620266] responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: unsubscribe_user_s_from_a_subscription_plan /survey/{id}: get: tags: - Surveys summary: Read Survey parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Survey" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_survey /surveys: get: tags: - Surveys summary: Read Surveys parameters: - in: query name: surveyIds schema: type: string description: Comma-separated list of survey IDs - in: query name: title schema: type: string description: Filter by title (supports LIKE matching) Exact match unless % wildcards are included. - in: query name: enabled schema: type: boolean description: Filter by enabled status - in: query name: createdBefore schema: type: string format: date description: Filter by surveys created before this date (YYYY-MM-DD) - in: query name: createdAfter schema: type: string format: date description: Filter by surveys created after this date (YYYY-MM-DD) - in: query name: modifiedBefore schema: type: string format: date description: Filter by surveys modified before this date (YYYY-MM-DD) - in: query name: modifiedAfter schema: type: string format: date description: Filter by surveys modified after this date (YYYY-MM-DD) - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: '#/components/parameters/pageParam' - in: query $ref: '#/components/parameters/pageSizeParam' - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Survey" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_surveys /surveyResponse: post: tags: - Surveys summary: Create Survey Response requestBody: content: application/json: schema: $ref: "#/components/schemas/SurveyResponse" responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SurveyResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' description: lesson_id and activity_id are required unless event_id is supplied; supplying event_id together with either returns 400. operationId: create_survey_response /surveyResponses: get: tags: - Surveys summary: Read Survey Responses parameters: - in: query name: userId schema: type: integer - in: query name: surveyId schema: type: integer - in: query name: lessonId schema: type: integer - in: query name: activityId schema: type: string - in: query name: eventId schema: type: integer - in: query name: questionId schema: type: string - in: query name: archived schema: type: boolean - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/SurveyResponse" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_survey_responses post: tags: - Surveys summary: Create Survey Responses requestBody: content: application/json: schema: type: object properties: responses: type: array items: $ref: "#/components/schemas/SurveyResponse" required: - responses responses: '201': description: Successful Response. content: application/json: schema: type: array items: $ref: '#/components/schemas/SurveyResponse' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' description: lesson_id and activity_id are required unless event_id is supplied; supplying event_id together with either returns 400. operationId: create_survey_responses /team: post: tags: - Teams summary: Create User Team requestBody: content: application/json: schema: $ref: "#/components/schemas/Team" responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Team' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_user_team /team/{id}: get: tags: - Teams summary: Read User Team parameters: - in: path name: id schema: type: integer required: true - in: query $ref: "#/components/parameters/excludeTeamParam" responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/Team' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_user_team patch: tags: - Teams summary: Update User Team parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/TeamUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/Team" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_user_team delete: tags: - Teams summary: Delete User Team parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_user_team /teams: get: tags: - Teams summary: Read User Teams parameters: - in: query $ref: "#/components/parameters/teamIdsParam" - in: query name: title schema: type: string description: Filter by title. Exact match unless % wildcards are included. - in: query name: memberType schema: type: string enum: [individuals, groups] example: individuals, groups - in: query name: createdBefore schema: type: string format: date - in: query name: createdAfter schema: type: string format: date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query $ref: "#/components/parameters/excludeTeamParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Team" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_user_teams /transactions: get: tags: - Transactions summary: Read Transactions parameters: - in: query name: id schema: type: integer - in: query name: axsTransactionId schema: type: integer - in: query name: productName schema: type: string - in: query name: productType schema: type: string - in: query name: transactorName schema: type: string - in: query name: transactorId schema: type: integer - in: query name: transactorType schema: type: string - in: query name: purchaserId schema: type: integer - in: query name: purchaserName schema: type: string - in: query name: payInstrumentName schema: type: string - in: query name: payInstrumentType schema: type: string enum: - credit card - invoice - purchase order - external description: "Filter by pay instrument type. Exact match on the type label." - in: query name: orderAmount schema: type: number - in: query name: exitStatus schema: type: string - in: query name: transactionType schema: type: string - in: query name: before schema: type: string format: date - in: query name: after schema: type: string format: date - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/Transaction" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_transactions /user: post: tags: - Users summary: Create User description: userTeamIds can only be assigned for teams with member_type = 'individuals'. requestBody: content: application/json: schema: $ref: "#/components/schemas/UserPayload" responses: '201': description: Successfully created users. content: application/json: schema: $ref: '#/components/schemas/User' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_user /user/{id}: get: tags: - Users summary: Read User parameters: - in: path name: id schema: type: integer required: true - in: query name: exclude description: > Comma-separated list of referenced datasets to omit from the response. All are included by default; excluding one both drops it from the payload and skips the query used to build it. Allowed values: `customFields`, `objects`, `enrolledCourseIds`, `userTeamIds`. Excluded custom field values can be fetched independently via GET /metadata/customFields/values?objectType=users; excluded objects via GET /objects; excluded enrollments via GET /user/{id}/courseProgress; excluded team membership via GET /teams. schema: type: string example: customFields,objects,enrolledCourseIds,userTeamIds responses: "200": description: Successfully created user content: application/json: schema: $ref: '#/components/schemas/User' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_user patch: tags: - Users summary: Update User description: UserTeamIds can only be assigned for teams with member_type = 'individuals'. parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: $ref: '#/components/schemas/UserPayloadUpdate' responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/User' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_user delete: tags: - Users summary: Delete User parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successfully deleted users. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_user /user/{id}/communityGroups: get: tags: - Users summary: Read User Community Groups parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/CommunityGroupIds" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_user_community_groups patch: tags: - Users summary: Update User Community Groups parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: allOf: - $ref: "#/components/schemas/CommunityGroupIds" required: - community_groups responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/CommunityGroupIds" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_user_community_groups /user/{id}/awards: get: tags: - Users summary: Read User's Earned Awards parameters: - in: path name: id schema: type: integer required: true - in: query $ref: "#/components/parameters/awardTitleParam" - in: query $ref: "#/components/parameters/awardTypeParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/AwardEarned" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_user_s_earned_awards /user/{userId}/award/{awardId}: patch: tags: - Users summary: Update a user's earned award parameters: - in: path name: userId schema: type: integer required: true - in: path name: awardId schema: type: integer required: true requestBody: content: application/json: schema: $ref: "#/components/schemas/AwardEarned" responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/AwardEarned' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' description: '{awardId} is the award-earned row id from GET /users/awards, not the award id. {userId} is existence-checked but does not scope the lookup.' operationId: update_a_user_s_earned_award /user/{id}/courseProgress: get: tags: - Users summary: Read User Course Progress parameters: - in: path name: id schema: type: integer required: true - in: query name: lessonId description: Filter by Lesson Id. schema: type: integer - in: query name: courseId description: Filter by Course Id. schema: type: integer - in: query name: archived description: If true, show only archived data. schema: type: boolean - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/UserCourseProgress" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_user_course_progress /user/{id}/subscriptions: get: tags: - Users summary: List User Subscriptions description: Retrieve a paginated list of subscriptions for a specific user. parameters: - in: path name: id schema: type: integer required: true description: The ID of the user. - in: query schema: type: integer name: planId description: Retrieve all subscriptions for this plan id - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/UserSubscription" "404": description: User not found. "500": description: Internal Server Error. '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: list_user_subscriptions /user/{id}/subscription/{subscriptionId}: get: tags: - Users summary: Get User Subscription Plan description: Retrieve the subscription plan details for a specified user and plan ID. parameters: - in: path name: id schema: type: integer required: true description: The ID of the user. - in: path name: subscriptionId schema: type: integer required: true description: The ID of the users subscription. responses: "200": description: Successful Response. content: application/json: schema: type: object properties: id: type: integer description: ID of the users subscription userId: type: integer description: The ID of the user. cancel_date: type: string description: The date the subscription was cancelled planId: type: integer description: The ID of the subscription plan. status: type: string description: Active or Inactive status next_payment_date: type: string description: The next date the user will be charged, if applicable. recurring_amount: type: string description: The amount the user will be charged on the next payment date, if applicable. period_length: type: string description: How often the subscription renews or ends for the user. "404": description: The user or subscription plan was not found. "500": description: Internal Server Error. '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: get_user_subscription_plan patch: tags: - Users summary: Update User Subscription Plan description: Update the subscription plan details for a specific user and plan ID. parameters: - in: path name: id schema: type: integer required: true description: The ID of the user. - in: path name: subscriptionId schema: type: integer required: true description: The ID of the subscription plan. requestBody: description: The fields to update for the subscription plan. required: true content: application/json: schema: type: object properties: next_payment_date: type: string format: date description: The updated start date for the subscription. responses: "200": description: Successfully updated the subscription plan. content: application/json: schema: type: object properties: success: type: boolean description: Status of the update operation. message: type: string description: Additional information about the update process. "400": description: Invalid request body or parameters. "404": description: User or subscription plan not found. "500": description: Internal Server Error. '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: update_user_subscription_plan /user/{userId}/subscription/{subId}/payment: post: tags: - Payments summary: Record Subscription Payment description: | Record a payment that was processed externally (e.g. via Stripe) against a user's subscription. Creates a row in `axs_pay_transactions` and the matching `hybrid_order` / `hybrid_order_item` / `hybrid_transaction` rows, then marks the subscription period `PAID`. Idempotent on `gateway_transaction_id`: replaying the same payload returns the existing record with `200` instead of `201`. A payload that collides with a different subscription's existing payment returns `409`. parameters: - in: path name: userId schema: type: integer required: true description: The ID of the LMS user. - in: path name: subId schema: type: integer required: true description: The subscription ID (axs_pay_subscriptions.id). requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SubscriptionPaymentCreate" responses: "201": description: Payment recorded. content: application/json: schema: $ref: "#/components/schemas/SubscriptionPayment" "200": description: Idempotent replay — the same `gateway_transaction_id` was already recorded for this user and subscription. content: application/json: schema: $ref: "#/components/schemas/SubscriptionPayment" "400": description: Validation failure (missing fields, `gateway_transaction_id` already used globally, etc). "403": description: Forbidden — token lacks `payments:create`. "404": description: Subscription not found for the given user. "409": description: "`gateway_transaction_id` already recorded against a different subscription or purchase type." "500": description: External pay instrument singleton not seeded in this client database. Run the LMS migration that adds `hybrid_pay_instrument_type` id=4 and the matching `hybrid_pay_instrument` row. '401': $ref: '#/components/responses/Unauthorized' operationId: record_subscription_payment /user/{userId}/subscription/{subId}/payments: get: tags: - Payments summary: List Subscription Payments description: | Return payments recorded against a user's subscription. Pass `gateway_transaction_id` to look up by the external gateway reference (Stripe payment_intent_id, etc.) — useful when the caller stored only the gateway id and needs to retrieve the Tovuti payment id for subsequent PATCH/DELETE calls. Includes voided (`status: PLHO`) payments; filter client-side if you only want successful ones. parameters: - in: path name: userId schema: type: integer required: true - in: path name: subId schema: type: integer required: true - in: query name: gatewayTransactionId schema: type: string description: Exact-match filter on the external gateway reference. Returns 0 or 1 result. example: pi_3O8aBcDeFgHiJk001 - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: type: object description: 'This endpoint builds its envelope by hand: only data, current_page, per_page, from and to are returned (plus total and last_page when includeTotal=true). No page URLs.' properties: data: type: array items: $ref: '#/components/schemas/SubscriptionPayment' current_page: type: integer per_page: type: integer from: type: integer nullable: true to: type: integer nullable: true total: type: integer nullable: true last_page: type: integer nullable: true "403": description: Forbidden — token lacks `payments:read`. "404": description: Subscription not found for the given user. '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' operationId: list_subscription_payments /user/{userId}/subscription/{subId}/payment/{id}: get: tags: - Payments summary: Read Subscription Payment parameters: - in: path name: userId schema: type: integer required: true - in: path name: subId schema: type: integer required: true - in: path name: id schema: type: integer required: true description: The `hybrid_transaction.id` returned by Create or List. responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/SubscriptionPayment" "400": description: Record exists but is not a subscription payment. "403": description: Forbidden — token lacks `payments:read`. "404": description: Payment not found, does not belong to the given user, or does not belong to the given subscription. '401': $ref: '#/components/responses/Unauthorized' operationId: read_subscription_payment patch: tags: - Payments summary: Correct Subscription Payment description: | Correct one or more fields on a recorded payment. All body fields are optional; only the fields supplied are updated. Only payments with status `SUC` can be corrected. To reverse a payment, use DELETE (void). parameters: - in: path name: userId schema: type: integer required: true - in: path name: subId schema: type: integer required: true - in: path name: id schema: type: integer required: true description: The `hybrid_transaction.id`. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/SubscriptionPaymentUpdate" responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/SubscriptionPayment" "400": description: Validation failure. "403": description: Forbidden — token lacks `payments:update`. "404": description: Payment not found. "409": description: Payment is voided or otherwise not in a correctable state. '401': $ref: '#/components/responses/Unauthorized' operationId: correct_subscription_payment delete: tags: - Payments summary: Void Subscription Payment description: | Void a payment. Soft-delete: rows remain. The payment status becomes `Voided` (`axs_pay_transactions.status = PLHO`), the `hybrid_order` / `hybrid_order_item` / `hybrid_transaction` rows are marked FAIL, and the subscription period reverts from `Paid` (`PAID`) to `Unpaid` (`NONE`). The new period status is visible on `GET /v1/user/{userId}/subscription/{subId}` in the `periods[]` array. A second DELETE on the same payment returns 409. parameters: - in: path name: userId schema: type: integer required: true - in: path name: subId schema: type: integer required: true - in: path name: id schema: type: integer required: true responses: "200": description: Payment voided. content: application/json: schema: $ref: "#/components/schemas/SubscriptionPayment" "403": description: Forbidden — token lacks `payments:delete`. "404": description: Payment not found. "409": description: Payment is already voided, or has been refunded and cannot be voided. '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' operationId: void_subscription_payment /users: get: tags: - Users summary: Read Users description: All parameters can be used in either the query or the request body. parameters: - in: query name: exclude description: > Comma-separated list of referenced datasets to omit from the response. All are included by default; excluding one both drops it from the payload and skips the query used to build it. Allowed values: `customFields`, `objects`, `enrolledCourseIds`, `userTeamIds`. Excluded custom field values can be fetched independently via GET /metadata/customFields/values?objectType=users; excluded objects via GET /objects; excluded enrollments via GET /user/{id}/courseProgress; excluded team membership via GET /teams. schema: type: string example: customFields,objects,enrolledCourseIds,userTeamIds - in: query $ref: "#/components/parameters/userIdsParam" - in: query name: name schema: type: string description: Search by user name. - in: query name: email schema: type: string description: Search by user email. - in: query name: status schema: type: string enum: - active - disabled description: Search by user status (active/disabled) status. - in: query $ref: "#/components/parameters/objectIdsParam" - in: query name: objectTitle schema: type: string description: Search Object Title associated to user. - in: query name: registeredBefore schema: type: string format: date - in: query name: registeredAfter schema: type: string format: date - in: query name: lastVisitedBefore schema: type: string format: date - in: query name: lastVisitedAfter schema: type: string format: date - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/teamIdsParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query $ref: "#/components/parameters/customFieldsParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/User" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_users /users/awards: get: tags: - Users summary: Read User Awards parameters: - in: query $ref: "#/components/parameters/userNameParam" - in: query $ref: "#/components/parameters/awardTitleParam" - in: query $ref: "#/components/parameters/awardTypeParam" - in: query $ref: "#/components/parameters/userIdsParam" - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/teamIdsParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/AwardEarned" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_user_awards /users/awards/{id}: delete: tags: - Users summary: Delete User Awards parameters: - in: path schema: type: integer name: id required: true responses: "200": description: Successful Response. content: application/json: schema: type: object example: {"success": "AwardEarned id = {$id} deleted"} '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' description: '{id} is the award-earned row id from GET /users/awards, not the award id.' operationId: delete_user_awards /users/checklistProgress: get: tags: - Users summary: Read User Checklist Progress parameters: - in: query $ref: "#/components/parameters/userNameParam" - in: query $ref: "#/components/parameters/userIdsParam" - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/teamIdsParam" - in: query name: archived description: If true, show only archived data. schema: type: boolean - in: query name: assignedBefore description: Include only records whose assigned_date is on or before this date (YYYY-MM-DD). schema: type: string format: date - in: query name: assignedAfter description: Include only records whose assigned_date is on or after this date (YYYY-MM-DD). schema: type: string format: date - in: query name: sortBy description: > Field to sort results by. `assigned_date` orders by the checklist's assigned date. `timestampModified` orders by the progress record's last-modified timestamp (the column the `timestampModifiedBefore` / `timestampModifiedAfter` filters compare against) with the record id as a tie-breaker, so results are stable when paging. Required whenever `sortDir` is supplied. schema: type: string enum: - assigned_date - timestampModified - in: query name: sortDir description: > Sort direction. The default depends on `sortBy`: `asc` for `assigned_date`, `desc` for `timestampModified`. Only valid together with `sortBy`; a request that sends `sortDir` on its own is rejected with HTTP 400. schema: type: string enum: - asc - desc - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/ChecklistProgress" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_user_checklist_progress /users/courseProgress: get: tags: - Users summary: Read Users Course Progress parameters: - in: query $ref: "#/components/parameters/courseTitleParam" - in: query $ref: "#/components/parameters/courseEnabledParam" - in: query $ref: "#/components/parameters/userNameParam" - in: query $ref: "#/components/parameters/userIdsParam" - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/teamIdsParam" - in: query name: archived description: If true, show only archived data. schema: type: boolean - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: startedBefore schema: type: string format: date - in: query name: startedAfter schema: type: string format: date - in: query name: lastActivityBefore schema: type: string - in: query name: lastActivityAfter schema: type: string - in: query name: completedBefore schema: type: string - in: query name: completedAfter schema: type: string responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/CourseProgress" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_users_course_progress /users/events: get: tags: - Users summary: Read User Event Registrations parameters: - in: query $ref: "#/components/parameters/userNameParam" - in: query $ref: "#/components/parameters/eventTitleParam" - in: query $ref: "#/components/parameters/userIdsParam" - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/teamIdsParam" - in: query $ref: "#/components/parameters/eventIdsParam" - in: query $ref: "#/components/parameters/timestampCreatedBeforeParam" - in: query $ref: "#/components/parameters/timestampCreatedAfterParam" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/EventRegistration" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_user_event_registrations /users/quizResults: get: deprecated: true tags: - Users summary: "Read Quiz Results - Deprecated, use /assessments/results instead" parameters: - in: query name: ids schema: type: string description: Comma separated list of ids for the quiz result. - in: query name: quizIds schema: type: string description: Comma separated list of quiz ids. - in: query $ref: "#/components/parameters/userNameParam" - in: query $ref: "#/components/parameters/userIdsParam" - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/teamIdsParam" - in: query name: archived description: If true, show only archived data. schema: type: boolean - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - in: query name: lessonId schema: type: integer - in: query name: submittedBefore schema: type: string - in: query name: submittedAfter schema: type: string - in: query name: timestampCreatedBefore schema: type: string format: date description: "Filter by timestamp_created before this date (YYYY-MM-DD)" - in: query name: timestampCreatedAfter schema: type: string format: date description: "Filter by timestamp_created after this date (YYYY-MM-DD)" - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" - in: query name: lessonTitle required: false schema: type: string description: Filter by lesson title. - in: query name: courseTitle required: false schema: type: string description: Filter by course title. responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/QuizResult" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_quiz_results_deprecated_use_assessments_results_instead /users/sendWelcomeEmail: post: tags: - Users summary: Send Welcome Emails description: > When sending the Welcome Email, a new system-generated password will be sent and, upon logging in, the user will be prompted to reset their password. parameters: - in: query name: userIds required: true schema: type: array items: type: integer example: [1620265, 1620266, 1620265] - in: query name: requirePasswordReset schema: type: boolean description: Defaults to true, if not explicitly set responses: "200": description: Successful Response. content: application/json: schema: type: object properties: status: type: string message: type: string users: type: array items: type: integer description: Ids of the users emailed. '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: send_welcome_emails_when_sending_the_welcome_email_a_new_system_generated_password_will_be_sent_and_upon_logging_in_the_user_will_be_prompted_to_reset_their_password /userGroup: post: tags: - User Groups summary: Create User Group requestBody: content: application/json: schema: allOf: - $ref: "#/components/schemas/UserGroup" required: - title - parent_id responses: '201': description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/UserGroup' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: create_user_group /userGroup/{id}: get: tags: - User Groups summary: Read User Group parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/UserGroup" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_user_group patch: tags: - User Groups summary: Update User Group parameters: - in: path name: id schema: type: integer required: true requestBody: content: application/json: schema: type: object $ref: "#/components/schemas/UserGroup" responses: "200": description: Successful Response. content: application/json: schema: $ref: "#/components/schemas/UserGroup" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: update_user_group delete: tags: - User Groups summary: Delete User Group description: "Delete a User Group via API.\n\nUser group ids 1, 2, 8, 20 and 32 are reserved and cannot be removed (403). Group id 8 is hidden from all user group endpoints." parameters: - in: path name: id schema: type: integer required: true responses: "200": description: Successful Response. content: application/json: schema: $ref: '#/components/schemas/SuccessMessage' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: delete_user_group /userGroup/{id}/users: get: tags: - User Groups summary: Read User Group's Users description: Returns a paginated list of users belonging to the given user group. parameters: - in: path name: id schema: type: integer required: true - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/User" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '404': $ref: '#/components/responses/NotFound' operationId: read_user_group_s_users /userGroups: get: tags: - User Groups summary: Read User Groups parameters: - in: query $ref: "#/components/parameters/groupIdsParam" - in: query $ref: "#/components/parameters/userIdsParam" - in: query name: title schema: type: string description: Search by title of the user group. Exact match unless % wildcards are included. - in: query name: lft schema: type: integer description: Start of the lft/rgt range. Required if rgt is present. - in: query name: rgt schema: type: integer description: End of the lft/rgt range. Required if lft is present. - in: query name: parentId schema: type: integer - in: query $ref: "#/components/parameters/sortByParam" - in: query $ref: "#/components/parameters/sortDirParam" - in: query $ref: "#/components/parameters/pageParam" - in: query $ref: "#/components/parameters/pageSizeParam" - in: query $ref: "#/components/parameters/includeTotalParam" - name: excludeUserIds in: query schema: type: boolean description: When true, omits the userIds array from the response to improve performance. - in: query $ref: "#/components/parameters/timestampModifiedBeforeParam" - in: query $ref: "#/components/parameters/timestampModifiedAfterParam" responses: "200": description: Successful Response. content: application/json: schema: allOf: - $ref: "#/components/schemas/PageData" - type: object properties: data: type: array items: $ref: "#/components/schemas/UserGroup" '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' operationId: read_user_groups components: parameters: timestampCreatedBeforeParam: name: timestampCreatedBefore in: query description: "Filter to records created before this datetime. Format: YYYY-MM-DD HH:MM:SS (date-only YYYY-MM-DD also accepted)." schema: type: string format: date-time pattern: '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?$' example: "2023-01-12 15:30:00" timestampCreatedAfterParam: name: timestampCreatedAfter in: query description: "Filter to records created after this datetime. Format: YYYY-MM-DD HH:MM:SS (date-only YYYY-MM-DD also accepted)." schema: type: string format: date-time pattern: '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?$' example: "2023-01-12 15:30:00" timestampModifiedBeforeParam: name: timestampModifiedBefore in: query description: "Filter to records last modified before this datetime. Format: YYYY-MM-DD HH:MM:SS (date-only YYYY-MM-DD also accepted). Compared inclusive of time against the raw timestamp value." schema: type: string pattern: '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?$' example: "2023-01-12 15:30:00" timestampModifiedAfterParam: name: timestampModifiedAfter in: query description: "Filter to records last modified after this datetime. Format: YYYY-MM-DD HH:MM:SS (date-only YYYY-MM-DD also accepted). Compared inclusive of time against the raw timestamp value." schema: type: string pattern: '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}:\d{2})?$' example: "2023-01-12 15:30:00" awardTitleParam: name: awardTitle in: query description: Award title. schema: type: string example: King of Sales awardTypeParam: name: awardType in: query description: Award type. schema: type: string example: certificate courseEnabledParam: name: courseEnabled in: query description: Course is enabled? (0 for false 1 for true). schema: type: integer example: 1 courseIdsParam: name: courseIds in: query description: Course Ids. schema: type: string example: 3,4,6 courseTitleParam: name: courseTitle in: query description: Course Title. schema: type: string example: Quantum gravity 101 customFieldsParam: name: customFields in: query style: deepObject explode: true description: | When querying Profile Fields you can use either field_id or title to specify the field value you want to query. % wildcard can be used in value key. Each entry requires value. Serialized as indexed brackets. For example: "https://api.tovuti.io/api/v1/users?customFields[0][field_id]=44&customFields[0][value]=73958" schema: type: array items: $ref: '#/components/schemas/CustomFieldFilter' eventIdsParam: name: eventIds in: query description: Comma separated list of event ids schema: type: string example: 1,2,3 eventTitleParam: name: eventTitle in: query description: Event title. schema: type: string example: The concept of art groupIdsParam: name: groupIds in: query description: Comma separated list of group ids. schema: type: string example: 8,50,51 objectIdsParam: name: objectIds in: query description: Comma separated list of object ids. schema: type: string example: 8,50,51 pageParam: name: page in: query description: Page number. example: 1 schema: type: integer minimum: 1 default: 1 pageSizeParam: name: pageSize in: query description: Page size, allowed values are 10,25,50,100,250. example: 50 schema: type: integer enum: - 10 - 25 - 50 - 100 - 250 default: 25 includeTotalParam: name: includeTotal in: query description: > When true, the response includes `total` (row count across all pages) and `last_page`. Off by default because computing the count adds an extra `COUNT(*)` query per request. example: true schema: type: boolean default: false sortByParam: name: sortBy in: query description: > Sort the result set by this field. Allowed value: `timestampModified`, which orders by the `timestamp_modified` value the endpoint returns on each record and breaks ties on the record's primary key, so results are stable when paging, and the `next_page_url` / `prev_page_url` links in the response carry `sortBy` and `sortDir` forward. Records whose `timestamp_modified` is null sort first under `asc` and last under `desc`. When `sortBy` is omitted the endpoint returns rows in its previous default order, which on most list endpoints is not guaranteed to be consistent from one page to the next. Required whenever `sortDir` is supplied. schema: type: string enum: - timestampModified example: timestampModified sortDirParam: name: sortDir in: query description: > Direction for `sortBy`: `asc` (oldest modification first) or `desc` (most recently modified first). Defaults to `desc`. Only valid together with `sortBy`; a request that sends `sortDir` on its own is rejected with HTTP 400. schema: type: string enum: - asc - desc default: desc example: desc excludeParam: name: exclude in: query description: > Comma-separated list of referenced datasets to omit from the response. All are included by default; excluding one both drops it from the payload and skips the query/computation used to build it. Allowed value: `customFields`. On the Events and Purchase Orders endpoints the response key it removes is spelled `custom_fields`; the parameter value is `customFields` on every endpoint that supports it. schema: type: string example: customFields excludeTeamParam: name: exclude in: query description: > Comma-separated list of referenced datasets to omit from the response. All are included by default; excluding one both drops it from the payload and skips the query used to build it. Allowed values: `assignable_learning_path_ids`, `assignable_media_item_ids`, `lead_user_groups`. schema: type: string example: assignable_learning_path_ids,assignable_media_item_ids,lead_user_groups teamIdsParam: name: teamIds in: query description: Comma separated list of team ids. schema: type: string example: 1,2,3 userIdsParam: name: userIds in: query description: Comma separated list of user ids. schema: type: string example: 1719918,1719907,1719901 userNameParam: name: userName in: query description: User name. schema: type: string example: Jack Sparrow responses: NotFound: description: Entity not found. content: application/json: schema: $ref: '#/components/schemas/NotFoundError' UnprocessableEntity: description: > Validation failure. Returned instead of 400 by endpoints whose request validation uses Laravel's default error format. content: application/json: schema: $ref: '#/components/schemas/UnprocessableEntityError' BadRequest: description: Validation failure. content: application/json: schema: $ref: '#/components/schemas/ValidationError' Unauthorized: description: Missing or invalid bearer token. content: application/json: schema: $ref: '#/components/schemas/Message' Forbidden: description: Token lacks the required permission. content: application/json: schema: $ref: '#/components/schemas/ForbiddenError' securitySchemes: sanctumToken: type: http scheme: bearer schemas: Assignment: type: object required: - title properties: id: type: integer readOnly: true example: 1 title: type: string type: type: string description: Set to 'recommended' for courses in this assignment to show up as recommended or 'assigned' for courses to show up as assigned. example: Assigned enum: - Assigned - Recommended - assigned - recommended assignment_type: type: string description: Set to 'courses' for courses or 'learningpaths' for learning paths. example: courses enum: - courses - learningpaths course_ids: type: array items: type: integer description: Required if assignment_type is "courses" learning_path_ids: type: array items: type: integer description: Required if assignment_type is "learningpaths" usergroups: type: array items: type: integer user_ids: type: array items: type: integer users: readOnly: true type: array items: type: object properties: id: type: integer example: 1620265 username: type: string example: johndoe email: type: string example: john@doe.com name: type: string example: John Doe free: type: boolean description: If true, the assignment is free. start_date: type: string format: date end_date: type: string format: date due_date: type: string format: date days_to_complete: type: integer minimum: 0 maximum: 2048 assignment_filter_type: type: string description: Filter type ( users or groups ). example: groups enum: - users - groups team_id: type: integer readOnly: true dynamic_due_dates_enabled: type: boolean description: Only works for Learning Path Assignments dynamic_due_date_number: type: integer description: Required if dynamic_due_dates_enabled is true dynamic_due_date_unit: type: string enum: - minute - hour - day - week - month - year example: '[minute, hour, day, month, year]' description: Required if dynamic_due_dates_enabled is true enroll_users_in_paths: type: boolean description: Only works for Learning Path Assignments. When true, users will be enrolled in the learning paths. Defaults to true if not specified. created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this assignment changed. description: type: string maxLength: 50 Audit: type: object properties: id: readOnly: true type: integer action: readOnly: true type: string date: readOnly: true type: string format: date user: readOnly: true type: object properties: id: type: integer example: 1620265 username: type: string example: johndoe email: type: string example: john@doe.com name: type: string example: John Doe ip_address: readOnly: true type: string audit_type_id: readOnly: true type: integer description: The id of the audit action type (see /audit/types). target_item_id: readOnly: true type: integer description: The ID of the record that was acted on, if there is one changes: readOnly: true type: array items: type: object properties: field_name: type: string before: type: string after: type: string supplemental_data: readOnly: true type: object description: Any additional info stored by the audit log for this action timestamp_modified: type: string format: date-time readOnly: true description: type: string readOnly: true AuditActionType: type: object properties: id: readOnly: true type: integer type: readOnly: true type: string AuthAudit: type: object properties: id: readOnly: true type: integer action: readOnly: true type: string date: readOnly: true type: string format: date user: readOnly: true type: object properties: id: type: integer example: 1620265 username: type: string example: johndoe email: type: string example: john@doe.com name: type: string example: John Doe timestamp_modified: type: string format: date-time readOnly: true Award: type: object required: - title - type properties: id: type: integer readOnly: true example: 1 title: type: string example: Badge of Awesomeness type: type: string description: Can be badge, certificate, or milestone. example: badge enum: - badge - certificate - milestone certificate_type: type: string enum: - internal - external default: internal description: External certificates have no requirements example: internal description: type: string example: This badge is awesome! maxLength: 50 enabled: type: boolean badge_hover: type: string example: Badge of Awesomeness share_award_page: type: boolean expiration_type: type: string description: Type of time period after which the certificate will expire. Possible values are "year", "month", "week", "day". example: year|month|week|day expiration_classification: type: string description: Type of award expiration. Possible values are "static", "dynamic", "none". example: static|dynamic|none expiration_date: type: string format: date description: Date of static award expiration example: '2024-01-01 16:08:08' expiration_amount: type: integer description: The number of [expiration_type]s that will need to pass before this award expires. requirement_type: type: string description: Set this to "assigned" to assign the certificate to a specific user or set of users, or set to "conditional" to only award the certificate after a specific set of requirements are met. example: conditional|assigned user_can_lose_badge: type: boolean description: If true if the user will be able to lose their award. certificate_id: type: integer description: The certificate template this award is associated with. Only used if type = 'certificate'. requirements_all: type: boolean description: Only needed when requirement_type is set to "conditional". Set this to true if all requirements must be met, or false if any subset of them can be met to award the certificate. user_list: type: array items: type: integer description: Array of user ids to assign the award to, only used when award type = "assigned". usergroup_actions: type: boolean description: If set to true, add the users who were awarded the certificate to usergroups. add_usergroups: type: array items: type: integer description: Array of user group ids to add award recipients to. remove_usergroups: type: array items: type: integer description: Array of user group ids to remove award recipients from. points_actions: type: boolean description: If set to true, points are awarded upon attainment of the award. points_category: type: integer description: Id of points category that points should be assigned under. points: type: integer description: The number of points to be awarded on certificate attainment. requirements: type: array items: $ref: "#/components/schemas/AwardRequirement" timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this award changed. created_by: type: integer readOnly: true created_on: type: string format: date-time readOnly: true AwardEarned: type: object properties: award_id: type: integer description: The primary key of the award_earned record. Important, this is NOT the ID of the award itself readOnly: true user_id: type: integer readOnly: true badge_id: type: integer description: The ID of the award. Can be used on the /award/{id} endpoint to pull more info. Works for badges, certificates, and milestones readOnly: true date_earned: type: string pattern: ^(\d{4})\-(0\d|1[012])\-(0\d|[12]\d|3[01])\s([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$ date_expires: type: string format: date readOnly: true award_title: type: string readOnly: true award_type: type: string readOnly: true user_name: type: string readOnly: true timestamp_modified: type: string format: date-time readOnly: true AwardRequirement: type: object properties: requirement_active: type: boolean description: Set this to true to enable the requirement, false to disable it. requirement_type: type: string description: One of "category", "course", "lesson", "usergroup", "accesslevel", "event", "quiz" or "checklist". example: course enum: - category - course - lesson - usergroup - accesslevel - event - quiz - checklist requirement_completion: type: string description: Defines whether any or all [requirement_type]s are required to be completed in order for this award to be assigned. example: any|all required_category: type: array items: type: integer description: An array of course category ids used when requirement_type = "category". required_course: type: array items: type: integer description: An array of course ids used when requirement_type = "course". required_lesson: type: array items: type: integer description: An array of lesson ids used when requirement_type = "lesson". usergroup: type: array items: type: integer description: An array of user group ids used when requirement_type = "usergroup". accesslevel: type: array items: type: integer description: An array of access level ids used when requirement_type = "accesslevel". required_event: type: array items: type: integer description: An array of event ids sed when requirement_type = "event". required_event_action: type: string description: Set this to "registered" or "checkin" when using the "event" requirement type. This will require the user to be either registered or checked in to whichever events are given as part of the requirement. example: registered|checkin required_quiz: type: array items: type: integer description: Quiz ids the requirement applies to. Used when requirement_type is quiz. required_checklist: type: array items: type: integer description: Checklist ids the requirement applies to. Used when requirement_type is checklist. required: - requirement_active - requirement_type - requirement_completion AwardSyncRequest: type: object properties: success: readOnly: true type: string award_id: type: integer user_id: type: integer Checklist: type: object properties: id: type: integer readOnly: true example: 1 title: type: string description: type: string enabled: type: boolean due_date: type: string format: date access_type: type: string example: none|access|user|list userlist: type: array items: type: integer usergroup: type: array items: type: integer accesslevel: type: array items: type: integer is_sequential: type: boolean items: type: array items: $ref: "#/components/schemas/ChecklistItem" show_tooltip: type: boolean due_date_type: type: string example: dynamic|fixed|none description: dynamic - Due date is Dynamically Based from the date that they first received any of the assigned user groups. (requires Access Restriction Type to be set as User Group), fixed - Set scheduled Due Date. none - No due date. checklist_due_dynamic_number: type: integer description: Number of [checklist_due_dynamic_unit]s until this checklist is due. example: 5 checklist_due_dynamic_unit: type: string example: day|week|month|year description: Unit of time used for 'dynamic' due date type. auto_translate: type: boolean language: type: string ordering: type: integer created_on: type: string format: date-time readOnly: true created_by: type: integer readOnly: true timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true params: type: string ChecklistItem: type: object properties: id: type: string example: 1634694593n29Uo7 readOnly: true type: type: string description: Describes on which event this checklist item will be considered completed. example: course_completion|lesson_completion|certificate_awarded|badge_awarded|event_registration|event_checkin|watched_video|milestone_awarded|custom icon: type: string example: lizicon-1-TEP-Connect-Icon-15 title: type: string instructions: type: string due_date_type: type: string example: dynamic|fixed|none description: Dynamic due date type is based on time passed since the user was assigned to the usergroup this checklist is assigned to. Fixed is an exact date. item_due_dynamic_number: type: string description: The number of [item_due_dynamic_unit] that describe the due date of this checklist item. Only used when due_date_type = dynamic. item_due_dynamic_unit: type: string example: day|week|month|year description: The unit of time used for [item_due_dynamic_number] Only used when due_date_type = dynamic. due_date: type: string format: date description: Only used when due_date_type = fixed. course_id: type: integer example: The id of the course for the course_completion item type. lesson_id: type: integer example: The id of the lesson for the lesson_completion item type. milestone_id: type: integer example: The id of the milestone for the milestone_awarded item type certificate_id: type: integer example: The id of the certificate for the certificate_awarded item type badge_id: type: integer example: The id of the badge for the badge_awarded item type event_id: type: integer example: The id of the event for the event_registration or event_checkin item types media_id: type: integer example: The id of the watched_video for the watched_video item type link: type: string completion_type: type: string example: auto|admin|user description: If set to 'auto', the checklist will complete when the course/lesson/certificate/badge/event/media is completed. If set to 'admin' only an admin user can mark this item complete. If set to 'user' any user can mark this item complete. points_category: type: integer example: 1 description: The id of the points category that points will be assigned to. points: type: integer description: The number of points awarded when this item is completed. required_for_completion: type: boolean description: If false the checklist item is not factored into the completion % for the list. group: type: integer description: The grouping of this checklist item. Items in the same group will have the same group number item_award: type: integer readOnly: true ChecklistProgress: type: object properties: user_id: type: integer readOnly: true checklist_id: type: integer readOnly: true item_id: type: string readOnly: true example: 1689003604CWilGr item_type: type: string readOnly: true completed: type: boolean readOnly: true date: type: string format: date readOnly: true due_date: type: string format: date readOnly: true archive_date: type: string format: date readOnly: true assigned_date: type: string format: date readOnly: true title: type: string readOnly: true type: type: string readOnly: true due_date_type: type: string readOnly: true completion_type: type: string readOnly: true enum: - auto - admin - user timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true user_name: type: string readOnly: true CommunityGroupPost: type: object properties: id: type: integer description: ID of the post, unique within its type. type: type: string enum: [post, discussion, announcement] community_group_id: type: integer user_id: type: integer description: ID of the user who authored the content. content_body: type: string description: Plain-text content. Mentions are rendered as the user's name and HTML is stripped. Discussions and announcements are the title and message separated by a blank line. destination_url: type: string format: uri description: Direct LMS link to the post. created_at: type: string description: When the item was created, in UTC (`YYYY-MM-DD HH:MM:SS`, one-second precision). example: "2026-09-01 14:30:00" CommunityGroupComment: type: object properties: id: type: integer type: type: string enum: [comment] post_id: type: integer post_type: type: string enum: [post, discussion, announcement] community_group_id: type: integer user_id: type: integer description: ID of the user who authored the comment. content_body: type: string description: Plain-text comment content. destination_url: type: string format: uri description: Direct LMS link to the parent post (comments have no permalink of their own). created_at: type: string description: When the item was created, in UTC (`YYYY-MM-DD HH:MM:SS`, one-second precision). example: "2026-09-01 14:35:00" CommunityGroup: type: object required: - name - published - enable_user_groups properties: id: type: integer readOnly: true name: type: string published: type: boolean enable_user_groups: type: boolean owner_id: type: integer readOnly: true description: type: string users: type: array items: type: integer user_groups: type: array items: type: integer created: type: string format: date-time readOnly: true CommunityGroupIds: type: object properties: community_groups: type: array items: type: integer Course: type: object required: - title - slug - coursescategory_id properties: id: type: integer readOnly: true title: type: string example: MyCourse slug: type: string description: Unique URI for use in Search Engine Friendly urls. pattern: "[a-z-]+" coursescategory_id: type: integer format: int64 description: Id of the course category this course belongs to. courses_sub_categories_ids: type: array items: type: integer description: Comma-separated list of course category ids that this course belongs to. description: type: string short_description: type: string readOnly: true image: type: string video_url: type: string featured_course: type: boolean price: type: number format: float available_to_purchase: type: boolean enabled: type: boolean registrants: readOnly: true type: array items: type: integer external_link: type: string format: url final_course_survey: nullable: true description: Set to null to remove the final course survey from the course. type: object properties: id: type: integer survey_title: type: string survey_instructions: type: string content_expires: type: boolean expiration_date: type: string format: date custom_id: type: string required_for_completion: type: boolean customFields: type: array description: When assigning customFields either a field_id or title can be provided. It is recommended to use the field_id in case there is a field name with a duplicate title. items: $ref: '#/components/schemas/CustomFieldFilter' lessons: type: number format: int readOnly: true description: The number of lessons in the course. ordering: type: number format: int readOnly: true description: Used when displaying multiple courses. view_access_type: type: string example: none description: 'Visibility Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access register_access_type: type: string example: none description: 'Registration Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access view_access_groups: type: array items: type: integer description: array of group ids. Required if view_access_type is user. view_access_users: type: array items: type: integer description: array of user ids. Required if view_access_type is list. view_access_levels: type: array items: type: integer description: array of access level ids. Required if view_access_type is access. register_access_groups: type: array items: type: integer description: array of group ids. Required if register_access_type is user. register_access_users: type: array items: type: integer description: array of user ids. Required if register_access_type is list. register_access_levels: type: array items: type: integer description: array of access level ids. Required if register_access_type is access. multilingual_overrides: type: object items: type: object description: 'An object with multilingual override data in the form { "fr": { "use": 1, "title": "French Title", ...} }. Overrides are only included if enabled (use = 1).' use_library_content: type: boolean description: Specifies if a SCORM (or bizlibrary) package is used for this course library_content_type: type: string description: Either 'bizlibrary' or 'scorm' bizlibrary_content_title: type: string bizlibrary_content_id: type: string scorm_id: type: integer scorm_title: type: string locked: type: integer use_due_date: type: boolean readOnly: true hard_due_date: type: boolean readOnly: true due_date_type: type: string readOnly: true description: static|dynamic example: static|dynamic due_static_date: type: string format: date readOnly: true due_dynamic_number: type: integer readOnly: true due_dynamic_unit: type: string readOnly: true description: minute|hour|day|week|month|year example: minute|hour|day|week|month|year open_date: type: string format: date readOnly: true close_date: type: string format: date readOnly: true visible_before_open: type: boolean readOnly: true visible_after_close: type: boolean readOnly: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this course changed, including related data such as lessons or assignments. course_sub_title: type: string readOnly: true ref_url: type: string readOnly: true pricing_modifiers: type: object readOnly: true created_on: type: string format: date-time readOnly: true modified_on: type: string format: date-time readOnly: true events: type: array readOnly: true items: type: object properties: id: type: integer title: type: string restrict_event_registrations: type: integer readOnly: true allow_to_regsister_all_events: type: integer readOnly: true description: 'Note: the misspelling is the actual field name returned by the API.' event_registration_limit: type: integer readOnly: true event_checkin_required: type: integer readOnly: true event_registration_required: type: integer readOnly: true CourseCategory: type: object required: - title - slug properties: id: type: integer readOnly: true title: type: string parent_id: type: integer description: The id of the parent course category. 0 for no parent. slug: type: string description: Unique URI for use in Search Engine Friendly urls. pattern: "[a-z-]+" enabled: type: boolean view_access_type: type: string example: none|list|user|access description: Visibility Permission Type. view_access_groups: type: array items: type: integer description: array of group ids. Required if view_access_type is user. view_access_users: type: array items: type: integer description: array of user ids. Required if view_access_type is list. view_access_levels: type: array items: type: integer description: array of access level ids. Required if view_access_type is access. multilingual_overrides: type: object items: type: object description: 'An object with multilingual override data in the form { "fr": { "use": 1, "title": "French Title", ...} } . Overrides are only included if enabled (use = 1).' timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this course category changed. CourseProgress: type: object properties: user_id: type: integer course_id: type: integer language: type: string example: en-GB lessons_completed_list: type: array items: type: integer lessons_total_list: type: array items: type: integer score: type: number progress: type: number format: float date_started: type: string format: date date_last_activity: type: string format: date date_completed: type: string format: date date_due: type: string format: date archive_date: type: string format: date status: type: string enum: - not started - in progress - complete description: Derived from date_started, date_completed, and progress fields. timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this course progress record changed, including related data. id: type: integer readOnly: true user_name: type: string readOnly: true course_title: type: string readOnly: true course_enabled: type: integer readOnly: true marked_complete: type: integer readOnly: true marked_complete_by: type: integer readOnly: true params: type: string LearningPathProgress: type: object properties: id: type: integer readOnly: true user_id: type: integer learning_path_id: type: integer items_total: type: integer readOnly: true description: >- Server-derived from the learning path's required-course count. Ignored if supplied in a request body. items_completed: type: integer minimum: 0 description: >- Must be between 0 and the learning path's item total (its required-course count), inclusive. progress: type: number format: float date_started: type: string format: date date_last_activity: type: string format: date date_completed: type: string format: date date_due: type: string format: date archive_date: type: string format: date timestamp_modified: type: string format: date-time readOnly: true CustomField: type: object description: Profile Fields are user defined fields that can be used in the user registration forms and/or subscription registration forms. properties: id: type: integer readOnly: true type: type: string example: "group|gender|birthdate|textarea|text|url|date|list|radio|checkbox|email|time" ordering: type: integer description: This column is used to define which group a custom field is in. For example a group with ordering = 1 would have fields in it with ordering = 2 or 3. Then another group could start at 4 with child fields with ordering id = 5 or 6. published: type: integer description: If a custom field is not published, it will not be available to be used in any registration or subscription forms. min: type: integer max: type: integer name: type: string tips: type: string visible: type: integer required: type: integer searchable: type: integer registration: type: integer options: type: array description: Options for select/radio style fields. items: type: string fieldcode: type: string description: Unique key used for field. params: type: string description: Params contains type-specific configuration for Profile Fields. Some options are alternate registration_text to use as the field label in the registration form, date range and format etc. example: {"registration_text": "", "display": "date", "readonly": "0", "maxrange": "1", "minrange": "1", "date_format": "1"} CustomFieldDefinition: type: object description: > A custom field definition. Custom fields carry extra structured data on courses, events, purchase orders and user objects (axs_custom_fields); rows with object_type `users` are user profile field definitions (joom_community_fields), returned by GET /metadata/customFields only when objectType=users is requested explicitly. `hide_field` is omitted on users rows - user profile fields have no such flag. properties: id: type: integer readOnly: true example: 44 name: type: string example: Cost Center type: type: string description: > Field type as stored by the LMS. On object_type `users` rows this is a user profile field type (see ProfileField.type); `group` rows are the section headers the LMS profile form uses - they are returned so that every field_id reported by GET /metadata/customFields/values?objectType=users resolves to a definition here, and they never carry values themselves. example: text object_type: type: string description: The kind of object this field can be attached to. enum: [courses, events, "purchase order", "user objects", users] example: courses enabled: type: boolean ordering: type: integer description: Display order within the object type. hide_field: type: boolean description: > LMS display flag. Not an authorization flag. Omitted on object_type `users` rows - user profile fields have no such flag. params: type: object description: > Type-specific configuration, stored by the LMS as a JSON string and returned decoded. Keys vary by field type. Omitted entirely when the field has no configuration, so absence carries no meaning beyond "nothing set". additionalProperties: true properties: options: type: array description: > The choices for select, list, radio and checkbox fields. The LMS stores these as a single newline-delimited string; the API returns them split and trimmed, with blank entries removed. Omitted when the field has no options, which is the normal case for types like text and country. items: type: string example: ["gah", "geh", "gee"] timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true CustomFieldValueDetail: type: object description: > A custom field value row (axs_custom_field_values) with its field definition nested. Returned by the standalone custom field value endpoints. The CustomFieldValueResponse schema is the trimmed shape embedded in course, event, object, purchase order and user payloads. properties: id: type: integer readOnly: true example: 1201 object_type: type: string enum: [courses, events, "purchase order", "user objects", users] example: courses object_id: type: integer description: > Id of the course, event, purchase order, user object or user this value belongs to, per object_type. Only unique within an object type. example: 91 field_id: type: integer description: > Retained alongside `field` so the row stays traceable when the definition has been deleted. For object_type `users` this references a user field definition (GET /metadata/customFields?objectType=users); for every other object_type it references a metadata custom field (GET /metadata/customFields) - the two are numbered independently. example: 44 value: type: string example: "73958" field: type: object nullable: true description: The field definition this value belongs to. Null when the definition has been deleted. properties: id: type: integer example: 44 name: type: string example: Cost Center type: type: string example: text enabled: type: boolean timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true Event: type: object required: - title - event_date - alias properties: id: type: integer readOnly: true example: 1 parent_id: description: When creating a recurring event several 'child' events are created, each with a date and title based on the recurring settings and the title of the parent event. If an event has parent_id = 0 then it is a parent and may or may not have children. type: integer category_id: type: integer secondary_category_ids: type: array items: type: integer description: IDs of secondary categories assigned to this event. readOnly: true location_id: type: integer title: type: string example: My Event registration_type: type: integer example: 0 description: 0 - Both Individual and Group Registration, 1 - Only Individual Registration, 2 - Only Group Registration, 3 - Disable Registration. view_access: type: array items: type: integer description: ids of the groups that can view this course. example: [1] registration_access: type: array items: type: integer description: ids of the groups that can register for this course. example: [1] event_date: type: string example: '2026-08-29 12:00:00' description: Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. event_end_date: type: string example: '2026-08-29 12:00:00' description: Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. short_description: type: string description: type: string individual_price: type: number format: float event_capacity: type: integer created_by: type: integer description: User id. example: 1620265 readOnly: true cut_off_date: type: string description: Registration end date. Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. example: '2026-08-29 12:00:00' published: type: boolean featured: type: boolean registration_start_date: type: string description: Registration start date. Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. example: '2026-08-29 12:00:00' alias: type: string description: Unique URI for use in Search Engine Friendly urls pattern: '[a-z-]+' example: my-event language: type: string enable_auto_reminder: type: boolean description: If set to 'true' registrants will get auto reminder emails for this event. image: type: string readOnly: true timezone: type: string virtual_classroom_id: type: string example: B0C4D939-AF12-43D8-82B3-0A68D423F894 readOnly: true virtual_classroom_uri: type: string description: uri of virtual classroom that can be used for linking directly to virtual classroom readOnly: true request_register: type: boolean readOnly: true request_team: type: boolean readOnly: true request_instructor: type: boolean readOnly: true instructor_ids: type: array readOnly: true items: type: integer allow_to_cancel: type: boolean readOnly: true cancel_before_date: type: string format: date nullable: true description: Only present when allow_to_cancel is true. readOnly: true registration_count: type: integer readOnly: true description: Total number of registrants for this event. checked_in_count: type: integer readOnly: true description: Total number of checked-in registrants for this event. waitlist_count: type: integer readOnly: true description: Total number of waitlisted registrants for this event. sub_capacities: type: array readOnly: true items: $ref: "#/components/schemas/EventSubCapacity" custom_fields: type: array readOnly: true items: $ref: '#/components/schemas/CustomFieldValueResponse' timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this event changed, including related data such as registrations. EventSubCapacity: type: object properties: id: type: integer readOnly: true example: 1 event_id: type: integer example: 100 usergroup_ids: type: array items: type: integer capacity: type: integer example: 50 EventWithImage: type: object required: - title - event_date - alias properties: id: type: integer readOnly: true example: 1 parent_id: description: When creating a recurring event several 'child' events are created, each with a date and title based on the recurring settings and the title of the parent event. If an event has parent_id = 0 then it is a parent and may or may not have children. type: integer category_id: type: integer secondary_category_ids: type: array items: type: integer description: IDs of secondary categories assigned to this event. readOnly: true location_id: type: integer title: type: string example: My Event registration_type: type: integer example: 0 description: 0 - Both Individual and Group Registration, 1 - Only Individual Registration, 2 - Only Group Registration, 3 - Disable Registration. view_access: type: array items: type: integer description: ids of the groups that can view this course. registration_access: type: array items: type: integer description: ids of the groups that can register for this course. event_date: type: string example: '2026-08-29 12:00:00' description: Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. event_end_date: type: string example: '2026-08-29 12:00:00' description: Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. short_description: type: string description: type: string individual_price: type: number format: float event_capacity: type: integer created_by: type: integer description: User id. example: 1620265 readOnly: true cut_off_date: type: string description: Registration end date. Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. example: '2026-08-29 12:00:00' published: type: boolean featured: type: boolean registration_start_date: type: string description: Registration start date. Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. example: '2026-08-29 12:00:00' alias: type: string description: Unique URI for use in Search Engine Friendly urls. pattern: "[a-z-]+" language: type: string enable_auto_reminder: type: boolean description: If set to 'true' registrants will get auto reminder emails for this event. image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. Maximum size 10MB. timezone: type: string example: America/New_York EventRegistration: type: object properties: id: type: integer description: > Registration id - the unique key for this record. (user_id, event_id) is not unique: a user can hold more than one registration for the same event (for example a cancelled registration followed by a new one, or a waitlist entry), and a group booking has a billing row plus one row per member. event_id: type: integer user_id: type: integer group_id: type: integer description: > For a member of a group booking, the id of the group's billing registration; 0 for individual registrations and billing rows. first_name: type: string last_name: type: string organization: type: string address: type: string address2: type: string city: type: string state: type: string country: type: string zip: type: string phone: type: string fax: type: string email: type: string number_registrants: type: integer total_amount: type: number discount_amount: type: number amount: type: number register_date: type: string format: date payment_date: type: string format: date payment_method: type: string transaction_id: type: string axs_trxn_id: type: integer comment: type: string published: type: boolean is_request: type: integer cart_id: type: integer payment_processing_fee: type: number late_fee: type: number notified: type: boolean checked_in: type: boolean coupon_usage_calculated: type: boolean checked_in_count: type: integer deposit_amount: type: number payment_status: type: integer coupon_id: type: integer check_coupon: type: boolean tax_amount: type: number registration_code: type: string params: type: object is_reminder_sent: type: boolean is_deposit_payment_reminder_sent: type: boolean process_deposit_payment: type: boolean deposit_payment_transaction_id: type: integer deposit_payment_axs_trxn_id: type: integer user_ip: type: string deposit_payment_method: type: integer is_group_billing: type: boolean language: type: string invoice_number: type: integer cancel_date: type: string format: date original_event_id: type: integer currency_code: type: string nullable: true base_currency: type: string nullable: true exchange_rate: type: number nullable: true base_amount: type: number nullable: true subcapacity_id: type: integer nullable: true course_id: type: integer nullable: true created_on: type: string format: date-time created_by: type: integer modified_on: type: string format: date-time modified_by: type: integer ordering: type: integer timestamp_created: type: string format: date-time timestamp_modified: type: string format: date-time user_name: type: string event_title: type: string status: type: string enum: - Pending - Registered - Cancelled - Waitlist - Unknown waitlist_order: type: array items: type: integer description: Ordered list of user IDs on the waitlist for this event Transaction: type: object properties: id: type: integer axs_transaction_id: type: integer transaction_number: type: string is_partial_order: type: boolean type: type: string pay_instrument: type: object properties: id: type: integer nullable: true description: >- ID of the LMS record this pay instrument references; which record that is depends on `type` (credit card → saved card record, invoice → invoice, purchase order → purchase order). Interpret it together with `type`. Always `null` when `type` is `external`. name: type: string type: type: string enum: - credit card - invoice - purchase order - external description: Only returned when the relation is explicitly loaded; GET /transactions does not return it. amount_in_base_currency: type: number base_currency: type: string exit_status: type: string transaction_amount: type: number transaction_currency: type: string transactor: type: object properties: id: type: integer username: type: string name: type: string description: Only returned when the relation is explicitly loaded; GET /transactions does not return it. transactor_type: type: string order: $ref: "#/components/schemas/Order" timestamp_created: type: string timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this transaction changed. Order: type: object properties: id: type: integer amount: type: number purchaser: type: object properties: id: type: integer username: type: string name: type: string description: Only returned when the relation is explicitly loaded; GET /transactions does not return it. item_count: type: integer status: type: string enum: - fulfilled - refunded - transaction fail - pending items: type: array items: $ref: "#/components/schemas/OrderItem" OrderItem: type: object properties: id: type: integer product: $ref: "#/components/schemas/Product" status: type: string total_amount_before_discount: type: number total_amount_with_discount: type: number fees: type: number total_amount: type: number quantity: type: integer discounts: type: array items: $ref: "#/components/schemas/OrderItemDiscount" OrderItemDiscount: type: object properties: order_item_id: type: integer sequence_number: type: integer amount_before_discount: type: number amount_with_discount: type: number discount: $ref: "#/components/schemas/Discount" Product: type: object properties: id: type: integer name: type: string type: type: string lms_product_id: type: integer price: type: number recurring_price: type: number fixed_group_price: type: number late_fee: type: number Discount: type: object properties: id: type: integer name: type: string type: type: string enum: - promo code - pricing modifier - event coupon - event discount - event early bird lms_discount_id: type: integer is_active: type: boolean LearningPath: type: object required: - title properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean description: type: string courses: type: array items: type: integer course_details: type: array readOnly: true items: type: object properties: id: type: integer title: type: string ordering: type: integer optional_courses: type: array items: type: integer optional_course_details: type: array readOnly: true items: type: object properties: id: type: integer title: type: string ordering: type: integer subcategories: type: array items: type: integer tags: type: array items: type: integer view_access_type: type: string example: none description: 'Visibility Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access register_access_type: type: string example: none description: 'Registration Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access view_access_groups: type: array items: type: integer description: array of group ids. Required if view_access_type is user. view_access_users: type: array items: type: integer description: array of user ids. Required if view_access_type is list. view_access_levels: type: array items: type: integer description: array of access level ids. Required if view_access_type is access. register_access_groups: type: array items: type: integer description: array of group ids. Required if register_access_type is user. register_access_users: type: array items: type: integer description: array of user ids. Required if register_access_type is list. register_access_levels: type: array items: type: integer description: array of access level ids. Required if register_access_type is access. created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path changed, including related data such as courses or subcategories. image: type: string readOnly: true LearningPathWithImage: type: object required: - title properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean description: type: string courses: type: array items: type: integer subcategories: type: array items: type: integer tags: type: array items: type: integer image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. Maximum size 10MB. view_access_type: type: string example: none|list|user|access description: Visibility Permission Type. register_access_type: type: string example: none|list|user|access description: Registration Permission Type. view_access_groups: type: array items: type: integer description: array of group ids. Required if view_access_type is user. view_access_users: type: array items: type: integer description: array of user ids. Required if view_access_type is list. view_access_levels: type: array items: type: integer description: array of access level ids. Required if view_access_type is access. register_access_groups: type: array items: type: integer description: array of group ids. Required if register_access_type is user. register_access_users: type: array items: type: integer description: array of user ids. Required if register_access_type is list. register_access_levels: type: array items: type: integer description: array of access level ids. Required if register_access_type is access. created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path changed, including related data such as courses or subcategories. optional_courses: type: array items: type: integer description: Ids of optional (non-required) courses in the learning path. LearningPathCategory: type: object required: - title properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean subcategories: type: array items: type: integer subcategory_details: type: array readOnly: true items: type: object properties: id: type: integer title: type: string ordering: type: integer created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path category changed, including related data such as subcategories. access_type: type: string example: none enum: - none - access - user - list description: 'Note: "list" targets specific users and "user" targets user groups.' userlist: type: array items: type: integer usergroup: type: array items: type: integer accesslevel: type: array items: type: integer LearningPathSubcategory: type: object required: - title properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean description: type: string categories: type: array items: type: integer learning_paths: type: array items: type: integer learning_path_details: type: array readOnly: true items: type: object properties: id: type: integer title: type: string ordering: type: integer created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path subcategory changed, including related data such as learning paths. access_type: type: string example: none enum: - none - access - user - list description: 'Note: "list" targets specific users and "user" targets user groups.' userlist: type: array items: type: integer usergroup: type: array items: type: integer accesslevel: type: array items: type: integer image: type: string readOnly: true LearningPathSubcategoryWithImage: type: object required: - title properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean description: type: string categories: type: array items: type: integer image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. Maximum size 10MB. learning_paths: type: array items: type: integer created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path subcategory changed, including related data such as learning paths. access_type: type: string example: none|access|user|list userlist: type: array items: type: integer usergroup: type: array items: type: integer accesslevel: type: array items: type: integer Lesson: type: object properties: lesson_id: type: integer title: type: string description: Title of Lesson. example: Introduction to Quantum Physics image: type: string description: Image URL. example: http://example.com/image.jpg description: type: string description: Lesson description. example: Lesson description text lesson_type: type: integer description: Lesson Type. example: 0 - Public, 1 - Access Only language: type: string description: Language code. example: en-GB|pt-BR lesson_gating: type: integer description: Lesson Gating Status, read only, 1 if enabled, 0 if disabled. published: type: boolean description: Lesson publish status. example: true|false quiz_prerequisite_setting: type: integer description: Unlock after quiz. example: true|false award_points: type: integer description: Number of Award points. example: 10000 prerequisite_quizzes: type: array items: type: object example: [{"quiz_id": 1, "lesson_quiz": 10}] teacher: type: object description: Simplified teacher object. $ref: "#/components/schemas/Teacher" teachers: type: array readOnly: true items: type: object $ref: "#/components/schemas/Teacher" teacher_ids: type: array writeOnly: true items: type: integer description: List of teachers for this lesson, use the id of the teacher not the user course: type: object properties: course_id: type: integer title: type: string ordering: type: integer activities: type: array items: type: object readOnly: true created_on: type: string format: style ordering: type: integer is_final_course_survey: type: boolean use_library_content: type: boolean description: Specifies if a SCORM (or bizlibrary) package is used for this course library_content_type: type: string description: Either 'bizlibrary' or 'scorm' bizlibrary_content_title: type: string bizlibrary_content_id: type: string scorm_required: type: boolean scorm_id: type: integer scorm_title: type: string timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this lesson changed, including related data such as activities or quizzes. LessonInsert: type: object required: - title properties: title: type: string description: Title of Lesson. example: Introduction to Quantum Physics image: type: string description: Image URL. example: http://example.com/image.jpg description: type: string description: Lesson description. example: Lesson description text lesson_type: type: integer description: Lesson Type. example: 0 - Public, 1 - Access Only language: type: string description: Language code. example: en-GB|pt-BR published: type: boolean description: Lesson publish status. example: true|false quiz_prerequisite_setting: type: boolean description: Unlock after quiz. example: true|false award_points: type: integer description: Number of Award points. example: 10000 prerequisite_quizzes: type: array example: [1, 2, 4] items: type: integer teacher_id: type: integer description: Teacher ID. deprecated: true teacher_ids: type: array items: type: integer description: Teacher IDs. course_id: type: integer description: Course ID. Location: type: object properties: id: type: integer name: type: string example: Tovuti Headquarters address: type: string example: 775 S Rivershore Ln \#120, Eagle, ID 83616, USA city: type: string example: Eagle state: type: string example: Idaho zip: type: string example: 83616 country: type: string example: United States lat: type: number format: float example: 43.687440 description: Latitude. long: type: number format: float example: -116.354894 description: Longitude. published: type: boolean example: true user_id: type: integer description: User that created the location. language: type: string example: en-GB description: "Language code for the location. '*' is returned as 'All'." layout: type: string description: Possible values are '', table, timeline. timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true EventCategory: type: object properties: id: type: integer readOnly: true parent_id: type: integer description: Parent category ID name: type: string description: type: string published: type: boolean timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true MediaCategory: type: object required: - title - published - access_type properties: id: type: integer readOnly: true example: 2 parent_id: type: integer example: 5 description: id of the parent media category. title: type: string maxLength: 255 example: My Category page_title: type: string maxLength: 255 example: text description: type: string maxLength: 4000 example: This is descriptive text published: type: boolean example: true access_type: type: string example: none enum: - none - list - user - access description: 'Note: "list" targets specific users and "user" targets user groups.' usergroup: type: array items: type: integer description: array of group ids. userlist: type: array items: type: integer description: array of user ids. accesslevel: type: array items: type: integer description: array of access level ids. MediaItem: type: object required: - title - published - media_type - access_type properties: id: type: integer readOnly: true example: 2 title: type: string maxLength: 255 example: My Video speaker: type: string maxLength: 255 example: Jim Bob description: type: string maxLength: 4000 example: This is descriptive text published: type: boolean example: true go_live_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). archive_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). use_expiration: type: boolean example: false custom_id: type: string example: ABC123 expiration_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). category: type: integer example: 5 subcategory: type: integer example: 6 media_type: type: string example: video enum: - video - audio - pdf - link video_type: type: string example: mp4 description: Required if media_type is video. enum: - mp4 - youtube - screencast - facebook - vimeo source: type: string format: binary description: audio file, video file, or pdf. Required if media_type is video, audio, or PDF. thumbnail_image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. cover_image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. youtube_id: type: string example: DOWDNBu9DkU description: ID of youtube video or full url. Required if video_type is youtube. screencast_id: type: string example: DOWDNBu9DkU description: Required if video_type is screencast. facebook_url: type: string example: DOWDNBu9DkU description: Required if video_type is facebook. vimeo_id: type: string example: DOWDNBu9DkU description: ID of vimeo video or full url. Required if video_type is vimeo. interactive_source: type: string example: http://something.com description: must be a full URL. Required if media_type is link. access_type: type: string example: none description: 'Visibility Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access access_purchase_type: type: string example: none description: 'Access Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access usergroup: type: array items: type: integer description: array of group ids. Required if access_type is user. userlist: type: array items: type: integer description: array of user ids. Required if access_type is list. accesslevel: type: array items: type: integer description: array of access level ids. Required if access_type is access. usergroup_purchase_register: type: array items: type: integer description: array of group ids. Required if access_purchase_type is user. userlist_purchase_register: type: array items: type: integer description: array of user ids. Required if access_purchase_type is list. accesslevel_purchase_register: type: array items: type: integer description: array of access level ids. Required if access_purchase_type is access. tags: type: array items: type: string created_on: type: string format: date example: YYYY-mm-dd MediaItemNoData: type: object required: - title - published - media_type - access_type properties: id: type: integer readOnly: true example: 2 title: type: string maxLength: 255 example: My Video speaker: type: string maxLength: 255 example: Jim Bob description: type: string maxLength: 4000 example: This is descriptive text published: type: boolean example: true go_live_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). archive_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). use_expiration: type: boolean example: false custom_id: type: string example: ABC123 expiration_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). category: type: integer example: 5 subcategory: type: integer example: 6 media_type: type: string example: video enum: - video - audio - pdf - link video_type: type: string example: mp4 description: Required if media_type is video. enum: - mp4 - youtube - screencast - facebook - vimeo youtube_id: type: string example: DOWDNBu9DkU description: ID of youtube video or full url. Required if video_type is youtube. screencast_id: type: string example: JnD7uBZDI0Z description: Required if video_type is screencast. facebook_url: type: string example: https://facebook.com/johnd description: Required if video_type is facebook. vimeo_id: type: string example: https://vimeo.com/johndoe description: ID of vimeo video or full url. Required if video_type is vimeo. interactive_source: type: string example: http://interactivesource.com description: must be a full URL. Required if media_type is link. access_type: type: string example: none description: 'Visibility Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access access_purchase_type: type: string example: none description: 'Access Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access usergroup: type: array items: type: integer description: array of group ids. Required if access_type is user. userlist: type: array items: type: integer description: array of user ids. Required if access_type is list. accesslevel: type: array items: type: integer description: array of access level ids. Required if access_type is access. usergroup_purchase_register: type: array items: type: integer description: array of group ids. Required if access_purchase_type is user. userlist_purchase_register: type: array items: type: integer description: array of user ids. Required if access_purchase_type is list. accesslevel_purchase_register: type: array items: type: integer description: array of access level ids. Required if access_purchase_type is access. tags: type: array items: type: string Meeting: type: object required: - meetingName - meetingType - date - timezone properties: id: type: integer readOnly: true meetingId: type: string example: 2391AFB0-0893-4850-9208-D7505685BE1F readOnly: true meetingName: type: string meetingType: type: string example: tovuti enum: - tovuti - zoom - webex - gotomeeting - google - joinme - other creator: type: integer readOnly: true maxParticipants: type: integer description: Maximum number of participants (0-999999). minimum: 0 maximum: 999999 description: type: string date: type: string format: datetime timezone: type: string example: "America/New_York" access_type: type: string example: none enum: - none - access - user - list description: 'Note: "list" targets specific users and "user" targets user groups.' hosts: type: array items: type: integer externalUrl: type: string format: url moderatorPW: type: string readOnly: true attendeePW: type: string readOnly: true record: type: boolean description: If set to true, the meeting will be recorded. duration: type: integer enabled: type: boolean userlist: type: array items: type: integer description: An array of user ids with access. Required access_type = 'users'. accesslevel: type: array items: type: integer description: An array of access level ids with access. Required access_type = 'accesslevel'. usergroup: type: array items: type: integer description: An array of usergroup ids with access. Required access_type = 'groups'. attendees: type: array items: type: integer description: User ids of attendees for this meeting. readOnly: true created: type: string format: date-time readOnly: true Object: type: object properties: id: type: integer readOnly: true example: 2 title: type: string example: MyOrganization type_id: type: integer example: id of ObjectType user_portal: type: integer description: id of user portal for user portal override setting. description: type: string enabled: type: boolean image: type: string customFields: type: array description: When assigning customFields either a field_id or title can be provided. It is recommended to use the field_id in case there is a field name with a duplicate title. items: $ref: "#/components/schemas/CustomFieldFilter" timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true ObjectType: type: object properties: id: type: integer readOnly: true example: 2 title: type: string example: Organization enabled: type: boolean example: true ObjectsValue: type: object properties: id: type: integer title: type: string PageData: type: object description: > Pagination envelope. The `first_page_url`, `next_page_url` and `prev_page_url` links preserve the request's `pageSize`, `includeTotal`, `sortBy` and `sortDir` parameters, so following them keeps the same page size and sort order. properties: current_page: type: integer description: The current page. example: 1 from: type: integer description: The start of the range for the page. example: 1 nullable: true to: type: integer description: The end of the range for the page. example: 25 nullable: true per_page: type: integer description: The number of items per page. example: 10 first_page_url: type: string description: A URI to the first page. format: url example: http://{domain}/api/{endpoint}?page=1 next_page_url: type: string description: A URI to the next page. format: url example: http://{domain}/api/{endpoint}?page=1 nullable: true prev_page_url: type: string description: A URI to the previous page. format: url example: http://{domain}/api/endpoint}?page=1 nullable: true total: type: integer description: Total row count across all pages. Present only when `includeTotal=true` was passed. example: 142 last_page: type: integer description: Last page number. Present only when `includeTotal=true` was passed. example: 6 path: type: string description: Base URL of the paginated endpoint. last_page_url: type: string nullable: true description: Only returned by endpoints that serialize the paginator directly, and only when includeTotal=true. links: type: array items: type: object description: Only returned by endpoints that serialize the paginator directly, and only when includeTotal=true. ProfileField: type: object required: - type - enabled - name - visibility - required - searchable - registration - readonly - group_id properties: id: type: integer readOnly: true example: 10 type: type: string enum: [text, textarea, select, list, radio, checkbox, country, gender, email, time, date, url, birthdate] example: '[text, textarea, select, list, radio, checkbox, country, gender, email, time, date, url, birthdate]' ordering: type: integer readOnly: true enabled: type: boolean name: type: string visibility: type: string example: '[personal, all, admin]' enum: [personal, all, admin] required: type: boolean searchable: type: boolean input_type: type: string example: '[text,password]' enum: [text, password] registration: type: boolean description: If true, the field is available on the registration form registration_text: type: string description: Text that appears on the registration page, alongside the field readonly: type: boolean min_characters: type: integer description: Used by input types [text, textarea, email, url] max_characters: type: integer description: Used by input types [text, textarea, email, url] max_length: type: integer description: Used by input types [text, url] style: type: string description: Used by input types [text, textarea, select, list, radio, checkbox, date, url] options: type: array items: type: string description: Used by input types [select, list, radio, checkbox]. Note, country and gender have pre-defined options and cannot be changed size: type: integer description: Used by input types [select] domains_whitelist: type: array items: type: string description: Used by input types [email] domains_blacklist: type: array items: type: string description: Used by input types [email] date_range_max: type: string format: date description: Used by input types [date, birthdate] example: 2009-09-01 date_range_min: type: string format: date description: Used by input types [date, birthdate] example: 2009-09-01 date_format: type: string description: | Used by input types [date, birthdate]. 8 date format characters are available. Dates can be separated with spaces, commas, hyphens, orslashes. Example date is January 2, 2000. Y - Full numeric representation of a year, e.g. 2000 y - Last two digits of the year, e.g. 00 M - Abbreviated month name, three letters, e.g. Jan m - Numeric representation of a month, with leading zeroes, e.g. 01 D - Abbreviated day of the month, e.g. Sun d - Numeric day of the month, e.g. 01 F - Full month name, e.g. January l - Full weekday name e.g. Sunday date_type: type: string enum: [date, age] example: '[date,age]' description: Used by input types [date, birthdate] fieldcode: type: string readOnly: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this profile field changed. group_id: type: integer description: Id of the profile field group this field belongs to (see GET /profileFields/groups). Required when creating a field. UserGroupMappingResponse: type: object properties: id: type: integer readOnly: true title: type: string example: "Employees of Company X" field_id: type: integer example: 1 field_name: type: string example: "Role" field_values: type: array items: type: string example: ["employee", "administrator", "manager"] group_ids: type: array items: type: integer example: [2570, 199, 52] UserGroupMapping: type: object required: - group_ids properties: id: type: integer readOnly: true title: type: string example: "Employees of Company X" group_ids: type: array items: type: integer example: [1, 2, 3] field_id: type: integer example: 1 field_values: type: array items: type: string example: ["employee", "administrator", "manager"] ProfileFieldGroup: type: object required: - enabled - name - visibility properties: id: type: integer readOnly: true example: 10 enabled: type: boolean name: type: string visibility: type: string example: '[personal, all, admin]' enum: [personal, all, admin] timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this profile field group changed. ordering: type: integer PurchaseOrder: type: object properties: id: type: integer description: Purchase Order ID readOnly: true title: type: string maxLength: 200 description: Purchase Order title purchase_order_number: type: string maxLength: 155 nullable: true description: Purchase Order number description: type: string nullable: true description: Purchase Order description initial_amount: type: number format: double nullable: true description: Initial amount remaining_balance: type: number format: double nullable: true description: Remaining balance currency: type: object readOnly: true description: Currency associated with this purchase order properties: id: type: integer currency: type: string code: type: string object_type_id: type: integer description: Object Type ID use_tokens: type: boolean description: Whether tokens are used token_id: type: integer nullable: true description: Token ID enabled: type: boolean description: Whether purchase order is enabled date_created: type: string format: date nullable: true description: Creation date (YYYY-MM-DD) example: "2026-01-15" date_modified: type: string format: date nullable: true description: Last modification date (YYYY-MM-DD) example: "2026-01-20" deprecated: true date_expires: type: string format: date nullable: true description: Expiration date (YYYY-MM-DD) example: "2026-12-31" object: type: object nullable: true description: Associated object custom_fields: type: array description: Custom field values items: type: object properties: field_id: type: integer value: type: string field_title: type: string nullable: true field_type: type: string nullable: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this purchase order changed, including related data. PromoCode: type: object properties: id: type: integer readOnly: true example: 1 description: Promo code ID title: type: string example: "Summer Sale 2024" description: Promo code title promo_code: type: string example: "SUMMER2024" description: The actual promo code string item_discount_unit: type: string enum: - Percent - Flat example: "Percent" description: Discount unit type for item purchases item_discount_amount: type: number format: float example: 10.00 description: Discount amount for item purchases initial_discount_unit: type: string enum: - Percent - Flat example: "Flat" description: Discount unit type for initial subscription payment initial_discount_amount: type: number format: float example: 5.00 description: Discount amount for initial subscription payment recurring_discount_unit: type: string enum: - Percent - Flat example: "Percent" description: Discount unit type for recurring subscription payments recurring_discount_amount: type: number format: float example: 15.00 description: Discount amount for recurring subscription payments active_date: type: string format: date example: "2024-06-01" nullable: true description: Date when promo code becomes active (null if not set) expiration_date: type: string format: date example: "2024-08-31" nullable: true description: Date when promo code expires (null if not set) uses_remaining: type: integer example: 100 description: Number of times promo code can still be used times_used: type: integer example: 5 description: Number of times promo code has been used include_all_courses: type: boolean example: true description: Whether promo code applies to all courses timestamp_created: type: string format: date-time readOnly: true example: "2024-01-15 10:30:00" description: When the promo code was created timestamp_modified: type: string format: date-time readOnly: true example: "2024-01-20 14:45:00" description: When the promo code was last modified course_ids: type: array items: type: integer readOnly: true example: [1, 2, 3] description: IDs of courses associated with this promo code plan_ids: type: array items: type: integer readOnly: true example: [5, 6] description: IDs of subscription plans associated with this promo code Quiz: type: object required: - title - slug - required_score properties: id: type: integer readOnly: true example: 1 title: type: string example: MyQuiz slug: type: string description: Unique URI for use in Search Engine Friendly urls. pattern: "[a-z-]+" image: type: string format: uri tries: type: integer description: Number of attempts users have to complete the quiz. remaining_retries: type: integer description: Remaining tries. description: type: string example: This is my quiz course_id: type: integer description: Course id of the course this quiz is assigned to. lesson_id: type: integer description: Lesson id of the lesson this quiz is assigned to. created_by: type: integer description: User id of the user who created this quiz. readOnly: true created_on: type: string format: date readOnly: true required_score: type: number description: Required score in percentage. example: 75 type: type: string example: quiz enum: - quiz - survey description: Only accepted on create; ignored on update. completion_message: type: string example: Quiz Completed! pass_message: type: string example: Congratulations, you passed! fail_message: type: string example: Quiz Failed, minimum score is 75% questions: type: array items: $ref: "#/components/schemas/QuizQuestion" allow_retries: type: boolean duration: type: integer description: Time limit for the quiz in minutes. Must be in the range 0-100. show_overlay: type: boolean show_answers: type: boolean missed_questions_only: type: boolean description: Maps to Allow to Retake Only Incorrect Answers toggle in LMS. quiz_result: type: array items: type: object properties: quizresult_id: type: integer point: type: integer total_marks: type: integer user_id: type: integer example: 1625627 quizquestion_id: type: integer course_id: type: integer lesson_id: type: integer enabled: type: integer ordering: type: integer date: type: string format: datetime answers: type: string archive_date: type: string format: date description: Only populated by GET /quizzes; never returned by GET /quiz/{id}/. timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this quiz changed. show_question_numbers: type: integer modified_by: type: integer readOnly: true modified_on: type: string format: date-time readOnly: true lesson_title: type: string readOnly: true course_title: type: string readOnly: true AssessmentDetail: type: object properties: id: type: integer readOnly: true course_id: type: integer lesson_id: type: integer title: type: string description: type: string image: type: string enabled: type: boolean type: type: object properties: id: type: integer label: type: string question_bank_id: type: integer nullable: true show_question_numbers: type: boolean show_feedback: type: boolean show_question_choice_feedback: type: boolean show_correct_answer: type: boolean is_final: type: boolean use_pool: type: boolean randomize_answer_order: type: boolean pool_size: type: integer nullable: true created_by: type: integer timestamp_created: type: string format: date-time readOnly: true modified_by: type: integer timestamp_modified: type: string format: date-time readOnly: true description: > Also bumped when the assessment's questions or choices are created, updated or deleted via the API (including question bank changes for bank-backed assessments), so timestampModifiedAfter polling detects content edits. time_limit_minutes: type: integer description: Quiz only required_passing_score: type: number description: Quiz only allow_retries: type: boolean description: Quiz only number_allowed_retries: type: integer description: Quiz only completion_message: type: string description: Quiz only passed_message: type: string description: Quiz only failed_message: type: string description: Quiz only rating_scale_max: type: integer description: Survey only completed_message: type: string description: Survey only questions: type: array description: Included on single assessment detail. Questions include type-specific data (choices, keywords). items: type: object properties: id: type: integer assessment_id: type: integer question_bank_id: type: integer nullable: true sequence_number: type: integer label: type: string media: type: string nullable: true show_feedback: type: boolean timestamp_modified: type: string format: date-time nullable: true description: Mirrors the parent assessment's modified timestamp; questions have no timestamp columns of their own. type: type: string choices: type: array description: Multiple choice questions only items: type: object properties: id: type: integer label: type: string sequence_number: type: integer is_correct: type: boolean feedback_text: type: string nullable: true image_url: type: string nullable: true keywords: type: array description: Free text questions only items: type: object properties: id: type: integer label: type: string variation1: type: string nullable: true variation2: type: string nullable: true variation3: type: string nullable: true feedback_correct: type: string nullable: true feedback_incorrect: type: string nullable: true min_character_count: type: integer description: Free text questions only max_character_count: type: integer description: Free text questions only retry_missed_questions_only: type: boolean readOnly: true description: Quiz assessments only. horizontal_rating_scale_display: type: boolean readOnly: true description: Survey assessments only. use_default_scale_labels: type: boolean readOnly: true description: Survey assessments only. course: type: object readOnly: true properties: id: type: integer title: type: string lesson: type: object readOnly: true properties: id: type: integer title: type: string AssessmentResultSummary: type: object properties: id: type: integer readOnly: true user_id: type: integer assessment_id: type: integer assessment_type: type: string description: Type of assessment course_id: type: integer lesson_id: type: integer assessment_title: type: string lesson_title: type: string course_title: type: string submitted_date: type: string format: date-time score: type: number passed: type: boolean total_questions: type: integer number_correct: type: integer user_name: type: string archive_date: type: string format: date-time nullable: true timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true AssessmentResultDetail: allOf: - $ref: "#/components/schemas/AssessmentResultSummary" - type: object properties: responses: type: array description: | Per-response data. Shape varies by question type. Multi-select multiple choice questions emit one entry per chosen choice (the same `question_id` will appear multiple times); consumers must group by `question_id` to reconstruct the answer. items: type: object properties: question_id: type: integer question: type: string description: Question label text question_type: type: string enum: - multiple choice - multiple choice (multi select) - free-form text recorded_timestamp: type: string format: date-time nullable: true selected_choice: type: object nullable: true description: Present for multiple choice questions properties: id: type: integer label: type: string free_text: type: string nullable: true description: Present for free text questions — the learner's written response is_correct: type: boolean nullable: true description: "For MC: from choice. For free text: from graded response (null if ungraded)." QuizQuestion: type: object required: - title - answer1 - answer2 - correctAnswer properties: title: type: string example: "Why did foo bar?" media: type: string format: uri answer1: type: string example: "Because baz" answer2: type: string example: "Because couldn't solve fizzbuzz" answer3: type: string example: "Because bar foo" answer4: type: string example: "All of the above" correctAnswer: type: integer description: Index of the correct answer. 0 - answer1 , 1 - answer2, etc. QuizResponsePayload: type: object required: - user_id - quiz_id - course_id - answers properties: user_id: type: integer example: 1714926 quiz_id: type: integer example: 1234 lesson_id: type: integer example: 1234 course_id: type: integer example: 1234 answers: type: array items: type: integer example: [0, 2, 1] QuizResult: type: object properties: id: type: integer readOnly: true user_id: type: integer readOnly: true quiz_id: type: integer format: int64 readOnly: true answers: type: array items: type: object properties: question: type: string answer: type: string correct: type: boolean correctAnswer: type: string readOnly: true submitted_date: type: string format: date readOnly: true total_questions: type: integer readOnly: true number_correct: type: integer readOnly: true score: type: number readOnly: true passed: type: boolean readOnly: true quiz: readOnly: true type: object $ref: "#/components/schemas/Quiz" lesson_id: type: integer readOnly: true user_name: type: string readOnly: true archive_date: type: string nullable: true readOnly: true timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true ReportsChecklists: type: object properties: started_count: type: number completed_count: type: number ReportsChecklistsGroupedByUsergroup: type: object description: Map keyed by the numeric user group id. additionalProperties: type: object properties: group_title: type: string description: The title of the group started_count: type: number completed_count: type: number ReportsChecklistsGroupedByUser: type: object description: Map keyed by the numeric user id. additionalProperties: type: object properties: started_count: type: number completed_count: type: number display_name: type: string description: The display name of the user ReportsChecklistsGroupedByChecklist: type: object description: Map keyed by the numeric checklist id. additionalProperties: type: object properties: checklist_title: type: string description: The title of the checklist started_count: type: number completed_count: type: number ReportsCourses: type: object properties: started_count: type: number completed_count: type: number ReportsCoursesGroupedByUsergroup: type: object description: Map keyed by the numeric user group id. additionalProperties: type: object properties: group_title: type: string description: The title of the group started_count: type: number completed_count: type: number ReportsCoursesGroupedByUser: type: object description: Map keyed by the numeric user id. additionalProperties: type: object properties: display_name: type: string description: The display name of the user started_count: type: number completed_count: type: number ReportsCoursesGroupedByCourse: type: object description: Map keyed by the numeric course id. additionalProperties: type: object properties: course_title: type: string description: The course title started_count: type: number completed_count: type: number ReportsUsers: type: object properties: login_count: type: number active_count: type: number ReportsUsersGroupedByUsergroup: type: object description: Map keyed by the numeric user group id. additionalProperties: type: object properties: group_title: type: string description: The title of the group login_count: type: number active_count: type: number Subscription: type: object required: - title properties: id: type: integer readOnly: true example: 1 title: type: string published: type: boolean private: type: boolean featured: type: boolean default_sub_length: type: string description: Default length of the subscription period. Valid values are 1-15D, 1-12M, and 1-5Y example: 1D default_initial_amount: type: number description: Amount of money (in USD) that the subscription will cost on signup. format: float default_amount: type: number description: Amount of money (in USD) that the subscription will cost when the subscription period length has elapsed and the subscription is renewed. format: float usergroups: type: array items: type: integer description: Array of user groups for which this subscription will be available. description_html: type: string description: Plain text or HTML-formatted description that describes the subscription. description_type: type: string description: Description type. type: type: string description: type: string timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true SubscriptionPayment: type: object description: | A payment recorded against a user's subscription period. `id` is the `hybrid_transaction.id` and is the value the PATCH and DELETE endpoints expect in the URL. `gateway_transaction_id` is the external (e.g. Stripe) reference used for idempotent replay and for look-up via the list endpoint. properties: id: type: integer readOnly: true description: The `hybrid_transaction.id`. Use this in PATCH/DELETE URLs. example: 1234 gateway_transaction_id: type: string description: External payment gateway reference (e.g. Stripe `payment_intent_id`). example: pi_3O8aBcDeFgHiJk001 user_id: type: integer example: 42 subscription_id: type: integer example: 17 amount: type: number format: float example: 49.99 currency: type: string description: ISO-4217 currency code. example: USD paid_at: type: string description: When the payment was processed (`YYYY-MM-DD HH:MM:SS`). example: "2026-05-13 14:00:00" status: type: string description: | Human-readable payment status. Mapped from `axs_pay_transactions.status`. - `Success` (`SUC`) - `Voided` (`PLHO`) — soft-deleted via DELETE - `Refunded` (`REF`) - `Declined` (`DEC`) - `Failed` (`FAIL`) Unknown DB values pass through unchanged. example: Success period: type: object description: The subscription period this payment covers. properties: id: type: integer example: 9988 start: type: string format: date example: "2026-05-13" end: type: string format: date example: "2026-06-13" status: type: string description: | Human-readable period status. Mapped from `axs_pay_subscription_periods.status`. - `Paid` (`PAID`) - `Unpaid` (`NONE`) - `Partial` (`PART`) - `Prorated Partial` (`PRO1`) - `Provisional` (`PRO2`) - `Free` (`FREE`) - `Complimentary` (`COMP`) - `Paused` (`PAUS`) Unknown DB values pass through unchanged. example: Paid SubscribeRequest: type: object description: | Body for `POST /v1/subscription/{id}/subscribe/`. `userIds` is always required. ## Free flow Plan has `default_amount == 0.00`. Only `userIds` is required; the payment fields are ignored. `userIds` may contain one or many ids. `period_start`/`period_end` are honored when supplied; otherwise the subscription period is derived from the plan's configuration (`default_sub_length`, or the fixed-term end date). ## Paid flow Supply `gateway_transaction_id` (plus `amount`, `paid_at`, `currency`) alongside `userIds` to register an externally-processed payment. `userIds` must contain exactly one id, and the caller must hold one of `payments:create`/`payments:all`/`all:create`/`all`. required: - userIds properties: userIds: type: array minItems: 1 items: type: integer description: | LMS user ids to subscribe. Always an array — even for a single user. **Must contain exactly one id when `gateway_transaction_id` is supplied.** example: [1620265, 1620266] gateway_transaction_id: type: string maxLength: 255 description: | External gateway reference (e.g. Stripe `payment_intent_id`). Must be globally unique across all `axs_pay_transactions.trxn_id` values for this tenant. example: pi_3O8aBcDeFgHiJk001 amount: type: number format: float description: Amount paid. Must be greater than 0. example: 49.99 paid_at: type: string description: When the payment was processed. Must not be in the future. `YYYY-MM-DD HH:MM:SS`. example: "2026-05-13 14:00:00" currency: type: string minLength: 3 maxLength: 3 description: ISO-4217 currency code. Must exist in the tenant's `currency.code` table. example: USD period_start: type: string format: date description: | Optional. Start of the subscription period being registered (free flow) or covered by this payment (paid flow). If omitted, a period is derived from the plan's `default_sub_length` starting today. Required when `period_end` is supplied. example: "2026-05-13" period_end: type: string format: date description: Optional. End of the subscription period. Required when `period_start` is supplied; must be strictly after `period_start`. example: "2026-06-13" SubscriptionPaymentCreate: type: object required: - gateway_transaction_id - amount - paid_at - currency properties: gateway_transaction_id: type: string maxLength: 255 description: | External gateway reference (e.g. Stripe `payment_intent_id`). Must be globally unique across all `axs_pay_transactions.trxn_id` values for this tenant. Acts as the idempotency key — replaying the same `(userId, subId, gateway_transaction_id)` returns the existing record with HTTP 200 instead of 201. example: pi_3O8aBcDeFgHiJk001 amount: type: number format: float description: Amount paid. Must be greater than 0. example: 49.99 paid_at: type: string description: When the payment was processed. Must not be in the future. `YYYY-MM-DD HH:MM:SS`. example: "2026-05-13 14:00:00" currency: type: string minLength: 3 maxLength: 3 description: ISO-4217 currency code. example: USD period_start: type: string format: date description: | Optional. Start of the subscription period this payment covers. If omitted, a period is derived from the subscription's `period_length` starting today (or at the end of the existing covering period). Required when `period_end` is supplied. example: "2026-05-13" period_end: type: string format: date description: Optional. End of the subscription period. Required when `period_start` is supplied; must be strictly after `period_start`. example: "2026-06-13" SubscriptionPaymentUpdate: type: object description: | Correct one or more fields on an existing payment. All fields are optional; only the fields supplied are updated. The endpoint does not support reversing a payment — use DELETE for that. properties: gateway_transaction_id: type: string maxLength: 255 description: Corrected external gateway reference. amount: type: number format: float description: Corrected amount. Must be greater than 0. paid_at: type: string description: Corrected payment timestamp. Must not be in the future. `YYYY-MM-DD HH:MM:SS`. UserSubscription: type: object properties: id: type: integer readOnly: true user_id: type: integer readOnly: true cancel_date: type: string readOnly: true plan_id: type: integer readOnly: true status: type: string readOnly: true next_payment_date: type: string recurring_amount: type: string readOnly: true period_length: type: string readOnly: true Survey: type: object properties: id: type: integer readOnly: true example: 1 title: type: string example: MySurvey description: type: string example: This is my survey questions: type: array items: type: object properties: id: type: string readOnly: true example: 1624487827DHmcGo question_type: type: string description: Possible values are textbox, textarea, multiplechoice, multiplechoice_multiselect, and likert. example: multiplechoice question: type: string example: What is love? multiple_choice_options: type: string description: Newline separated list of options for multiplechoice and multiplechoice_multiselect question types. example: Baby\r\ndon't\r\nhurt\r\nme params: type: object properties: likert_labels: type: string description: Possible values are 'custom' or 'default'. label_1: type: string example: Strongly Disagree label_2: type: string example: Disagree label_3: type: string example: Undecided label_4: type: string example: Agree label_5: type: string example: Strongly Agree label_6: type: string label_7: type: string label_8: type: string label_9: type: string label_10: type: string label_11: type: string rating_number: type: string description: Likert scale number, possible values are 5, 7, or 11. example: 0 rating_direction: type: string description: Controls the display of likert labels in quiz. Possible values are 'vertical' or 'horizontal'. custom_completed_message: type: string description: Toggle for using either the default or user provided completion message. Possible values are 'custom' or 'default'. completed_message: type: string description: If custom_completed_message = custom then this message is used. enabled: type: boolean description: Defines the published (also called enabled) status of the survey. modified_date: type: string example: "2022-12-06 12:54:43" created_on: type: string example: "2022-12-06 12:54:43" created_by: type: integer readOnly: true timestamp_modified: type: string format: date-time readOnly: true timestamp_created: type: string format: date-time readOnly: true SurveyResponse: type: object required: - survey_id - user_id - question_id - question_type - question - answer properties: id: type: integer readOnly: true example: 1 survey_id: type: integer user_id: type: integer description: id of the user that submitted the response. example: 1623570 lesson_id: type: integer description: id of the lesson that this survey was submitted in. activity_id: type: string description: id of the corresponding lesson student activity used to complete the survey, it should be one of the activities inside lesson with id = lesson_id. example: 1656638001Xehtvk event_id: type: integer description: id of the event that this survey was completed as a part of. Surveys are either completed inside lessons or events. question_id: type: string example: 1659494905ZHLhxu question_type: type: string description: the question type can be likert, multiplechoice, multiplechoice_multiselect, textbox or textarea. enum: - likert - multiplechoice - textarea - multiplechoice_multiselect - textbox question: type: string example: Rate your learning experience on a scale from 1-5 answer: type: string example: 5 score: type: integer description: Used for question_type = likert, the corresponding likert score for the selected response. timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true submitted_date: type: string readOnly: true archive_date: type: string nullable: true readOnly: true Tag: type: object properties: id: type: integer readOnly: true title: type: string readOnly: true enabled: type: boolean readOnly: true timestamp_modified: type: string format: date-time readOnly: true Instructor: type: object properties: id: type: integer readOnly: true example: 1 name: type: string example: John Doe title: type: string example: Lead Instructor image: type: string example: images/instructors/photo.jpg enabled: type: boolean example: true user_id: type: integer nullable: true example: 123 use_tovuti_profile: type: boolean example: false timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this instructor changed, including related data. Teacher: type: object properties: teacher_id: type: integer title: type: string user_id: type: integer Team: type: object required: - title - member_type properties: id: type: integer readOnly: true example: 1 title: type: string example: MyUserTeam member_type: type: string description: Possible values are 'individuals' or 'groups'. example: groups enum: - individuals - groups description: type: string example: Team description enabled: type: boolean example: true description: Same as 'published' team_lead: type: array items: type: integer description: Set of user ids. Users with ids in this set are team leads. use_lead_groups: type: boolean example: true default: true description: When set to true, the lead_user_groups attribute can be set lead_user_groups: type: array items: type: integer description: An array of usergroup IDs user_ids: type: array items: type: integer description: Set of user ids. Users with these ids will be added as team members. Only used when member_type = 'individuals'. user_groups: type: array items: type: integer description: Set of user group ids. Users in these groups will be added as team members. Only used when member_type = 'groups'. date_created: type: string format: date readOnly: true allow_adding_users: type: boolean description: If set to 'true' team leads will be able to add users to teams they are leaders of. allow_removing_users_from_team: type: boolean description: If set to 'true' team leads will be able to remove users from teams they are leaders of. allow_removing_users_from_system: type: boolean description: If set to 'true' team leads will be able to delete users in their team completely. allow_managing_users_groups: type: boolean description: If set to 'true' team leads will be able to add or remove usergroups that are a part of the teams they are leaders of. assignable_user_groups: type: array items: type: integer description: Set of user group ids that team leads can assign members to. allow_assigning_courses: type: boolean description: If set to 'true' team leads will be able to assign team members to course in assignable_course_ids. assignable_course_ids: type: array items: type: integer description: Set of course ids that team leads can enroll team members in. allow_assigning_events: type: boolean description: If set to 'true' team leads will be able to register team members for events. allow_assigning_learning_paths: type: boolean description: If set to 'true' team leads will be able to assign learning paths to teanm members. assignable_learning_path_ids: type: array items: type: integer description: Set of learning path ids that team leads can enroll team members in. allow_assigning_media_items: type: boolean description: > If set to 'true' team leads will be able to create media item assignments for team members from the media items in assignable_media_item_ids. Only takes effect on sites with media item assignments enabled; the value is stored either way. assignable_media_item_ids: type: array items: type: integer description: > Set of media item ids that team leads can assign to team members. An empty array allows every enabled media item. Team leads also need visibility access to a media item to assign it. On update, omit this field to leave the list unchanged; send an empty array to clear it. timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this team changed. created_by: type: integer readOnly: true User: type: object properties: id: type: integer format: int64 readOnly: true example: 1714926 name: type: string example: John Doe username: type: string example: johndoe email: type: string example: johndoe@gmail.com password: type: string example: password100 writeOnly: true userGroupIds: type: array items: type: integer description: Ids of usergroups this user belongs to. userTeamIds: type: array items: type: integer description: Ids of userteams this user belongs to. userTeamIds can only be assigned for teams with member_type = 'individuals'. enrolledCourseIds: type: array items: type: integer requireReset: type: boolean description: If 'true' the user will be required to reset their password on their next login. registerDate: readOnly: true type: string format: date lastvisitDate: readOnly: true type: string format: date customFields: type: array description: When assigning customFields either a field_id or title can be provided. It is recommended to use the field_id in case there is a field name with a duplicate title. items: $ref: '#/components/schemas/CustomFieldValueResponse' objects: type: array description: Array of Objects associated to user. items: $ref: "#/components/schemas/ObjectsValue" accessLevels: readOnly: true type: array items: type: integer status: type: string description: The current enabled/disabled status of the user. Possible values are active or disabled. example: active timestamp_modified: type: string format: date-time readOnly: true UserCourseProgress: type: object properties: user_id: type: integer readOnly: true course_id: type: integer language: type: string lessons_completed_list: type: array items: type: integer lessons_total_list: type: array items: type: integer score: type: number progress: type: number format: float date_started: type: string format: date date_last_activity: type: string format: date date_completed: type: string format: date date_due: type: string format: date archive_date: type: string format: date lessons: type: object description: Lessons list. example: {"activities": [{"activity_id": "1619209659BqkVD2", "user_id": "User ID", "activity_name": "Name", "activity_type": "interactive", "student_response": "Recorded student response for activity", "activity_status": "in progress"}]} id: type: integer readOnly: true status: type: string readOnly: true user_name: type: string readOnly: true course_title: type: string readOnly: true course_enabled: type: integer readOnly: true timestamp_modified: type: string format: date-time readOnly: true UserGroup: type: object properties: id: type: integer readOnly: true example: 2 title: type: string example: MyUserGroup parent_id: type: integer description: User group id of the parent group. example: 1 userIds: type: array items: type: integer description: User ids of users that are in this group. links: type: object readOnly: true properties: parent_url: type: string children_url: type: string descendants_url: type: string lft: type: integer description: Start of range that contains descendant user groups. See https://en.wikipedia.org/wiki/Nested_set_model for more info. readOnly: true rgt: type: integer description: End of range that contains descendant user groups. See https://en.wikipedia.org/wiki/Nested_set_model for more info. readOnly: true timestamp_modified: type: string format: date-time readOnly: true UserPayload: type: object required: - name - username - email - password properties: id: type: integer format: int64 readOnly: true example: 1714926 name: type: string example: John Doe username: type: string example: johndoe email: type: string example: johndoe@gmail.com password: type: string example: password100 writeOnly: true userGroupIds: type: array items: type: integer description: Ids of usergroups this user belongs to. userTeamIds: type: array items: type: integer description: Ids of userteams this user belongs to. userTeamIds can only be assigned for teams with member_type = 'individuals'. enrolledCourseIds: type: array items: type: integer requireReset: type: boolean description: If 'true' the user will be required to reset their password on their next login. registerDate: readOnly: true type: string format: date lastvisitDate: readOnly: true type: string format: date customFields: type: array description: When assigning customFields either a field_id or title can be provided. It is recommended to use the field_id in case there is a field name with a duplicate title. items: $ref: '#/components/schemas/CustomFieldFilter' objectIds: type: array description: Array of Objects Ids. items: type: integer accessLevels: readOnly: true type: array items: type: integer status: type: string enum: [active, disabled] example: '[active, disabled]' # ========================================== # Assessment Schemas # ========================================== QuestionBank: type: object properties: id: type: integer readOnly: true example: 1 label: type: string example: "Math Fundamentals Question Bank" description: type: string nullable: true example: "Collection of basic math questions" enabled: type: boolean example: true created_by: type: integer nullable: true example: 123 created_timestamp: type: string format: date-time readOnly: true modified_by: type: integer nullable: true example: 456 modified_timestamp: type: string format: date-time readOnly: true description: > Also bumped when the bank's questions or choices are created, updated or deleted via the API. Bank changes cascade to assessments drawing from the bank, so timestampModifiedAfter polling on assessments detects them too. questions: type: array readOnly: true items: $ref: "#/components/schemas/Question" QuestionBankCreate: type: object required: - label properties: label: type: string example: "Math Fundamentals Question Bank" description: type: string nullable: true example: "Collection of basic math questions" enabled: type: boolean default: true QuestionBankUpdate: type: object properties: label: type: string example: "Updated Question Bank" description: type: string nullable: true enabled: type: boolean modified_by: type: integer nullable: true Question: type: object properties: id: type: integer readOnly: true example: 1 assessment_id: type: integer nullable: true example: 5 question_bank_id: type: integer nullable: true example: 3 sequence_number: type: integer default: 0 example: 1 label: type: string example: "What is 2 + 2?" media: type: string nullable: true example: "https://example.com/image.jpg" show_feedback: type: boolean default: false timestamp_modified: type: string format: date-time readOnly: true nullable: true example: "2026-08-26 15:43:26" description: > Questions have no timestamp columns of their own; question and choice edits bump the parent assessment (or question bank), so this mirrors the parent's modified timestamp - a "last changed no later than" value. type: type: object readOnly: true properties: id: type: integer example: 1 label: type: string example: "multiple choice" choices: type: array readOnly: true description: Multiple choice questions only items: $ref: "#/components/schemas/QuestionChoice" keywords: type: array readOnly: true description: Free text questions only items: type: object properties: id: type: integer label: type: string variation1: type: string nullable: true variation2: type: string nullable: true variation3: type: string nullable: true feedback_correct: type: string nullable: true feedback_incorrect: type: string nullable: true min_character_count: type: integer description: Free text questions only max_character_count: type: integer description: Free text questions only QuestionCreate: type: object required: - label - type_id properties: label: type: string example: "What is 2 + 2?" type_id: type: integer example: 1 sequence_number: type: integer default: 0 media: type: string nullable: true show_feedback: type: boolean default: false choices: type: array items: type: object required: - label - sequence_number properties: label: type: string example: "4" sequence_number: type: integer example: 1 is_correct: type: boolean default: false feedback_text: type: string nullable: true QuestionCreateIndependent: type: object required: - label - type_id properties: label: type: string example: "What is 2 + 2?" type_id: type: integer example: 1 assessment_id: type: integer nullable: true example: 5 description: "Either assessment_id or question_bank_id must be provided (mutually exclusive)" question_bank_id: type: integer nullable: true example: 3 description: "Either assessment_id or question_bank_id must be provided (mutually exclusive)" sequence_number: type: integer default: 0 media: type: string nullable: true show_feedback: type: boolean default: false choices: type: array items: type: object required: - label - sequence_number properties: label: type: string example: "4" sequence_number: type: integer example: 1 is_correct: type: boolean default: false feedback_text: type: string nullable: true QuestionUpdate: type: object properties: label: type: string type_id: type: integer sequence_number: type: integer media: type: string nullable: true show_feedback: type: boolean QuestionChoice: type: object properties: id: type: integer readOnly: true example: 1 question_id: type: integer example: 5 label: type: string example: "4" sequence_number: type: integer example: 1 is_correct: type: boolean example: true static_sequence: type: boolean nullable: true example: false feedback_text: type: string nullable: true example: "Correct!" image_url: type: string nullable: true example: "https://example.com/image.png" QuestionChoiceCreate: type: object required: - label - sequence_number properties: label: type: string example: "4" sequence_number: type: integer example: 1 is_correct: type: boolean default: false feedback_text: type: string nullable: true QuestionChoiceUpdate: type: object properties: label: type: string sequence_number: type: integer is_correct: type: boolean feedback_text: type: string nullable: true CustomFieldFilter: type: object required: - value properties: field_id: type: integer description: Id of the profile field. Preferred over title. title: type: string description: Title of the profile field; use field_id when titles are ambiguous. value: type: string description: Value to match/assign. % wildcards supported when filtering. CustomFieldValueResponse: type: object properties: field_id: type: integer readOnly: true value: type: string readOnly: true field_title: type: string readOnly: true field_type: type: string readOnly: true AwardUpdate: type: object properties: id: type: integer readOnly: true example: 1 title: type: string example: Badge of Awesomeness type: type: string description: Can be badge, certificate, or milestone. example: badge enum: - badge - certificate - milestone certificate_type: type: string enum: - internal - external default: internal description: External certificates have no requirements example: internal description: type: string example: This badge is awesome! maxLength: 50 enabled: type: boolean badge_hover: type: string example: Badge of Awesomeness share_award_page: type: boolean expiration_type: type: string description: Type of time period after which the certificate will expire. Possible values are "year", "month", "week", "day". example: year|month|week|day expiration_classification: type: string description: Type of award expiration. Possible values are "static", "dynamic", "none". example: static|dynamic|none expiration_date: type: string format: date description: Date of static award expiration example: '2024-01-01 16:08:08' expiration_amount: type: integer description: The number of [expiration_type]s that will need to pass before this award expires. requirement_type: type: string description: Set this to "assigned" to assign the certificate to a specific user or set of users, or set to "conditional" to only award the certificate after a specific set of requirements are met. example: conditional|assigned user_can_lose_badge: type: boolean description: If true if the user will be able to lose their award. certificate_id: type: integer description: The certificate template this award is associated with. Only used if type = 'certificate'. requirements_all: type: boolean description: Only needed when requirement_type is set to "conditional". Set this to true if all requirements must be met, or false if any subset of them can be met to award the certificate. user_list: type: array items: type: integer description: Array of user ids to assign the award to, only used when award type = "assigned". usergroup_actions: type: boolean description: If set to true, add the users who were awarded the certificate to usergroups. add_usergroups: type: array items: type: integer description: Array of user group ids to add award recipients to. remove_usergroups: type: array items: type: integer description: Array of user group ids to remove award recipients from. points_actions: type: boolean description: If set to true, points are awarded upon attainment of the award. points_category: type: integer description: Id of points category that points should be assigned under. points: type: integer description: The number of points to be awarded on certificate attainment. requirements: type: array items: $ref: "#/components/schemas/AwardRequirement" timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this award changed. created_by: type: integer readOnly: true created_on: type: string format: date-time readOnly: true description: Same shape as Award but with no required fields - all fields are optional on update. TeamUpdate: type: object properties: id: type: integer readOnly: true example: 1 title: type: string example: MyUserTeam member_type: type: string description: Possible values are 'individuals' or 'groups'. example: groups enum: - individuals - groups description: type: string example: Team description enabled: type: boolean example: true description: Same as 'published' team_lead: type: array items: type: integer description: Set of user ids. Users with ids in this set are team leads. use_lead_groups: type: boolean example: true default: true description: When set to true, the lead_user_groups attribute can be set lead_user_groups: type: array items: type: integer description: An array of usergroup IDs user_ids: type: array items: type: integer description: Set of user ids. Users with these ids will be added as team members. Only used when member_type = 'individuals'. user_groups: type: array items: type: integer description: Set of user group ids. Users in these groups will be added as team members. Only used when member_type = 'groups'. date_created: type: string format: date readOnly: true allow_adding_users: type: boolean description: If set to 'true' team leads will be able to add users to teams they are leaders of. allow_removing_users_from_team: type: boolean description: If set to 'true' team leads will be able to remove users from teams they are leaders of. allow_removing_users_from_system: type: boolean description: If set to 'true' team leads will be able to delete users in their team completely. allow_managing_users_groups: type: boolean description: If set to 'true' team leads will be able to add or remove usergroups that are a part of the teams they are leaders of. assignable_user_groups: type: array items: type: integer description: Set of user group ids that team leads can assign members to. allow_assigning_courses: type: boolean description: If set to 'true' team leads will be able to assign team members to course in assignable_course_ids. assignable_course_ids: type: array items: type: integer description: Set of course ids that team leads can enroll team members in. allow_assigning_events: type: boolean description: If set to 'true' team leads will be able to register team members for events. allow_assigning_learning_paths: type: boolean description: If set to 'true' team leads will be able to assign learning paths to teanm members. assignable_learning_path_ids: type: array items: type: integer description: Set of learning path ids that team leads can enroll team members in. timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this team changed. created_by: type: integer readOnly: true description: Same shape as Team but with no required fields - all fields are optional on update. CommunityGroupUpdate: type: object properties: id: type: integer readOnly: true name: type: string published: type: boolean enable_user_groups: type: boolean owner_id: type: integer readOnly: true description: type: string users: type: array items: type: integer user_groups: type: array items: type: integer created: type: string format: date-time readOnly: true description: Same shape as CommunityGroup but with no required fields - all fields are optional on update. UserPayloadUpdate: type: object properties: id: type: integer format: int64 readOnly: true example: 1714926 name: type: string example: John Doe username: type: string example: johndoe email: type: string example: johndoe@gmail.com password: type: string example: password100 writeOnly: true userGroupIds: type: array items: type: integer description: Ids of usergroups this user belongs to. userTeamIds: type: array items: type: integer description: Ids of userteams this user belongs to. userTeamIds can only be assigned for teams with member_type = 'individuals'. enrolledCourseIds: type: array items: type: integer requireReset: type: boolean description: If 'true' the user will be required to reset their password on their next login. registerDate: readOnly: true type: string format: date lastvisitDate: readOnly: true type: string format: date customFields: type: array description: When assigning customFields either a field_id or title can be provided. It is recommended to use the field_id in case there is a field name with a duplicate title. items: $ref: '#/components/schemas/CustomFieldFilter' objectIds: type: array description: Array of Objects Ids. items: type: integer accessLevels: readOnly: true type: array items: type: integer status: type: string enum: [active, disabled] example: '[active, disabled]' # ========================================== # Assessment Schemas # ========================================== description: Same shape as UserPayload but with no required fields - all fields are optional on update. ProfileFieldUpdate: type: object properties: id: type: integer readOnly: true example: 10 type: type: string enum: [text, textarea, select, list, radio, checkbox, country, gender, email, time, date, url, birthdate] example: '[text, textarea, select, list, radio, checkbox, country, gender, email, time, date, url, birthdate]' ordering: type: integer readOnly: true enabled: type: boolean name: type: string visibility: type: string example: '[personal, all, admin]' enum: [personal, all, admin] required: type: boolean searchable: type: boolean input_type: type: string example: '[text,password]' enum: [text, password] registration: type: boolean description: If true, the field is available on the registration form registration_text: type: string description: Text that appears on the registration page, alongside the field readonly: type: boolean min_characters: type: integer description: Used by input types [text, textarea, email, url] max_characters: type: integer description: Used by input types [text, textarea, email, url] max_length: type: integer description: Used by input types [text, url] style: type: string description: Used by input types [text, textarea, select, list, radio, checkbox, date, url] options: type: array items: type: string description: Used by input types [select, list, radio, checkbox]. Note, country and gender have pre-defined options and cannot be changed size: type: integer description: Used by input types [select] domains_whitelist: type: array items: type: string description: Used by input types [email] domains_blacklist: type: array items: type: string description: Used by input types [email] date_range_max: type: string format: date description: Used by input types [date, birthdate] example: 2009-09-01 date_range_min: type: string format: date description: Used by input types [date, birthdate] example: 2009-09-01 date_format: type: string description: | Used by input types [date, birthdate]. 8 date format characters are available. Dates can be separated with spaces, commas, hyphens, orslashes. Example date is January 2, 2000. Y - Full numeric representation of a year, e.g. 2000 y - Last two digits of the year, e.g. 00 M - Abbreviated month name, three letters, e.g. Jan m - Numeric representation of a month, with leading zeroes, e.g. 01 D - Abbreviated day of the month, e.g. Sun d - Numeric day of the month, e.g. 01 F - Full month name, e.g. January l - Full weekday name e.g. Sunday date_type: type: string enum: [date, age] example: '[date,age]' description: Used by input types [date, birthdate] fieldcode: type: string readOnly: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this profile field changed. group_id: type: integer description: Id of the profile field group this field belongs to (see GET /profileFields/groups). Required when creating a field. description: Same shape as ProfileField but with no required fields - all fields are optional on update. ProfileFieldGroupUpdate: type: object properties: id: type: integer readOnly: true example: 10 enabled: type: boolean name: type: string visibility: type: string example: '[personal, all, admin]' enum: [personal, all, admin] timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this profile field group changed. ordering: type: integer description: Same shape as ProfileFieldGroup but with no required fields - all fields are optional on update. UserGroupMappingUpdate: type: object properties: id: type: integer readOnly: true title: type: string example: "Employees of Company X" group_ids: type: array items: type: integer example: [1, 2, 3] field_id: type: integer example: 1 field_values: type: array items: type: string example: ["employee", "administrator", "manager"] description: Same shape as UserGroupMapping but with no required fields - all fields are optional on update. CourseUpdate: type: object properties: id: type: integer readOnly: true title: type: string example: MyCourse slug: type: string description: Unique URI for use in Search Engine Friendly urls. pattern: "[a-z-]+" coursescategory_id: type: integer format: int64 description: Id of the course category this course belongs to. courses_sub_categories_ids: type: array items: type: integer description: Comma-separated list of course category ids that this course belongs to. description: type: string short_description: type: string readOnly: true image: type: string video_url: type: string featured_course: type: boolean price: type: number format: float available_to_purchase: type: boolean enabled: type: boolean registrants: readOnly: true type: array items: type: integer external_link: type: string format: url final_course_survey: nullable: true description: Set to null to remove the final course survey from the course. type: object properties: id: type: integer survey_title: type: string survey_instructions: type: string content_expires: type: boolean expiration_date: type: string format: date custom_id: type: string required_for_completion: type: boolean customFields: type: array description: When assigning customFields either a field_id or title can be provided. It is recommended to use the field_id in case there is a field name with a duplicate title. items: $ref: '#/components/schemas/CustomFieldFilter' lessons: type: number format: int readOnly: true description: The number of lessons in the course. ordering: type: number format: int readOnly: true description: Used when displaying multiple courses. view_access_type: type: string example: none description: 'Visibility Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access register_access_type: type: string example: none description: 'Registration Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access view_access_groups: type: array items: type: integer description: array of group ids. Required if view_access_type is user. view_access_users: type: array items: type: integer description: array of user ids. Required if view_access_type is list. view_access_levels: type: array items: type: integer description: array of access level ids. Required if view_access_type is access. register_access_groups: type: array items: type: integer description: array of group ids. Required if register_access_type is user. register_access_users: type: array items: type: integer description: array of user ids. Required if register_access_type is list. register_access_levels: type: array items: type: integer description: array of access level ids. Required if register_access_type is access. multilingual_overrides: type: object items: type: object description: 'An object with multilingual override data in the form { "fr": { "use": 1, "title": "French Title", ...} }. Overrides are only included if enabled (use = 1).' use_library_content: type: boolean description: Specifies if a SCORM (or bizlibrary) package is used for this course library_content_type: type: string description: Either 'bizlibrary' or 'scorm' bizlibrary_content_title: type: string bizlibrary_content_id: type: string scorm_id: type: integer scorm_title: type: string locked: type: integer use_due_date: type: boolean readOnly: true hard_due_date: type: boolean readOnly: true due_date_type: type: string readOnly: true description: static|dynamic example: static|dynamic due_static_date: type: string format: date readOnly: true due_dynamic_number: type: integer readOnly: true due_dynamic_unit: type: string readOnly: true description: minute|hour|day|week|month|year example: minute|hour|day|week|month|year open_date: type: string format: date readOnly: true close_date: type: string format: date readOnly: true visible_before_open: type: boolean readOnly: true visible_after_close: type: boolean readOnly: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this course changed, including related data such as lessons or assignments. course_sub_title: type: string readOnly: true ref_url: type: string readOnly: true pricing_modifiers: type: object readOnly: true created_on: type: string format: date-time readOnly: true modified_on: type: string format: date-time readOnly: true events: type: array readOnly: true items: type: object properties: id: type: integer title: type: string restrict_event_registrations: type: integer readOnly: true allow_to_regsister_all_events: type: integer readOnly: true description: 'Note: the misspelling is the actual field name returned by the API.' event_registration_limit: type: integer readOnly: true event_checkin_required: type: integer readOnly: true event_registration_required: type: integer readOnly: true description: Same shape as Course but with no required fields - all fields are optional on update. CourseCategoryUpdate: type: object properties: id: type: integer readOnly: true title: type: string parent_id: type: integer description: The id of the parent course category. 0 for no parent. slug: type: string description: Unique URI for use in Search Engine Friendly urls. pattern: "[a-z-]+" enabled: type: boolean view_access_type: type: string example: none|list|user|access description: Visibility Permission Type. view_access_groups: type: array items: type: integer description: array of group ids. Required if view_access_type is user. view_access_users: type: array items: type: integer description: array of user ids. Required if view_access_type is list. view_access_levels: type: array items: type: integer description: array of access level ids. Required if view_access_type is access. multilingual_overrides: type: object items: type: object description: 'An object with multilingual override data in the form { "fr": { "use": 1, "title": "French Title", ...} } . Overrides are only included if enabled (use = 1).' timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this course category changed. description: Same shape as CourseCategory but with no required fields - all fields are optional on update. LessonInsertUpdate: type: object properties: title: type: string description: Title of Lesson. example: Introduction to Quantum Physics image: type: string description: Image URL. example: http://example.com/image.jpg description: type: string description: Lesson description. example: Lesson description text lesson_type: type: integer description: Lesson Type. example: 0 - Public, 1 - Access Only language: type: string description: Language code. example: en-GB|pt-BR published: type: boolean description: Lesson publish status. example: true|false quiz_prerequisite_setting: type: boolean description: Unlock after quiz. example: true|false award_points: type: integer description: Number of Award points. example: 10000 prerequisite_quizzes: type: array example: [1, 2, 4] items: type: integer teacher_id: type: integer description: Teacher ID. deprecated: true teacher_ids: type: array items: type: integer description: Teacher IDs. course_id: type: integer description: Course ID. description: Same shape as LessonInsert but with no required fields - all fields are optional on update. QuizUpdate: type: object properties: id: type: integer readOnly: true example: 1 title: type: string example: MyQuiz slug: type: string description: Unique URI for use in Search Engine Friendly urls. pattern: "[a-z-]+" image: type: string format: uri tries: type: integer description: Number of attempts users have to complete the quiz. remaining_retries: type: integer description: Remaining tries. description: type: string example: This is my quiz course_id: type: integer description: Course id of the course this quiz is assigned to. lesson_id: type: integer description: Lesson id of the lesson this quiz is assigned to. created_by: type: integer description: User id of the user who created this quiz. readOnly: true created_on: type: string format: date readOnly: true required_score: type: number description: Required score in percentage. example: 75 type: type: string example: quiz enum: - quiz - survey description: Only accepted on create; ignored on update. completion_message: type: string example: Quiz Completed! pass_message: type: string example: Congratulations, you passed! fail_message: type: string example: Quiz Failed, minimum score is 75% questions: type: array items: $ref: "#/components/schemas/QuizQuestion" allow_retries: type: boolean duration: type: integer description: Time limit for the quiz in minutes. Must be in the range 0-100. show_overlay: type: boolean show_answers: type: boolean missed_questions_only: type: boolean description: Maps to Allow to Retake Only Incorrect Answers toggle in LMS. quiz_result: type: array items: type: object properties: quizresult_id: type: integer point: type: integer total_marks: type: integer user_id: type: integer example: 1625627 quizquestion_id: type: integer course_id: type: integer lesson_id: type: integer enabled: type: integer ordering: type: integer date: type: string format: datetime answers: type: string archive_date: type: string format: date description: Only populated by GET /quizzes; never returned by GET /quiz/{id}/. timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this quiz changed. show_question_numbers: type: integer modified_by: type: integer readOnly: true modified_on: type: string format: date-time readOnly: true lesson_title: type: string readOnly: true course_title: type: string readOnly: true description: Same shape as Quiz but with no required fields - all fields are optional on update. AssignmentUpdate: type: object properties: id: type: integer readOnly: true example: 1 title: type: string type: type: string description: Set to 'recommended' for courses in this assignment to show up as recommended or 'assigned' for courses to show up as assigned. example: Assigned enum: - Assigned - Recommended - assigned - recommended assignment_type: type: string description: Set to 'courses' for courses or 'learningpaths' for learning paths. example: courses enum: - courses - learningpaths course_ids: type: array items: type: integer description: Required if assignment_type is "courses" learning_path_ids: type: array items: type: integer description: Required if assignment_type is "learningpaths" usergroups: type: array items: type: integer user_ids: type: array items: type: integer users: readOnly: true type: array items: type: object properties: id: type: integer example: 1620265 username: type: string example: johndoe email: type: string example: john@doe.com name: type: string example: John Doe free: type: boolean description: If true, the assignment is free. start_date: type: string format: date end_date: type: string format: date due_date: type: string format: date days_to_complete: type: integer minimum: 0 maximum: 2048 assignment_filter_type: type: string description: Filter type ( users or groups ). example: groups enum: - users - groups team_id: type: integer readOnly: true dynamic_due_dates_enabled: type: boolean description: Only works for Learning Path Assignments dynamic_due_date_number: type: integer description: Required if dynamic_due_dates_enabled is true dynamic_due_date_unit: type: string enum: - minute - hour - day - week - month - year example: '[minute, hour, day, month, year]' description: Required if dynamic_due_dates_enabled is true enroll_users_in_paths: type: boolean description: Only works for Learning Path Assignments. When true, users will be enrolled in the learning paths. Defaults to true if not specified. created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this assignment changed. description: type: string maxLength: 50 description: Same shape as Assignment but with no required fields - all fields are optional on update. LearningPathUpdate: type: object properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean description: type: string courses: type: array items: type: integer course_details: type: array readOnly: true items: type: object properties: id: type: integer title: type: string ordering: type: integer optional_courses: type: array items: type: integer optional_course_details: type: array readOnly: true items: type: object properties: id: type: integer title: type: string ordering: type: integer subcategories: type: array items: type: integer tags: type: array items: type: integer view_access_type: type: string example: none description: 'Visibility Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access register_access_type: type: string example: none description: 'Registration Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access view_access_groups: type: array items: type: integer description: array of group ids. Required if view_access_type is user. view_access_users: type: array items: type: integer description: array of user ids. Required if view_access_type is list. view_access_levels: type: array items: type: integer description: array of access level ids. Required if view_access_type is access. register_access_groups: type: array items: type: integer description: array of group ids. Required if register_access_type is user. register_access_users: type: array items: type: integer description: array of user ids. Required if register_access_type is list. register_access_levels: type: array items: type: integer description: array of access level ids. Required if register_access_type is access. created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path changed, including related data such as courses or subcategories. image: type: string readOnly: true description: Same shape as LearningPath but with no required fields - all fields are optional on update. LearningPathWithImageUpdate: type: object properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean description: type: string courses: type: array items: type: integer subcategories: type: array items: type: integer tags: type: array items: type: integer image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. Maximum size 10MB. view_access_type: type: string example: none|list|user|access description: Visibility Permission Type. register_access_type: type: string example: none|list|user|access description: Registration Permission Type. view_access_groups: type: array items: type: integer description: array of group ids. Required if view_access_type is user. view_access_users: type: array items: type: integer description: array of user ids. Required if view_access_type is list. view_access_levels: type: array items: type: integer description: array of access level ids. Required if view_access_type is access. register_access_groups: type: array items: type: integer description: array of group ids. Required if register_access_type is user. register_access_users: type: array items: type: integer description: array of user ids. Required if register_access_type is list. register_access_levels: type: array items: type: integer description: array of access level ids. Required if register_access_type is access. created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path changed, including related data such as courses or subcategories. optional_courses: type: array items: type: integer description: Ids of optional (non-required) courses in the learning path. description: Same shape as LearningPathWithImage but with no required fields - all fields are optional on update. LearningPathCategoryUpdate: type: object properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean subcategories: type: array items: type: integer subcategory_details: type: array readOnly: true items: type: object properties: id: type: integer title: type: string ordering: type: integer created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path category changed, including related data such as subcategories. access_type: type: string example: none enum: - none - access - user - list description: 'Note: "list" targets specific users and "user" targets user groups.' userlist: type: array items: type: integer usergroup: type: array items: type: integer accesslevel: type: array items: type: integer description: Same shape as LearningPathCategory but with no required fields - all fields are optional on update. LearningPathSubcategoryUpdate: type: object properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean description: type: string categories: type: array items: type: integer learning_paths: type: array items: type: integer learning_path_details: type: array readOnly: true items: type: object properties: id: type: integer title: type: string ordering: type: integer created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path subcategory changed, including related data such as learning paths. access_type: type: string example: none enum: - none - access - user - list description: 'Note: "list" targets specific users and "user" targets user groups.' userlist: type: array items: type: integer usergroup: type: array items: type: integer accesslevel: type: array items: type: integer image: type: string readOnly: true description: Same shape as LearningPathSubcategory but with no required fields - all fields are optional on update. LearningPathSubcategoryWithImageUpdate: type: object properties: id: type: integer readOnly: true title: type: string slug: type: string readOnly: true published: type: boolean description: type: string categories: type: array items: type: integer image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. Maximum size 10MB. learning_paths: type: array items: type: integer created_by: type: integer readOnly: true created_on: type: string format: date readOnly: true modified_by: type: integer readOnly: true modified_on: type: string format: date readOnly: true deprecated: true timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this learning path subcategory changed, including related data such as learning paths. access_type: type: string example: none|access|user|list userlist: type: array items: type: integer usergroup: type: array items: type: integer accesslevel: type: array items: type: integer description: Same shape as LearningPathSubcategoryWithImage but with no required fields - all fields are optional on update. MediaCategoryUpdate: type: object properties: id: type: integer readOnly: true example: 2 parent_id: type: integer example: 5 description: id of the parent media category. title: type: string maxLength: 255 example: My Category page_title: type: string maxLength: 255 example: text description: type: string maxLength: 4000 example: This is descriptive text published: type: boolean example: true access_type: type: string example: none enum: - none - list - user - access description: 'Note: "list" targets specific users and "user" targets user groups.' usergroup: type: array items: type: integer description: array of group ids. userlist: type: array items: type: integer description: array of user ids. accesslevel: type: array items: type: integer description: array of access level ids. description: Same shape as MediaCategory but with no required fields - all fields are optional on update. MediaItemNoDataUpdate: type: object properties: id: type: integer readOnly: true example: 2 title: type: string maxLength: 255 example: My Video speaker: type: string maxLength: 255 example: Jim Bob description: type: string maxLength: 4000 example: This is descriptive text published: type: boolean example: true go_live_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). archive_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). use_expiration: type: boolean example: false custom_id: type: string example: ABC123 expiration_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). category: type: integer example: 5 subcategory: type: integer example: 6 media_type: type: string example: video enum: - video - audio - pdf - link video_type: type: string example: mp4 description: Required if media_type is video. enum: - mp4 - youtube - screencast - facebook - vimeo youtube_id: type: string example: DOWDNBu9DkU description: ID of youtube video or full url. Required if video_type is youtube. screencast_id: type: string example: JnD7uBZDI0Z description: Required if video_type is screencast. facebook_url: type: string example: https://facebook.com/johnd description: Required if video_type is facebook. vimeo_id: type: string example: https://vimeo.com/johndoe description: ID of vimeo video or full url. Required if video_type is vimeo. interactive_source: type: string example: http://interactivesource.com description: must be a full URL. Required if media_type is link. access_type: type: string example: none description: 'Visibility Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access access_purchase_type: type: string example: none description: 'Access Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access usergroup: type: array items: type: integer description: array of group ids. Required if access_type is user. userlist: type: array items: type: integer description: array of user ids. Required if access_type is list. accesslevel: type: array items: type: integer description: array of access level ids. Required if access_type is access. usergroup_purchase_register: type: array items: type: integer description: array of group ids. Required if access_purchase_type is user. userlist_purchase_register: type: array items: type: integer description: array of user ids. Required if access_purchase_type is list. accesslevel_purchase_register: type: array items: type: integer description: array of access level ids. Required if access_purchase_type is access. tags: type: array items: type: string description: Same shape as MediaItemNoData but with no required fields - all fields are optional on update. MediaItemUpdate: type: object properties: id: type: integer readOnly: true example: 2 title: type: string maxLength: 255 example: My Video speaker: type: string maxLength: 255 example: Jim Bob description: type: string maxLength: 4000 example: This is descriptive text published: type: boolean example: true go_live_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). archive_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). use_expiration: type: boolean example: false custom_id: type: string example: ABC123 expiration_date: type: string example: '2026-07-30 12:00:00' pattern: ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ description: Must be YYYY-MM-DD HH:MM:SS (a date-only value is rejected). category: type: integer example: 5 subcategory: type: integer example: 6 media_type: type: string example: video enum: - video - audio - pdf - link video_type: type: string example: mp4 description: Required if media_type is video. enum: - mp4 - youtube - screencast - facebook - vimeo source: type: string format: binary description: audio file, video file, or pdf. Required if media_type is video, audio, or PDF. thumbnail_image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. cover_image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. youtube_id: type: string example: DOWDNBu9DkU description: ID of youtube video or full url. Required if video_type is youtube. screencast_id: type: string example: DOWDNBu9DkU description: Required if video_type is screencast. facebook_url: type: string example: DOWDNBu9DkU description: Required if video_type is facebook. vimeo_id: type: string example: DOWDNBu9DkU description: ID of vimeo video or full url. Required if video_type is vimeo. interactive_source: type: string example: http://something.com description: must be a full URL. Required if media_type is link. access_type: type: string example: none description: 'Visibility Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access access_purchase_type: type: string example: none description: 'Access Permission Type. Note: "list" targets specific users and "user" targets user groups.' enum: - none - list - user - access usergroup: type: array items: type: integer description: array of group ids. Required if access_type is user. userlist: type: array items: type: integer description: array of user ids. Required if access_type is list. accesslevel: type: array items: type: integer description: array of access level ids. Required if access_type is access. usergroup_purchase_register: type: array items: type: integer description: array of group ids. Required if access_purchase_type is user. userlist_purchase_register: type: array items: type: integer description: array of user ids. Required if access_purchase_type is list. accesslevel_purchase_register: type: array items: type: integer description: array of access level ids. Required if access_purchase_type is access. tags: type: array items: type: string created_on: type: string format: date example: YYYY-mm-dd description: Same shape as MediaItem but with no required fields - all fields are optional on update. EventUpdate: type: object properties: id: type: integer readOnly: true example: 1 parent_id: description: When creating a recurring event several 'child' events are created, each with a date and title based on the recurring settings and the title of the parent event. If an event has parent_id = 0 then it is a parent and may or may not have children. type: integer category_id: type: integer secondary_category_ids: type: array items: type: integer description: IDs of secondary categories assigned to this event. readOnly: true location_id: type: integer title: type: string example: My Event registration_type: type: integer example: 0 description: 0 - Both Individual and Group Registration, 1 - Only Individual Registration, 2 - Only Group Registration, 3 - Disable Registration. view_access: type: array items: type: integer description: ids of the groups that can view this course. example: [1] registration_access: type: array items: type: integer description: ids of the groups that can register for this course. example: [1] event_date: type: string example: '2026-08-29 12:00:00' description: Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. event_end_date: type: string example: '2026-08-29 12:00:00' description: Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. short_description: type: string description: type: string individual_price: type: number format: float event_capacity: type: integer created_by: type: integer description: User id. example: 1620265 readOnly: true cut_off_date: type: string description: Registration end date. Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. example: '2026-08-29 12:00:00' published: type: boolean featured: type: boolean registration_start_date: type: string description: Registration start date. Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. example: '2026-08-29 12:00:00' alias: type: string description: Unique URI for use in Search Engine Friendly urls pattern: '[a-z-]+' example: my-event language: type: string enable_auto_reminder: type: boolean description: If set to 'true' registrants will get auto reminder emails for this event. image: type: string readOnly: true timezone: type: string virtual_classroom_id: type: string example: B0C4D939-AF12-43D8-82B3-0A68D423F894 readOnly: true virtual_classroom_uri: type: string description: uri of virtual classroom that can be used for linking directly to virtual classroom readOnly: true request_register: type: boolean readOnly: true request_team: type: boolean readOnly: true request_instructor: type: boolean readOnly: true instructor_ids: type: array readOnly: true items: type: integer allow_to_cancel: type: boolean readOnly: true cancel_before_date: type: string format: date nullable: true description: Only present when allow_to_cancel is true. readOnly: true registration_count: type: integer readOnly: true description: Total number of registrants for this event. checked_in_count: type: integer readOnly: true description: Total number of checked-in registrants for this event. waitlist_count: type: integer readOnly: true description: Total number of waitlisted registrants for this event. sub_capacities: type: array readOnly: true items: $ref: "#/components/schemas/EventSubCapacity" custom_fields: type: array readOnly: true items: $ref: '#/components/schemas/CustomFieldValueResponse' timestamp_modified: type: string format: date-time readOnly: true description: Reflects the last time anything about this event changed, including related data such as registrations. description: Same shape as Event but with no required fields - all fields are optional on update. EventWithImageUpdate: type: object properties: id: type: integer readOnly: true example: 1 parent_id: description: When creating a recurring event several 'child' events are created, each with a date and title based on the recurring settings and the title of the parent event. If an event has parent_id = 0 then it is a parent and may or may not have children. type: integer category_id: type: integer secondary_category_ids: type: array items: type: integer description: IDs of secondary categories assigned to this event. readOnly: true location_id: type: integer title: type: string example: My Event registration_type: type: integer example: 0 description: 0 - Both Individual and Group Registration, 1 - Only Individual Registration, 2 - Only Group Registration, 3 - Disable Registration. view_access: type: array items: type: integer description: ids of the groups that can view this course. registration_access: type: array items: type: integer description: ids of the groups that can register for this course. event_date: type: string example: '2026-08-29 12:00:00' description: Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. event_end_date: type: string example: '2026-08-29 12:00:00' description: Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. short_description: type: string description: type: string individual_price: type: number format: float event_capacity: type: integer created_by: type: integer description: User id. example: 1620265 readOnly: true cut_off_date: type: string description: Registration end date. Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. example: '2026-08-29 12:00:00' published: type: boolean featured: type: boolean registration_start_date: type: string description: Registration start date. Accepts YYYY-MM-DD or YYYY-MM-DD HH:MM:SS; responses include the time component. example: '2026-08-29 12:00:00' alias: type: string description: Unique URI for use in Search Engine Friendly urls. pattern: "[a-z-]+" language: type: string enable_auto_reminder: type: boolean description: If set to 'true' registrants will get auto reminder emails for this event. image: type: string format: binary description: Supported file types - jpg,png,jpeg,gif. Maximum size 10MB. timezone: type: string example: America/New_York description: Same shape as EventWithImage but with no required fields - all fields are optional on update. SubscriptionUpdate: type: object properties: id: type: integer readOnly: true example: 1 title: type: string published: type: boolean private: type: boolean featured: type: boolean default_sub_length: type: string description: Default length of the subscription period. Valid values are 1-15D, 1-12M, and 1-5Y example: 1D default_initial_amount: type: number description: Amount of money (in USD) that the subscription will cost on signup. format: float default_amount: type: number description: Amount of money (in USD) that the subscription will cost when the subscription period length has elapsed and the subscription is renewed. format: float usergroups: type: array items: type: integer description: Array of user groups for which this subscription will be available. description_html: type: string description: Plain text or HTML-formatted description that describes the subscription. description_type: type: string description: Description type. type: type: string description: type: string timestamp_created: type: string format: date-time readOnly: true timestamp_modified: type: string format: date-time readOnly: true description: Same shape as Subscription but with no required fields - all fields are optional on update. SuccessMessage: type: object properties: success: type: string example: Entity id = 1 deleted Message: type: object properties: message: type: string SubscribeResult: type: object properties: success: type: string subscription_id: type: integer nullable: true description: Present for paid plans. payment_id: type: integer nullable: true description: Present for paid plans. ValidationError: type: object properties: errors: type: array items: type: string example: errors: - The title field is required. UnprocessableEntityError: type: object properties: message: type: string description: The first validation message, followed by a count of any others. errors: type: object description: Validation messages keyed by the request field that failed. additionalProperties: type: array items: type: string example: message: The label field is required. (and 1 more error) errors: label: - The label field is required. type_id: - The type id field is required. ForbiddenError: type: object properties: Forbidden: type: string example: Forbidden: Access Denied NotFoundError: type: object properties: error: type: string example: error: Entity id = 1 not found