If you run Moodle alongside Salesforce, your student success or support team probably has the same complaint: the CRM knows the student's grades and last login, but not how far through the course they actually are. That progress percentage is the number a coach reaches for first, and it is stuck in the LMS.
You can fix that with a scheduled sync built on Moodle's Web Services API. Here is how it works, and the design choices that decide whether the result is trustworthy or just more noise.
The gap: the CRM has everything except progress
Many Moodle-to-Salesforce setups already push some data across: GPA, lesson numbers, last login. What they usually miss is course-progress percentage, because it is a computed value rather than a stored field. So a coach who wants to know "is this student keeping up?" has to leave Salesforce, open Moodle, and check course by course. That does not scale across a caseload, and it hides the earliest sign of disengagement in a system the coaching team does not live in.
Moodle's Web Services API in brief
Moodle exposes a REST API through its Web Services layer. To use it you:
- Enable web services and the REST protocol in Moodle.
- Create a token tied to a service and a role with only the functions you need.
- Call REST functions such as
core_enrol_get_users_coursesto list a user's courses, and the grade-report functions to read progress and grades per course.
Each call is an HTTP request with the token, the function name, and parameters such as the Moodle user id. You get JSON back.
The sync pattern
A reliable design is a weekly scheduled Apex batch:
- Match students to Moodle users on an identifier you already store on the contact (the Moodle user id), so nothing has to be re-keyed.
- Read progress for each student's relevant courses from the Web Services API.
- Write the progress percentage onto the Salesforce records your team already reports from.
- Schedule it to run on the cadence your reviews actually use, weekly is usually plenty.
Batch it so you respect both Salesforce governor limits and Moodle's load, and log failures so a bad week is visible rather than silent.
Update, do not create
This is the design decision that matters most. If a push already creates the records your team reports from, do not create a second, parallel set. Instead, match the existing records and update only the field you are adding (the progress percentage). Two writers on the same field produce disagreeing numbers in reports, so contribute only what nothing else supplies, and let each field keep a single source. It is less code and far more trustworthy.
Design choices that matter
- Send the token in the request body, not the URL. A token in a query string ends up in Moodle's web-server access logs. In the POST body it does not.
- Make the course list configuration, not code. Programs and courses change every term. Drive the sync from a custom setting or custom metadata so a new course is a configuration change, not a deployment.
- Parse progress defensively. Moodle grade and progress values come back as strings in varied formats. Extract the percentage with a tolerant parser rather than assuming one shape.
- Respect security. Read only what you need with a scoped token and role, and keep the whole thing on-platform so no student data leaves your systems beyond the Moodle call itself.
Frequently asked questions
Can Salesforce read data from Moodle automatically?
Yes. Moodle's Web Services REST API lets Salesforce Apex read courses, grades, and progress on a schedule, then write the values onto Salesforce records so teams see them without logging into Moodle.
Which Moodle Web Services functions return course progress?
core_enrol_get_users_courses lists a user's courses, and the grade-report functions (such as the course-grades overview) return the grade and progress values you parse into a percentage. Completion-status functions exist too, but only work when courses have completion criteria configured.
Should the sync create new Salesforce records or update existing ones?
Update existing ones wherever a push already creates them. Contribute only the field you are adding, so each field has a single source and reports never show two disagreeing numbers.
How often should Moodle progress sync to Salesforce?
Match the cadence of your actual reviews. For most student-success and support workflows a weekly scheduled batch is enough, and it keeps load on both systems low.
From a manual check to a weekly sync
We built this for a university whose success coaches were checking progress in Moodle by hand, and brought weekly course progress onto every student record in Salesforce. The full story is in our Moodle progress-sync case study.
If your team's data is stranded in an LMS or another platform, we can bring it into Salesforce natively and keep it in sync. Book a free consultation.