Google Docs to Forms - Formswrite.com logo
BlogPricing

Moodle API: Create Users, Courses, and Enrol Students (Code Examples)

Formswrite Team

February 15, 2026

Moodle API: Create Users, Courses, and Enrol Students (Code Examples)

Moodle API: Create Users, Courses, and Enrol Students

This guide covers the most common Moodle API operations with complete code examples: creating users, creating courses, enrolling students, and retrieving data.

Prerequisites

Before using these examples, make sure you have:
  1. Web services enabled in Site Administration → Advanced features
  2. REST protocol enabled in Site Administration → Plugins → Web services → Manage protocols
  3. An API token created in Site Administration → Plugins → Web services → Manage tokens
  4. A web service with the required functions assigned

Create Users: core_user_create_users

The core_user_create_users function creates one or more user accounts.

Required Fields

FieldTypeDescription
usernamestringUnique login name
passwordstringMust meet password policy
firstnamestringFirst name
lastnamestringLast name
emailstringEmail address

cURL Example

bashcurl -X POST "https://your-moodle.com/webservice/rest/server.php" \
  -d "wstoken=YOUR_TOKEN" \
  -d "wsfunction=core_user_create_users" \
  -d "moodlewsrestformat=json" \
  -d "users[0][username]=jane.smith" \
  -d "users[0][password]=SecurePass123!" \
  -d "users[0][firstname]=Jane" \
  -d "users[0][lastname]=Smith" \
  -d "users[0][email][email protected]" \
  -d "users[0][auth]=manual"

Response

json[
  {
    "id": 15,
    "username": "jane.smith"
  }
]

Python: Create Multiple Users

pythonimport requests

MOODLE_URL = "https://your-moodle.com/webservice/rest/server.php"
TOKEN = "your_token"

students = [
    {"username": "alice.j", "firstname": "Alice", "lastname": "Johnson", "email": "[email protected]", "password": "Pass123!"},
    {"username": "bob.w", "firstname": "Bob", "lastname": "Williams", "email": "[email protected]", "password": "Pass456!"},
    {"username": "carol.d", "firstname": "Carol", "lastname": "Davis", "email": "[email protected]", "password": "Pass789!"},
]

data = {
    "wstoken": TOKEN,
    "wsfunction": "core_user_create_users",
    "moodlewsrestformat": "json",
}

for i, student in enumerate(students):
    for key, value in student.items():
        data[f"users[{i}][{key}]"] = value

response = requests.post(MOODLE_URL, data=data)
created_users = response.json()

for user in created_users:
    print(f"Created user: {user['username']} (ID: {user['id']})")

PHP Example

php$token = 'YOUR_TOKEN';
$url = 'https://your-moodle.com/webservice/rest/server.php';

