--- name: moodle-external-api-development description: "This skill guides you through creating custom external web service APIs for Moodle LMS, following Moodle's external API framework and coding standards." risk: critical source: community date_added: "2026-02-27" --- # Moodle External API Development This skill guides you through creating custom external web service APIs for Moodle LMS, following Moodle's external API framework and coding standards. ## Detailed Guide Read [the detailed guide](references/detailed-guide.md) before executing this skill. It retains the complete procedure and reference material. Treat its safety, prerequisites, and validation requirements as mandatory. For focused work, load the relevant sections; for end-to-end work, read the guide completely. ## When to Use This Skill - Creating custom web services for Moodle plugins - Implementing REST/AJAX endpoints for course management - Building APIs for quiz operations, user tracking, or reporting - Exposing Moodle functionality to external applications - Developing mobile app backends using Moodle ## Illustrative Implementation Fragments ### Simple Read API (Get Quiz Attempts) ```php libdir/externallib.php"); use external_api; use external_function_parameters; use external_single_structure; use external_value; class get_quiz_attempts extends external_api { public static function execute_parameters() { return new external_function_parameters([ 'userid' => new external_value(PARAM_INT, 'User ID'), 'courseid' => new external_value(PARAM_INT, 'Course ID') ]); } public static function execute($userid, $courseid) { global $DB; $params = self::validate_parameters(self::execute_parameters(), [ 'userid' => $userid, 'courseid' => $courseid ]); $context = \context_course::instance($params['courseid']); self::validate_context($context); require_capability('mod/quiz:viewreports', $context); // Instructor-report endpoint; add group/quiz-specific visibility restrictions as needed. $sql = "SELECT COUNT(*) AS quiz_attempts FROM {quiz_attempts} qa JOIN {quiz} q ON qa.quiz = q.id WHERE qa.userid = :userid AND q.course = :courseid"; $attempts = $DB->get_field_sql($sql, [ 'userid' => $params['userid'], 'courseid' => $params['courseid'] ]); return ['quiz_attempts' => (int)$attempts]; } public static function execute_returns() { return new external_single_structure([ 'quiz_attempts' => new external_value(PARAM_INT, 'Total number of quiz attempts') ]); } } ``` ### Complex Write API (Create Quiz from Categories) The referenced `create_quiz_from_categories.php` is not bundled. Do not claim it was read, executed or transaction-tested. Use the installed Moodle release's activity/question APIs with context/capability checks, group visibility, bounded input and rollback tests; direct insertion fragments in the guide are historical schema illustrations, not a complete quiz builder. Use least-privilege test roles and synthetic learner data, never production admin tokens in shell arguments. ## Limitations - Use this skill only when the task clearly matches the scope described above. - Do not treat the output as a substitute for environment-specific validation, testing, or expert review. - Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.