Enrollment API - Nothing happens

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

Hi @lukehayes and welcome to the community!

What version of Tutor are you running? What API are you using and what docs are you looking at for help? Do you have any error logs?