$params = [
    'wstoken' => $token,
    'wsfunction' => 'core_user_create_users',
    'moodlewsrestformat' => 'json',
    'users' => [
        [
            'username' => 'jane.smith',
            'password' => 'SecurePass123!',
            'firstname' => 'Jane',
            'lastname' => 'Smith',
            'email' => '[email protected]',
        ]
    ]
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = json_decode(curl_exec($ch));
curl_close($ch);

Get All Users: core_user_get_users

Get Users by Email

bashcurl "https://your-moodle.com/webservice/rest/server.php?wstoken=YOUR_TOKEN&wsfunction=core_user_get_users&moodlewsrestformat=json&criteria[0][key]=email&criteria[0][value][email protected]"

Get Users by Username

bashcurl "https://your-moodle.com/webservice/rest/server.php?wstoken=YOUR_TOKEN&wsfunction=core_user_get_users_by_field&moodlewsrestformat=json&field=username&values[0]=alice.j&values[1]=bob.w"

Python: List All Users

pythonresponse = requests.get(MOODLE_URL, params={
    "wstoken": TOKEN,
    "wsfunction": "core_user_get_users",
    "moodlewsrestformat": "json",
    "criteria[0][key]": "email",
    "criteria[0][value]": "%@school.edu"
})

users = response.json()["users"]
for user in users:
    print(f"{user['id']}: {user['firstname']} {user['lastname']} ({user['email']})")

Create Courses: core_course_create_courses

Required Fields

FieldTypeDescription
fullnamestringFull course name
shortnamestringShort identifier (unique)
categoryidintCategory ID (1 = Miscellaneous)

cURL Example

bashcurl -X POST "https://your-moodle.com/webservice/rest/server.php" \
  -d "wstoken=YOUR_TOKEN" \
  -d "wsfunction=core_course_create_courses" \
  -d "moodlewsrestformat=json" \
  -d "courses[0][fullname]=Biology 101 - Introduction to Biology" \
  -d "courses[0][shortname]=BIO101" \
  -d "courses[0][categoryid]=1" \
  -d "courses[0][summary]=An introductory course covering cell biology, genetics, and evolution." \
  -d "courses[0][format]=topics" \
  -d "courses[0][numsections]=12"

Response

json[
  {
    "id": 5,
    "shortname": "BIO101"
  }
]

Python: Create Multiple Courses

pythoncourses = [
    {"fullname": "Biology 101", "shortname": "BIO101", "categoryid": 1},
    {"fullname": "Chemistry 201", "shortname": "CHEM201", "categoryid": 1},
    {"fullname": "Physics 301", "shortname": "PHYS301", "categoryid": 1},
]

data = {
    "wstoken": TOKEN,
    "wsfunction": "core_course_create_courses",
    "moodlewsrestformat": "json",
}

for i, course in enumerate(courses):
    for key, value in course.items():
        data[f"courses[{i}][{key}]"] = value

response = requests.post(MOODLE_URL, data=data)
print(response.json())

Get All Courses: core_course_get_courses

bashcurl "https://your-moodle.com/webservice/rest/server.php?wstoken=YOUR_TOKEN&wsfunction=core_course_get_courses&moodlewsrestformat=json"

Python

pythonresponse = requests.get(MOODLE_URL, params={
    "wstoken": TOKEN,
    "wsfunction": "core_course_get_courses",
    "moodlewsrestformat": "json"
})

for course in response.json():
    print(f"Course {course['id']}: {course['fullname']} ({course['shortname']})")

Enrol Users: enrol_manual_enrol_users

Moodle Role IDs

Role IDRole
1Manager
2Course Creator
3Teacher
4Non-editing Teacher
5Student

cURL: Enrol a Student

bashcurl -X POST "https://your-moodle.com/webservice/rest/server.php" \
  -d "wstoken=YOUR_TOKEN" \
  -d "wsfunction=enrol_manual_enrol_users" \
  -d "moodlewsrestformat=json" \
  -d "enrolments[0][roleid]=5" \
  -d "enrolments[0][userid]=15" \
  -d "enrolments[0][courseid]=5"

Python: Bulk Enrol Students

pythonstudent_ids = [15, 16, 17, 18, 19]
course_id = 5

data = {
    "wstoken": TOKEN,
    "wsfunction": "enrol_manual_enrol_users",
    "moodlewsrestformat": "json",
}

for i, uid in enumerate(student_ids):
    data[f"enrolments[{i}][roleid]"] = 5
    data[f"enrolments[{i}][userid]"] = uid
    data[f"enrolments[{i}][courseid]"] = course_id

response = requests.post(MOODLE_URL, data=data)
print("Enrolment complete" if response.status_code == 200 else "Error")

Complete Workflow: Create Course, Users, and Enrol

pythonimport requests

MOODLE_URL = "https://your-moodle.com/webservice/rest/server.php"
TOKEN = "your_token"

# Step 1: Create the course
course_data = {
    "wstoken": TOKEN,
    "wsfunction": "core_course_create_courses",
    "moodlewsrestformat": "json",
    "courses[0][fullname]": "Biology 101",
    "courses[0][shortname]": "BIO101-2026",
    "courses[0][categoryid]": 1,
}
course_response = requests.post(MOODLE_URL, data=course_data).json()
course_id = course_response[0]["id"]
print(f"Created course: {course_id}")

# Step 2: Create students
students = [
    {"username": "s1", "firstname": "Alice", "lastname": "A",
     "email": "[email protected]", "password": "P@ss1234!"},
    {"username": "s2", "firstname": "Bob", "lastname": "B",
     "email": "[email protected]", "password": "P@ss1234!"},
]

user_data = {
    "wstoken": TOKEN,
    "wsfunction": "core_user_create_users",
    "moodlewsrestformat": "json",
}
for i, s in enumerate(students):
    for k, v in s.items():
        user_data[f"users[{i}][{k}]"] = v

user_response = requests.post(MOODLE_URL, data=user_data).json()
user_ids = [u["id"] for u in user_response]
print(f"Created users: {user_ids}")

# Step 3: Enrol students
enrol_data = {
    "wstoken": TOKEN,
    "wsfunction": "enrol_manual_enrol_users",
    "moodlewsrestformat": "json",
}
for i, uid in enumerate(user_ids):
    enrol_data[f"enrolments[{i}][roleid]"] = 5
    enrol_data[f"enrolments[{i}][userid]"] = uid
    enrol_data[f"enrolments[{i}][courseid]"] = course_id

requests.post(MOODLE_URL, data=enrol_data)
print("All students enrolled!")

Adding Quizzes to Your Courses

Once your courses and users are set up via the Moodle API, the next step is adding assessments. While the Moodle API handles user and course management well, creating quiz questions programmatically is complex.
The easiest way to add quizzes is with Formswrite:
  1. Write your quiz in a Google Doc
  2. Convert to Moodle XML via the Formswrite API or web interface
  3. Import the XML into your course's Question Bank
This pairs perfectly with the Moodle API workflow: use the Moodle API for users and courses, and Formswrite for quiz content.

FAQ

What is core_user_create_users?

core_user_create_users is the Moodle Web Services function for creating new user accounts. It accepts an array of user objects with fields like username, password, firstname, lastname, and email.

Can I create users without passwords?

No. The password field is required and must meet your Moodle site's password policy.

What role ID should I use for students?

Role ID 5 is the default Student role. Use 3 for Teachers and 1 for Managers.

Can I bulk enrol from a CSV?

The Moodle API doesn't have a CSV upload endpoint, but you can read a CSV in your script and call enrol_manual_enrol_users with the data.

Summary

The Moodle API makes it easy to automate user creation, course setup, and enrolment. For quiz content, pair it with Formswrite to convert Google Docs into Moodle XML files automatically.

Share this post with your network


Formswrite - Google Docs to Forms Converter

Create forms in seconds, not hours

Convert Google Docs to Forms with one click

Save hours on quiz creation every month.

No more manual form creation. No more formatting hassles.

We care about your data in our privacy policy

© 2026 Formswrite. All Rights Reserved.