Moodle LMS Administration

Moodle Web Service · Playground & Code Boilerplates

Trigger REST protocols, copy production boilerplates, explore interactive playgrounds with authentic test datasets, and follow masterclass developer practices.

Pipeline M: REST API Gateway Request Lifecycle

Client Call
curl / fetch
Params: wsfunction, token
Gateway Dispatch
webservice/rest/server.php
Authenticate Token & Client
Execution Controller
External Functions
Call API logic & return array
Output Formatter
JSON/XML Render
Enforce schema compliance

Step 1: Enable Web Services in Moodle

Before testing custom endpoints, you must enable Moodle's Web Service engines and map services. Follow this quick setup checklist inside the Moodle Admin UI:

1. Enable Global Web Services

Navigate to Site Administration > Advanced features. Search for Enable web services (enablewebservices), check the checkbox, and click Save.

2. Enable the REST Protocol

Go to Site Administration > Server > Web Services > Manage protocols. Find the REST protocol row and click the eye icon to enable it. (XML-RPC or SOAP can be left disabled).

3. Create the Custom Services

Go to External services, click Add. Create a service named Course Progress Service with shortname local_courseprogress, and check the Enabled box. Repeat for User Logins Service with shortname local_userlogins.

4. Generate User Authentication Token

Navigate to Manage tokens, select Add. Choose an administrator user or specialized integration account, link it to the Course Progress Service, and save. Copy the generated wstoken string to authenticate cURL requests.

Step 2: 13 Custom APIs Specification Playground

This section lists each custom API registered on your Moodle server, complete with details on request arguments, required security capabilities, dynamic cURL examples, and high-fidelity mock return datasets.

local_courseprogress_get_user_course_progress read

Description: Get course completion percentage and basic milestones for a specific user.

Request Arguments:
userid (int, required)
courseid (int, required)
Security Capabilities:
moodle/user:viewdetails
moodle/course:view
cURL Access Request:
curl -X POST "https://classroom.demodemo.com/webservice/rest/server.php" \
     -d "wstoken=your_service_token" \
     -d "wsfunction=local_courseprogress_get_user_course_progress" \
     -d "moodlewsrestformat=json" \
     -d "userid=42" \
     -d "courseid=3"
Sample Test Run Dataset:
{
  "userid": 42,
  "courseid": 3,
  "coursename": "Advanced Cloud Engineering",
  "progress_percentage": 78.57,
  "completed_activities": 11,
  "total_activities": 14,
  "last_accessed": 1779717317
}
local_courseprogress_get_user_all_courses_progress read

Description: Retrieve aggregated progress metrics for all courses in which a user is enrolled.

Request Arguments:
userid (int, required)
Security Capabilities:
moodle/user:viewdetails
cURL Access Request:
curl -X POST "https://classroom.demodemo.com/webservice/rest/server.php" \
     -d "wstoken=your_service_token" \
     -d "wsfunction=local_courseprogress_get_user_all_courses_progress" \
     -d "moodlewsrestformat=json" \
     -d "userid=42"
Sample Test Run Dataset:
[
  {
    "courseid": 3,
    "coursename": "Advanced Cloud Engineering",
    "progress": 78.57,
    "status": "in_progress"
  },
  {
    "courseid": 5,
    "coursename": "Enterprise Linux Systems Tuning",
    "progress": 100.00,
    "status": "completed"
  }
]
local_courseprogress_get_course_progress_details read

Description: Get detailed course progress quiz and assignment marks.

Request Arguments:
userid (int, required)
courseid (int, required)
Security Capabilities:
moodle/user:viewdetails
moodle/grade:viewall
cURL Access Request:
curl -X POST "https://classroom.demodemo.com/webservice/rest/server.php" \
     -d "wstoken=your_service_token" \
     -d "wsfunction=local_courseprogress_get_course_progress_details" \
     -d "moodlewsrestformat=json" \
     -d "userid=42" \
     -d "courseid=3"
Sample Test Run Dataset:
{
  "courseid": 3,
  "userid": 42,
  "activities": [
    {
      "moduleid": 101,
      "name": "MariaDB Tuning Quiz",
      "type": "quiz",
      "completed": true,
      "grade": "95.00",
      "maxgrade": "100.00"
    },
    {
      "moduleid": 102,
      "name": "NFS Enterprise Lab Submission",
      "type": "assign",
      "completed": false,
      "grade": null,
      "maxgrade": "100.00"
    }
  ]
}

Step 3: Interactive REST API Test Console

