Loopwise Docs
Admin APIMutations

Course Mutations

Mutation operations for managing courses and student enrollments in your Loopwise school

The course mutations allow you to create, update, and delete courses within your Loopwise school, as well as manage student enrollments. These operations enable you to programmatically manage your course catalog and student access.

Course entity mutations:

  • createCourse — Creates a new course
  • updateCourse — Updates an existing course
  • deleteCourse — Deletes a course

Enrollment mutations:

  • enrollStudentToCourse — Enrolls a student to a course or updates an existing enrollment
  • removeStudentFromCourse — Removes a student's enrollment from a course
  • expireStudentCourseAccess — Marks a student's course access as expired
  • extendStudentCourseAccess — Extends a student's access to a course

All course mutations return an errors field in the response that will contain any validation or processing errors that occurred during the operation.


Create a Course

The createCourse mutation allows you to create a new course in your school with the specified properties.

Input Parameters

FieldTypeDescription
inputAdminCourseInput!Input object containing course creation details

AdminCourseInput Fields

FieldTypeRequiredDescription
nameString!YesCourse name
slugString!YesURL slug for the course. Must contain only lowercase letters, numbers, and hyphens
courseTypeString!YesType of the course (paid, public_access, free_redeem, pre_order)
descriptionStringNoCourse description
categoryIds[String!]NoIDs of categories to associate with this course
tagList[String!]NoTags to associate with this course

Return Type

type AdminCourseCreatePayload {
  # The created course object, null if operation failed
  course: AdminCourse

  # Array of error messages, if any occurred during the operation
  errors: [String!]
}

Example

mutation CreateCourse {
  createCourse(input: {
    name: "GraphQL Fundamentals"
    slug: "graphql-fundamentals"
    courseType: "paid"
    description: "Learn the basics of GraphQL API development"
    categoryIds: ["cat_123"]
    tagList: ["graphql", "api", "development"]
  }) {
    course {
      id
      name
      slug
      courseType
      description
    }
    errors
  }
}

Sample Response

{
  "data": {
    "createCourse": {
      "course": {
        "id": "course_12345",
        "name": "GraphQL Fundamentals",
        "slug": "graphql-fundamentals",
        "courseType": "paid",
        "description": "Learn the basics of GraphQL API development"
      },
      "errors": []
    }
  }
}

Common Errors

ErrorDescription
Name cannot be emptyThe course name is required
Slug already existsThe provided slug is already in use
Invalid course typeThe courseType must be one of: paid, public_access, free_redeem, pre_order
Category not foundOne or more category IDs do not exist

Update a Course

The updateCourse mutation allows you to update an existing course with new properties in your Loopwise school.

Input Parameters

FieldTypeDescription
idString!ID of the course to update
inputAdminCourseInput!Input object containing course update details

AdminCourseInput Fields

FieldTypeRequiredDescription
nameString!YesCourse name
slugString!YesURL slug for the course. Must contain only lowercase letters, numbers, and hyphens
courseTypeString!YesType of the course (paid, public_access, free_redeem, pre_order)
descriptionStringNoCourse description
categoryIds[String!]NoIDs of categories to associate with this course
tagList[String!]NoTags to associate with this course

Return Type

type AdminCourseUpdatePayload {
  # The updated course object, null if operation failed
  course: AdminCourse

  # Array of error messages, if any occurred during the operation
  errors: [String!]
}

Example

mutation UpdateCourse {
  updateCourse(
    id: "course_12345"
    input: {
      name: "Advanced GraphQL Fundamentals"
      slug: "advanced-graphql-fundamentals"
      courseType: "paid"
      description: "Learn advanced GraphQL concepts and patterns"
      categoryIds: ["cat_123", "cat_456"]
      tagList: ["graphql", "advanced", "api"]
    }
  ) {
    course {
      id
      name
      slug
      courseType
      description
      categories {
        id
        name
      }
      tags
    }
    errors
  }
}

Sample Response

