I am attempting to use the API to enrol users into the demo course, but it does not seem to work. I get this returned to me, but when I go to the studio backend and look to see if the admin user has been enrolled, that user is not enrolled.
Can anyone help me with this? I have been at this for 12 hours and have gotten nowhere.
# Default course to enroll in
DEFAULT_COURSE_ID = "course-v1:OpenedX+DemoX+DemoCourse"
# === Step 1: Get OAuth2 Access Token ===
def get_access_token():
"""
Obtain an OAuth2 bearer token via Resource Owner Password Credentials.
"""
url = f"{LMS_BASE_URL}/oauth2/access_token/"
data = {
"grant_type": "password",
"username": USERNAME,
"password": PASSWORD,
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET
}
resp = requests.post(url, data=data)
resp.raise_for_status()
token = resp.json().get("access_token")
if not token:
raise ValueError("No access token in response")
return token
# === Step 2: Enroll User and Activate ===
def enroll_user(token: str, course_id: str, username: str, mode: str = "audit"):
"""
Enroll a user and mark them active by sending a GET request to:
/api/enrollment/v1/enrollment/{username},{course_id}?mode={mode}&is_active=true
Handles empty responses gracefully and prints full JSON.
"""
# URL-encode identifiers, preserving comma
user_enc = urllib.parse.quote(username, safe=',')
course_enc = urllib.parse.quote(course_id, safe=',')
# include is_active flag
url = (
f"{LMS_BASE_URL}/api/enrollment/v1/enrollment/"
f"{user_enc},{course_enc}?mode={mode}&is_active=true"
)
headers = {"Authorization": f"Bearer {token}"}
print(f"GET {url}")
resp = requests.get(url, headers=headers)
resp.raise_for_status()
try:
data = resp.json()
except ValueError:
data = {"status": resp.status_code, "detail": resp.text or "No content"}
return data
# === Step 3: Interactive Prompt ===
def main():
print("=== Open edX Enrollment Script ===")
course = input(f"Course ID [{DEFAULT_COURSE_ID}]: ").strip() or DEFAULT_COURSE_ID
user = None
while not user:
user = input("Username/email: ").strip()
valid = ["audit", "honor", "verified"]
mode = input("Mode (audit/honor/verified) [audit]: ").strip().lower() or "audit"
if mode not in valid:
print(f"Invalid mode '{mode}', using 'audit'.")
mode = "audit"
token = get_access_token()
result = enroll_user(token, course, user, mode)
# Print all JSON fields returned
print("\nEnrollment Result JSON:")
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()
=== Open edX Enrollment Script ===
Course ID [course-v1:OpenedX+DemoX+DemoCourse]:
Username/email: admin
Mode (audit/honor/verified) [audit]:
GET https://learn.codeblue.studio/api/enrollment/v1/enrollment/admin,course-v1%3AOpenedX%2BDemoX%2BDemoCourse?mode=audit&is_active=true
Enrollment Result JSON:
{
"created": "2025-07-16T20:51:10.972018Z",
"mode": "audit",
"is_active": false,
"course_details": {
"course_id": "course-v1:OpenedX+DemoX+DemoCourse",
"course_name": "Open edX Demo Course",
"enrollment_start": null,
"enrollment_end": null,
"course_start": "2020-01-01T00:00:00Z",
"course_end": null,
"invite_only": false,
"course_modes": [
{
"slug": "audit",
"name": "Audit",
"min_price": 0,
"suggested_prices": "",
"currency": "usd",
"expiration_datetime": null,
"description": null,
"sku": null,
"bulk_sku": null
}
],
"pacing_type": "Self Paced"
},
"user": "admin"
}
Process finished with exit code 0