Simulate live API triggers directly from your browser! Select an API endpoint, configure your mock query tokens or user IDs, and run execution loops to view formatted JSON payloads instantly.

Live Client Request (cURL):
curl -X POST "https://classroom.demodemo.com/webservice/rest/server.php" \
  -d "wstoken=ws_tok_2026_demo_classroom" \
  -d "wsfunction=local_courseprogress_get_user_course_progress" \
  -d "userid=42" \
  -d "courseid=3"
REST Gateway Response JSON (Latency: --):
{
  "click": "Execute Query to see mock results..."
}

Step 4: Core Moodle APIs (Must-Know Specs)

In addition to writing your own custom plugins, every enterprise developer must integrate Moodle's built-in system APIs to handle common student provisioning, enrollments, and grading routines.

core_user_create_users write

Description: Provision new student or teacher accounts programmatically. Ideal for syncing accounts from external HR/LMS databases.

Request Arguments:
users[0][username] (string, required)
users[0][password] (string, required)
users[0][email] (string, required)
users[0][firstname] (string, required)
users[0][lastname] (string, required)
Security Capabilities:
moodle/user:create
cURL Access Request:
curl -X POST "https://classroom.demodemo.com/webservice/rest/server.php" \
     -d "wstoken=your_service_token" \
     -d "wsfunction=core_user_create_users" \
     -d "moodlewsrestformat=json" \
     -d "users[0][username]=akash99" \
     -d "users[0][password]=SecurePass123!" \
     -d "users[0][email]=akash@example.com" \
     -d "users[0][firstname]=Akash" \
     -d "users[0][lastname]=Kumar"
Sample Return Dataset:
[
  {
    "id": 142,
    "username": "akash99"
  }
]
core_enrol_enrol_users write

Description: Enrolls an authenticated user inside a course with manual enrolment roles (e.g. Student role ID 5, Teacher role ID 3).

Request Arguments:
enrolments[0][roleid] (int, required)
enrolments[0][userid] (int, required)
enrolments[0][courseid] (int, required)
Security Capabilities:
enrol/manual:enrol
cURL Access Request:
curl -X POST "https://classroom.demodemo.com/webservice/rest/server.php" \
     -d "wstoken=your_service_token" \
     -d "wsfunction=core_enrol_enrol_users" \
     -d "moodlewsrestformat=json" \
     -d "enrolments[0][roleid]=5" \
     -d "enrolments[0][userid]=142" \
     -d "enrolments[0][courseid]=3"
Sample Return Dataset:
null
mod_assign_save_grade write

Description: Submits quiz or assignment grades from external platforms directly into Moodle's gradebook.

Request Arguments:
assignmentid (int, required)
userid (int, required)
grade (float, required)
attemptnumber (int, required)
workflowstate (string, optional)
Security Capabilities:
mod/assign:grade
cURL Access Request:
curl -X POST "https://classroom.demodemo.com/webservice/rest/server.php" \
     -d "wstoken=your_service_token" \
     -d "wsfunction=mod_assign_save_grade" \
     -d "moodlewsrestformat=json" \
     -d "assignmentid=12" \
     -d "userid=42" \
     -d "grade=92.5" \
     -d "attemptnumber=1" \
     -d "workflowstate=graded"
Sample Return Dataset:
null

Step 5: Multi-Deployment Checklist

To add new endpoints iteratively to a pre-existing custom plugin (e.g. local_courseprogress) over time, execute these deployment loops:

1. Append service description inside db/services.php

Internal Registration
Open your custom plugin's db/services.php file. Add the new function array containing classname, methodname, description, type, and required capabilities check.

2. Bump the version code inside version.php

Required to Trigger Schema Refresher
Moodle indexes external services directly in the SQL database. If you do not change the decimal number inside the $plugin->version parameter in version.php, Moodle will bypass scanning db/services.php, throwing a nofunction API exception on run.
local/courseprogress/version.php
// Bump the version by one (e.g., 2026052500 -> 2026052501)
$plugin->version = 2026052501;

3. Execute the Moodle CLI upgrade tool

Production Upgrade Trigger
Execute Moodle's built-in command line upgrade script as the web service owner (e.g. www-data or Apache's daemon) to write the new specifications to database tables:
bash · CLI Upgrade
sudo -u www-data php /var/www/moodl_ulo2026Demo/admin/cli/upgrade.php --non-interactive

4. Flush Web Service Reflection Caches

Purge Caches for Signature Updates
If you are only editing method arguments inside external/progress.php (and not adding *new* keys to `services.php`), version bumping is unnecessary. However, Moodle caches PHP reflection signatures indefinitely. You MUST purge application caches to apply class modifications:
bash · CLI Cache Purge
sudo -u www-data php /var/www/moodl_ulo2026Demo/admin/cli/purge_caches.php