{
  "data": {
    "updateCourse": {
      "course": {
        "id": "course_12345",
        "name": "Advanced GraphQL Fundamentals",
        "slug": "advanced-graphql-fundamentals",
        "courseType": "paid",
        "description": "Learn advanced GraphQL concepts and patterns",
        "categories": [
          {
            "id": "cat_123",
            "name": "Programming"
          },
          {
            "id": "cat_456",
            "name": "Web Development"
          }
        ],
        "tags": ["graphql", "advanced", "api"]
      },
      "errors": []
    }
  }
}

Common Errors

ErrorDescription
Course not foundThe specified course ID does not exist
Name cannot be emptyThe course name is required
Slug already existsThe provided slug is already in use by another course
Invalid course typeThe courseType must be one of: paid, public_access, free_redeem, pre_order
Category not foundOne or more category IDs do not exist

Delete a Course

The deleteCourse mutation allows you to delete a course if no active enrollments exist.

Note: This mutation is still under development and will be fully documented when available.


Enroll a Student to a Course

The enrollStudentToCourse mutation allows you to enroll a student to a specified course, or update existing enrollment details. For paid or pre-order courses, this mutation automatically creates payment records using the specified curriculum plan's pricing information.

Input Parameters

FieldTypeRequiredDescription
userIdStringNo*ID of the student (User) to enroll
emailStringNo*Email of the student. If user doesn't exist, a placeholder user will be created
nameStringNoName of the student. Required when creating a new user
courseIdString!YesID of the course to enroll the student into
planIdStringNoID of the curriculum plan to apply to this enrollment. If not provided, will use the course's first plan (ordered by creation date). For paid/pre-order courses, the plan's amount and currency are used to create the payment record
endedAtIntNoOptional expiration date for the enrollment (Unix Timestamp)

*Either userId or email must be provided.

Return Type

type AdminEnrollStudentToCoursePayload {
  # The created or updated enrollment
  enrollment: StudentCourseShip
}

StudentCourseShip Object

FieldTypeDescription
idString!ID of the enrollment
completionRateFloatThe completion rate of the enrolled course which student achieved
courseAdminCourse!Information of the enrolled course
userAdminUser!User information of the enrolled course
createdAtInt!Created date of the enrollment (Unix Timestamp)
updatedAtInt!Last updated date of the enrollment (Unix Timestamp)
endedAtIntExpiration date for the enrollment (Unix Timestamp)

Example — Enroll a New Student

mutation EnrollNewStudent {
  enrollStudentToCourse(
    courseId: "ab6ee332-614d-475d-93b5-abc5ebb1fc84"
    email: "student@example.com"
    name: "John Doe"   # Required when creating a new user
  ) {
    enrollment {
      id
      completionRate
      createdAt
      updatedAt
      endedAt
      course {
        id
        name
        slug
      }
      user {
        id
        name
        email
      }
    }
  }
}

Example — Enroll Student to a Paid Course with Specific Plan

mutation EnrollStudentToPaidCourse {
  enrollStudentToCourse(
    courseId: "paid-course-123"
    email: "premium.student@example.com"
    name: "Premium Student"
    planId: "premium-plan-456"
    endedAt: 1735689600
  ) {
    enrollment {
      id
      completionRate
      endedAt
      course {
        id
        name
      }
      user {
        id
        name
        email
      }
    }
  }
}

Note: For paid or pre-order courses, this mutation creates a payment record with amount and currency from the specified plan, status set to manual_enrolled, and a lineitem linking to the curriculum plan. For free or redeem courses, no payment record is created. If the student is already enrolled in a paid/pre-order course, the mutation returns the existing enrollment without creating a new payment.

Sample Response

{
  "data": {
    "enrollStudentToCourse": {
      "enrollment": {
        "id": "619ad939-8591-40ad-9364-cf3825a9bf70",
        "completionRate": 0.0,
        "createdAt": 1672531200,
        "updatedAt": 1672531200,
        "endedAt": null,
        "course": {
          "id": "ab6ee332-614d-475d-93b5-abc5ebb1fc84",
          "name": "Introduction to GraphQL",
          "slug": "intro-graphql"
        },
        "user": {
          "id": "387b0c87-0f85-44cc-833e-7306c1b5d3e6",
          "name": "John Doe",
          "email": "student@example.com"
        }
      }
    }
  }
}

Common Errors

