openapi: 3.0.3 info: title: LearnWorlds API description: >- The LearnWorlds API (v2) is a REST API for programmatically managing an online school on the LearnWorlds course / LMS platform. It exposes school entities - users, courses, enrollments, subscriptions, payments, course progress, tags, bundles, certificates, and webhooks - over HTTPS. The API is served per-school from https://{school}.learnworlds.com/admin/api/v2 and is authenticated with OAuth2 (client credentials): a bearer access token is obtained from the school's token endpoint and every request also carries the Lw-Client header identifying the client (school) application. API and Webhook access is a plan-gated feature (Learning Center and High Volume & Corporate plans). Version 1 of the API is deprecated. Exact request/response schemas and the full endpoint catalog live in the official reference at learnworlds.dev; the paths modeled here are grounded in the public documentation, help center, and the official API wrapper, and should be reconciled against the live reference. version: '2.0' contact: name: LearnWorlds url: https://www.learnworlds.dev license: name: Proprietary url: https://www.learnworlds.com/terms-of-service/ servers: - url: https://{school}.learnworlds.com/admin/api/v2 description: Per-school API base URL variables: school: default: yourschool description: The subdomain / school identifier of your LearnWorlds academy. security: - oauth2ClientCredentials: [] lwClient: [] tags: - name: Users description: Manage school users (students / members) and their profiles. - name: Courses description: Read the school's courses and their contents. - name: Enrollments description: Enroll and unenroll users on courses, bundles, and subscriptions. - name: Payments description: Read payments, subscriptions, and transactions. - name: Progress description: Read per-user course progress and completion. - name: Tags description: List tags and attach / detach them from users. - name: Webhooks description: Manage webhook subscriptions for school events. paths: /users: get: operationId: listUsers tags: - Users summary: List users description: Lists the school's users. Supports pagination and filtering. parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/ItemsPerPage' responses: '200': description: A paginated list of users. content: application/json: schema: $ref: '#/components/schemas/UserList' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createUser tags: - Users summary: Create a user description: Creates a new user (student) in the school. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserInput' responses: '201': description: The created user. content: application/json: schema: $ref: '#/components/schemas/User' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/ValidationError' /users/{id}: parameters: - $ref: '#/components/parameters/UserId' get: operationId: getUser tags: - Users summary: Get a user description: Retrieves a single user by ID or email. responses: '200': description: The requested user. content: application/json: schema: $ref: '#/components/schemas/User' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' put: operationId: updateUser tags: - Users summary: Update a user description: Updates an existing user's profile fields. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserInput' responses: '200': description: The updated user. content: application/json: schema: $ref: '#/components/schemas/User' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/ValidationError' /users/{id}/enrollment: parameters: - $ref: '#/components/parameters/UserId' post: operationId: enrollUser tags: - Enrollments summary: Enroll a user description: >- Enrolls a user on a product - a course, bundle, or subscription. The product type and id are supplied in the request body. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EnrollmentInput' responses: '200': description: Enrollment result. content: application/json: schema: $ref: '#/components/schemas/Enrollment' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' '422': $ref: '#/components/responses/ValidationError' delete: operationId: unenrollUser tags: - Enrollments summary: Unenroll a user description: Removes a user's enrollment from a product. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/EnrollmentInput' responses: '200': description: Unenrollment confirmation. content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /users/{id}/enrollments: parameters: - $ref: '#/components/parameters/UserId' get: operationId: listUserEnrollments tags: - Enrollments summary: List a user's enrollments description: Lists all products (courses, bundles, subscriptions) a user is enrolled in. responses: '200': description: A list of the user's enrollments. content: application/json: schema: $ref: '#/components/schemas/EnrollmentList' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /users/{id}/progress: parameters: - $ref: '#/components/parameters/UserId' get: operationId: getUserProgress tags: - Progress summary: Get a user's progress description: >- Returns the user's progress and completion status across the courses they are enrolled in. responses: '200': description: The user's course progress. content: application/json: schema: $ref: '#/components/schemas/ProgressList' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /users/{id}/tags: parameters: - $ref: '#/components/parameters/UserId' post: operationId: attachUserTags tags: - Tags summary: Attach tags to a user description: Attaches one or more tags to a user. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TagInput' responses: '200': description: The user's updated tags. content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' delete: operationId: detachUserTags tags: - Tags summary: Detach tags from a user description: Detaches one or more tags from a user. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TagInput' responses: '200': description: Detach confirmation. content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /courses: get: operationId: listCourses tags: - Courses summary: List courses description: Lists the school's courses. parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/ItemsPerPage' responses: '200': description: A paginated list of courses. content: application/json: schema: $ref: '#/components/schemas/CourseList' '401': $ref: '#/components/responses/Unauthorized' /courses/{id}: parameters: - name: id in: path required: true description: The course identifier. schema: type: string get: operationId: getCourse tags: - Courses summary: Get a course description: Retrieves a single course by its identifier. responses: '200': description: The requested course. content: application/json: schema: $ref: '#/components/schemas/Course' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /courses/{id}/contents: parameters: - name: id in: path required: true description: The course identifier. schema: type: string get: operationId: getCourseContents tags: - Courses summary: Get course contents description: Retrieves the sections and learning units that make up a course. responses: '200': description: The course contents. content: application/json: schema: type: object additionalProperties: true '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' /payments: get: operationId: listPayments tags: - Payments summary: List payments description: >- Lists payment transactions for the school. A payment may include multiple products (for cart orders and bundle purchases). parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/ItemsPerPage' responses: '200': description: A paginated list of payments. content: application/json: schema: $ref: '#/components/schemas/PaymentList' '401': $ref: '#/components/responses/Unauthorized' /subscriptions: get: operationId: listSubscriptions tags: - Payments summary: List subscriptions description: Lists the school's subscriptions, including status and billing period. parameters: - $ref: '#/components/parameters/Page' - $ref: '#/components/parameters/ItemsPerPage' responses: '200': description: A paginated list of subscriptions. content: application/json: schema: $ref: '#/components/schemas/SubscriptionList' '401': $ref: '#/components/responses/Unauthorized' /webhooks: get: operationId: listWebhooks tags: - Webhooks summary: List webhooks description: Lists the configured webhook subscriptions for the school. responses: '200': description: A list of webhooks. content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Webhook' '401': $ref: '#/components/responses/Unauthorized' post: operationId: createWebhook tags: - Webhooks summary: Create a webhook description: >- Creates a webhook subscription that POSTs event payloads to a target URL when the subscribed event fires (for example course.completed, user.enrolled, payment.created). requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/WebhookInput' responses: '201': description: The created webhook. content: application/json: schema: $ref: '#/components/schemas/Webhook' '401': $ref: '#/components/responses/Unauthorized' '422': $ref: '#/components/responses/ValidationError' /webhooks/{id}: parameters: - name: id in: path required: true description: The webhook identifier. schema: type: string delete: operationId: deleteWebhook tags: - Webhooks summary: Delete a webhook description: Deletes a webhook subscription. responses: '200': description: Deletion confirmation. content: application/json: schema: $ref: '#/components/schemas/GenericSuccess' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' components: securitySchemes: oauth2ClientCredentials: type: oauth2 description: >- OAuth2 client credentials flow. Exchange your client_id and client_secret for a bearer access token at the school token endpoint, then pass it as Authorization: Bearer ACCESS_TOKEN. flows: clientCredentials: tokenUrl: https://yourschool.learnworlds.com/admin/api/oauth2/access_token scopes: {} lwClient: type: apiKey in: header name: Lw-Client description: >- Client identifier header sent on every request alongside the bearer token. Its value is your API client_id. parameters: UserId: name: id in: path required: true description: The user identifier (LearnWorlds user id or email). schema: type: string Page: name: page in: query required: false description: The page number to retrieve. schema: type: integer default: 1 ItemsPerPage: name: items_per_page in: query required: false description: The number of items to return per page. schema: type: integer default: 50 responses: Unauthorized: description: Missing or invalid access token or Lw-Client header. content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: The requested resource was not found. content: application/json: schema: $ref: '#/components/schemas/Error' ValidationError: description: The request payload failed validation. content: application/json: schema: $ref: '#/components/schemas/Error' schemas: Error: type: object properties: success: type: boolean example: false errors: type: array items: type: object properties: code: type: string message: type: string GenericSuccess: type: object properties: success: type: boolean example: true Pagination: type: object properties: page: type: integer total_items: type: integer items_per_page: type: integer total_pages: type: integer UserInput: type: object required: - email properties: email: type: string format: email username: type: string password: type: string first_name: type: string last_name: type: string tags: type: array items: type: string fields: type: object additionalProperties: true User: allOf: - $ref: '#/components/schemas/UserInput' - type: object properties: id: type: string created: type: integer description: Unix timestamp of user creation. is_admin: type: boolean tags: type: array items: type: string UserList: type: object properties: data: type: array items: $ref: '#/components/schemas/User' meta: $ref: '#/components/schemas/Pagination' Course: type: object properties: id: type: string title: type: string description: type: string access: type: string description: Access model for the course (free, paid, subscription, etc). price: type: number courseImage: type: string created: type: integer CourseList: type: object properties: data: type: array items: $ref: '#/components/schemas/Course' meta: $ref: '#/components/schemas/Pagination' EnrollmentInput: type: object required: - productId - productType properties: productId: type: string description: The id of the course, bundle, or subscription plan. productType: type: string enum: - course - bundle - subscription price: type: number description: Optional price to record for the enrollment. justification: type: string description: Optional reason recorded for the manual enrollment. send_enrollment_email: type: boolean Enrollment: type: object properties: productId: type: string productType: type: string user_id: type: string enrolled: type: boolean created: type: integer EnrollmentList: type: object properties: data: type: array items: $ref: '#/components/schemas/Enrollment' meta: $ref: '#/components/schemas/Pagination' Progress: type: object properties: course_id: type: string user_id: type: string progress_rate: type: number description: Completion percentage for the course (0-100). status: type: string enum: - not_started - in_progress - completed completed_units: type: integer total_units: type: integer ProgressList: type: object properties: data: type: array items: $ref: '#/components/schemas/Progress' meta: $ref: '#/components/schemas/Pagination' TagInput: type: object required: - tags properties: tags: type: array items: type: string Payment: type: object properties: id: type: string user_id: type: string amount: type: number currency: type: string products: type: array description: Products included in the payment (cart orders and bundle purchases can include several). items: type: object additionalProperties: true gateway: type: string created: type: integer PaymentList: type: object properties: data: type: array items: $ref: '#/components/schemas/Payment' meta: $ref: '#/components/schemas/Pagination' Subscription: type: object properties: id: type: string user_id: type: string plan_id: type: string status: type: string enum: - active - trialing - cancelled - past_due current_period_end: type: integer created: type: integer SubscriptionList: type: object properties: data: type: array items: $ref: '#/components/schemas/Subscription' meta: $ref: '#/components/schemas/Pagination' WebhookInput: type: object required: - endpoint - triggers properties: endpoint: type: string format: uri description: The URL LearnWorlds POSTs event payloads to. triggers: type: array description: The event types this webhook subscribes to. items: type: string Webhook: allOf: - $ref: '#/components/schemas/WebhookInput' - type: object properties: id: type: string active: type: boolean