Step 6: Code Directory Boilerplate

Switch tabs below to view and copy the actual complete production code files for the local_courseprogress plugin. These files are loaded directly from your repository's view directories to ensure perfect correctness.

local/courseprogress/version.php
<?php
defined('MOODLE_INTERNAL') || die();

// $plugin->component = 'local_courseprogress';
// $plugin->version = 2025051601; // Increment the version
// $plugin->requires  = 2022041900; // Moodle 4.x



$plugin->component = 'local_courseprogress';
$plugin->version   = 2025051728;
$plugin->requires  = 2022041900;
$plugin->maturity  = MATURITY_STABLE;

Step 7: External Client Integrations & Attendance Suite

Moodle APIs are designed to be requested by external servers (such as a separate Laravel backend or frontend scripts). Explore these client scripts and Moodle Custom Attendance components directly loaded from your moodle_api directory.

local/customapi/external/get_attendance_log.php
<?php

namespace local_customapi\external;

defined('MOODLE_INTERNAL') || die();

require_once("$CFG->libdir/externallib.php");

use external_api;
use external_function_parameters;
use external_value;
use external_single_structure;
use external_multiple_structure;

class get_attendance_log extends external_api
{
    public static function execute_parameters()
    {
        return new external_function_parameters([
            'courseid' => new external_value(PARAM_INT, 'Course ID'),
        ]);
    }

    public static function execute($courseid)
    {
        global $DB;

        // Get attendance sessions
        $sessions = $DB->get_records_sql("
            SELECT s.*, a.name AS attendance_name
            FROM {attendance_sessions} s
            JOIN {attendance} a ON a.id = s.attendanceid
            WHERE a.course = ?
        ", [$courseid]);

        $logs = [];

        foreach ($sessions as $session) {
            $logs[] = [
                'attendanceid' => $session->attendanceid,
                'sessionid' => $session->id,
                'sessdate' => date('Y-m-d H:i:s', $session->sessdate),
                'duration' => $session->duration,
                'description' => $session->description,
                'attendance_name' => $session->attendance_name
            ];
        }

        return $logs;
    }

    public static function execute_returns()
    {
        return new external_multiple_structure(
            new external_single_structure([
                'attendanceid' => new external_value(PARAM_INT),
                'sessionid' => new external_value(PARAM_INT),
                'sessdate' => new external_value(PARAM_TEXT),
                'duration' => new external_value(PARAM_INT),
                'description' => new external_value(PARAM_TEXT),
                'attendance_name' => new external_value(PARAM_TEXT)
            ])
        );
    }
}

Step 8: Web Service Masterclass Best Practices

Enforce maximum reliability, enterprise security, fast throughput times, and clear traceability when exposing Moodle core and custom endpoints to external clients:

1. Strict Security Boundaries

  • IP Restrictions: Inside Manage tokens, strictly limit access to the IP address of the calling client server.
  • Token Isolation: Provision separate, unique tokens for each integration client. Avoid running general admin accounts as API endpoints.
  • Minimum Capabilities: Lock custom functions behind precise contextual boundaries (like CONTEXT_COURSE) and never grant wildcard permissions.

2. Performance & Caching Mechanics

  • Redis/Memcached caching: Exposing course completions requires scanning massive tables. Instruct clients to cache JSON responses.
  • Query Limit Parameters: Always configure limit and offset validations inside list-based parameters to prevent database deadlocks.
  • Purge reflections strictly: Only clear Moodle caches inside production windows to prevent database spikes.

3. Graceful Exception Diagnostics

  • Catch JSON Exceptions: Moodle throws a structure containing exception, errorcode, and message fields. Enforce try-catch checks on calling clients.
  • Debugging variables: Set $CFG->debugdisplay = 1 inside sandbox instances to output debug logs in standard JSON arrays.

4. Logging & Request Tracing

  • Standard standard_log Store: Query Moodle's built-in standard log store (mdl_logstore_standard_log) to audit service calls.
  • Webhook triggers: Leverage course event triggers to sync systems on demand rather than heavy polling loops.

API Core Rules & Operational Safety

Strict Parameter Checks

Every variable transmitted to custom classes must fall strictly into validation ranges (e.g. PARAM_INT, PARAM_ALPHA, or PARAM_TEXT).

Database Context Scope Limits

Always bound context validations to minimal access layers. Use Moodle standard role authorization helpers inside execution contexts to prevent privilege escapes.