ErrorDescription
Either user_id or email must be providedAt least one identifier must be provided
Name is required when creating a new userRequired when creating a new user via email
Course not foundThe specified course ID does not exist
User not foundThe specified user ID does not exist
Public access courses don't require enrollmentPublic access courses don't require enrollment
No valid plan found for this courseThe specified planId is invalid for this course

Remove a Student from a Course

The removeStudentFromCourse mutation allows you to completely remove a student's enrollment from a specified course. This action revokes the student's access to course content and removes all enrollment records.

Input Parameters

FieldTypeRequiredDescription
userIdString!YesID of the student (User) to remove from the course
courseIdString!YesID of the course to remove the student from

Return Type

type AdminRemoveStudentFromCoursePayload {
  # Additional information about the operation result
  message: String

  # Indicates whether the removal was successful
  success: Boolean!
}

Example

mutation RemoveStudentFromCourse {
  removeStudentFromCourse(
    userId: "a1b2c3d4-5678-90ef-ghij-klmnopqrstuv"
    courseId: "ab6ee332-614d-475d-93b5-abc5ebb1fc84"
  ) {
    success
    message
  }
}

Sample Response

{
  "data": {
    "removeStudentFromCourse": {
      "success": true,
      "message": "Student successfully removed from the course"
    }
  }
}

Common Errors

ErrorDescription
Student is not enrolled in this courseThe student is not enrolled in the specified course
Course not foundThe specified course ID does not exist
User not foundThe specified user ID does not exist

Extend Student Course Access

The extendStudentCourseAccess mutation allows you to extend a student's access to a course by updating the ended_at date. This is useful when you want to grant additional time for course completion.

Input Parameters

FieldTypeRequiredDescription
userIdString!YesID of the student (User) whose access should be extended
courseIdString!YesID of the course to extend access for
extensionDaysIntNo*Number of days to extend the access from the current ended_at date
newEndedAtIntNo*New expiration date as Unix Timestamp (seconds since epoch). Takes precedence over extensionDays if both are provided
indefiniteBooleanNoIf true, removes the access end date, granting unlimited access. Takes precedence over all other time parameters

*At least one of extensionDays, newEndedAt, or indefinite must be provided.

Return Type

type AdminExtendStudentCourseAccessPayload {
  # The updated enrollment with extended access
  enrollment: StudentCourseShip
}

StudentCourseShip Object

FieldTypeDescription
idString!ID of the enrollment
completionRateFloatThe completion rate of the enrolled course which student achieved
courseAdminCourse!Information of the enrolled course
userAdminUser!User information of the enrolled course
createdAtInt!Created date of the enrollment (Unix Timestamp)
updatedAtInt!Last updated date of the enrollment (Unix Timestamp)
endedAtIntExpiration date for the enrollment (Unix Timestamp). Null if indefinite access is granted

Example — Extend by Days

mutation ExtendStudentAccess {
  extendStudentCourseAccess(
    userId: "387b0c87-0f85-44cc-833e-7306c1b5d3e6"
    courseId: "9a1216f7-36de-4c50-8094-2ebfb7d3c383"
    extensionDays: 30
  ) {
    enrollment {
      id
      completionRate
      createdAt
      updatedAt
      endedAt
      course {
        id
        name
        slug
      }
      user {
        id
        name
        email
      }
    }
  }
}

Example — Set Specific End Date

mutation ExtendStudentAccessWithDate {
  extendStudentCourseAccess(
    userId: "387b0c87-0f85-44cc-833e-7306c1b5d3e6"
    courseId: "9a1216f7-36de-4c50-8094-2ebfb7d3c383"
    newEndedAt: 1735689600
  ) {
    enrollment {
      id
      endedAt
      course {
        id
        name
      }
      user {
        id
        name
      }
    }
  }
}

Example — Grant Indefinite Access

mutation GrantIndefiniteAccess {
  extendStudentCourseAccess(
    userId: "387b0c87-0f85-44cc-833e-7306c1b5d3e6"
    courseId: "9a1216f7-36de-4c50-8094-2ebfb7d3c383"
    indefinite: true
  ) {
    enrollment {
      id
      endedAt
      course {
        id
        name
      }
      user {
        id
        name
      }
    }
  }
}

Sample Response

{
  "data": {
    "extendStudentCourseAccess": {
      "enrollment": {
        "id": "619ad939-8591-40ad-9364-cf3825a9bf70",
        "completionRate": 0.5,
        "createdAt": 1672531200,
        "updatedAt": 1750076336,
        "endedAt": 1750076336,
        "course": {
          "id": "9a1216f7-36de-4c50-8094-2ebfb7d3c383",
          "name": "Introduction to GraphQL",
          "slug": "intro-graphql"
        },
        "user": {
          "id": "387b0c87-0f85-44cc-833e-7306c1b5d3e6",
          "name": "Student",
          "email": "student@example.com"
        }
      }
    }
  }
}

Common Errors

ErrorDescription
Student is not enrolled in this courseThe student is not enrolled in the specified course
Current enrollment has no end dateCannot extend an enrollment that already has indefinite access
The new end date is too far in the past. Please provide a timestamp after 2020.The provided newEndedAt date is invalid

Expire Student Course Access

The expireStudentCourseAccess mutation allows you to mark a student's course access as expired while retaining their course data. This is useful when you want to temporarily revoke a student's access without removing their progress and enrollment records.

Input Parameters

FieldTypeRequiredDescription
userIdString!YesID of the student (User) whose access should be expired
courseIdString!YesID of the course to expire access for
customEndedAtIntNoCustom expiration date as Unix Timestamp (seconds since epoch). Must be a positive integer after January 1, 2020. Defaults to current time
reasonStringNoOptional reason for expiring the access

Return Type

type AdminExpireStudentCourseAccessPayload {
  # The updated enrollment with expired access
  enrollment: StudentCourseShip
}

StudentCourseShip Object

FieldTypeDescription
idString!ID of the enrollment
completionRateFloatThe completion rate of the enrolled course which student achieved
courseAdminCourse!Information of the enrolled course
userAdminUser!User information of the enrolled course
createdAtInt!Created date of the enrollment (Unix Timestamp)
updatedAtInt!Last updated date of the enrollment (Unix Timestamp)
endedAtIntExpiration date for the enrollment (Unix Timestamp)

Example

mutation ExpireStudentAccess {
  expireStudentCourseAccess(
    userId: "a1b2c3d4-5678-90ef-ghij-klmnopqrstuv"
    courseId: "ab6ee332-614d-475d-93b5-abc5ebb1fc84"
  ) {
    enrollment {
      id
      completionRate
      createdAt
      updatedAt
      endedAt
      course {
        id
        name
        slug
      }
      user {
        id
        name
        email
      }
    }
  }
}

Example — With Custom Expiration Date

mutation ExpireStudentAccessWithCustomDate {
  expireStudentCourseAccess(
    userId: "a1b2c3d4-5678-90ef-ghij-klmnopqrstuv"
    courseId: "ab6ee332-614d-475d-93b5-abc5ebb1fc84"
    customEndedAt: 1735689600
    reason: "Course access expired due to non-payment"
  ) {
    enrollment {
      id
      endedAt
      course {
        id
        name
      }
      user {
        id
        name
      }
    }
  }
}

Sample Response

{
  "data": {
    "expireStudentCourseAccess": {
      "enrollment": {
        "id": "619ad939-8591-40ad-9364-cf3825a9bf70",
        "completionRate": 0.25,
        "createdAt": 1672531200,
        "updatedAt": 1747297936,
        "endedAt": 1747297936,
        "course": {
          "id": "9a1216f7-36de-4c50-8094-2ebfb7d3c383",
          "name": "Introduction to GraphQL",
          "slug": "intro-graphql"
        },
        "user": {
          "id": "387b0c87-0f85-44cc-833e-7306c1b5d3e6",
          "name": "Student",
          "email": "student@example.com"
        }
      }
    }
  }
}

Common Errors

ErrorDescription
Student is not enrolled in this courseThe student is not enrolled in the specified course
Course not foundThe specified course ID does not exist
User not foundThe specified user ID does not exist
The new end date is too far in the past. Please provide a timestamp after 2020.The provided customEndedAt date is invalid

On this page