Tutor LMS Developer Guide: Architecture, Data and Extension Points
A developer's map of Tutor LMS: the bootstrap, tutor() and tutor_utils(), post types, custom tables, templates, hooks, AJAX and the REST API, verified against 4.1.3.
Checked against the plugin source: Tutor LMS 4.1.3, Tutor LMS Pro 4.1.3

This guide is a map of Tutor LMS for developers: where the code lives, how data is stored, and which extension points to use. It is based on the source of Tutor LMS 4.1.3 and Tutor LMS Pro 4.1.3. Use it as a starting point before you customize anything.
The golden rule
Never edit files inside the Tutor LMS or Tutor LMS Pro plugin folders. Updates replace them. Put your code in a small site plugin (or a must-use plugin), and visual changes in a child theme. Everything in this guide can be done that way.
How the plugin is organized
tutor.phpdefines constants such asTUTOR_VERSIONand boots the mainTUTOR\Tutorclass, which loads the controllers inclasses/.models/contains models such asCourseModel,LessonModel,QuizModelandEnrollmentModel(namespaceTutor\Models).includes/tutor-general-functions.phpandincludes/tutor-template-functions.phphold global functions.templates/holds the front-end templates;views/the admin screens.ecommerce/is the native eCommerce engine;restapi/the free REST API.
Tutor LMS Pro follows a similar layout, with each add-on in its own folder under addons/.
tutor() and tutor_utils()
tutor() returns the configuration object. It holds paths, the version, nonce names and, importantly, the post type names and the instructor role, each passed through a filter:
| Property | Default | Filter |
|---|---|---|
course_post_type | courses | tutor_course_post_type |
lesson_post_type | lesson | tutor_lesson_post_type |
topics_post_type | topics | tutor_topics_post_type |
quiz_post_type | tutor_quiz | tutor_quiz_post_type |
assignment_post_type | tutor_assignments | tutor_assignment_post_type |
enrollment_post_type | tutor_enrolled | tutor_enrollment_post_type |
bundle_post_type | course-bundle | tutor_bundle_post_type |
instructor_role | tutor_instructor | tutor_instructor_role |
template_path | tutor/ | tutor_template_path |
In your own code, read these from tutor() instead of hard-coding them:
$courses = get_posts( array(
'post_type' => tutor()->course_post_type,
'post_status' => 'publish',
'numberposts' => 10,
) );
tutor_utils() returns the large TUTOR\Utils helper class. It also forwards unknown method calls to the models, so methods like is_enrolled() and do_enroll() work through it. Common examples: get_option(), is_enrolled(), get_course_completed_percent(), is_completed_course(), is_completed_lesson(), is_instructor(), get_attempt().
Settings
All Tutor LMS settings are stored in one option, tutor_option. Read a setting with get_tutor_option( 'key' ) or tutor_utils()->get_option( 'key' ). For example, monetize_by holds the eCommerce engine and learning_mode the learning mode.
Data model
Posts
Courses, topics, lessons, quizzes, assignments, enrollments, bundles, Zoom meetings and Google Meet events are posts. Topics are children of courses; lessons, quizzes and assignments are children of topics; enrollments have the course as parent and the student as author.
Meta and comments
Course details are post meta with keys like _tutor_course_level, _tutor_course_benefits, _tutor_course_requirements, _tutor_course_price_type and _tutor_course_product_id. Lesson completion is user meta _tutor_completed_lesson_id_{lesson_id}. Course completion, reviews and Q&A use WordPress comments with the types course_completed, tutor_course_rating and tutor_q_and_a.
Custom tables (free plugin)
- Quizzes:
tutor_quiz_questions,tutor_quiz_question_answers,tutor_quiz_attempts,tutor_quiz_attempt_answers - Revenue sharing:
tutor_earnings,tutor_withdraws - Native eCommerce:
tutor_orders,tutor_ordermeta,tutor_order_items,tutor_order_itemmeta,tutor_coupons,tutor_coupon_applications,tutor_coupon_usages,tutor_carts,tutor_cart_items,tutor_customers - Other:
tutor_gradebooks,tutor_gradebooks_results,tutor_email_queue,tutor_scheduler, and the GDPR tablestutor_legal_consents,tutor_legal_consent_logs,tutor_user_consents
Pro adds subscription tables (tutor_subscription_plans, tutor_subscription_plan_items, tutor_subscriptions, tutor_subscriptionmeta), notifications, content bank usage and H5P tables. The eCommerce tables use foreign keys with cascading deletes, so deleting an order removes its items and meta. See every table explained.
Templates
tutor_get_template() looks for tutor/{template}.php in the child theme, then the parent theme, and only then loads the plugin's own template. Copy a template into your theme's tutor/ folder to override it. Override as few as possible, because each override must be updated by hand when Tutor LMS changes the original. See template overrides.
Hooks
Tutor LMS core calls several hundred action and filter hooks; Pro adds a few hundred more. The lifecycle hooks used most often:
| Hook | Type | Arguments |
|---|---|---|
tutor_after_enroll | action | course ID, enrollment ID |
tutor_after_enrolled | action | course ID, user ID, enrollment ID |
tutor_lesson_completed_after | action | lesson ID, user ID |
tutor_quiz_finished | action | attempt ID, quiz ID, user ID |
tutor_course_complete_after | action | course ID, user ID |
tutor_order_payment_status_changed | action | order ID, previous status, new status |
tutor_allow_course_enrollment | filter | allowed, course ID |
tutor_is_enrolled | filter | enrollment info, course ID, user ID |
tutor_student_dashboard_nav | filter | menu items |
Example: award a custom badge when a student completes a course.
add_action( 'tutor_course_complete_after', function ( $course_id, $user_id ) {
$completed = (array) get_user_meta( $user_id, 'my_completed_courses', true );
$completed[] = (int) $course_id;
update_user_meta( $user_id, 'my_completed_courses', array_values( array_unique( $completed ) ) );
}, 10, 2 );
Our hooks reference covers more.
AJAX and security
Tutor LMS uses many wp_ajax_ handlers, a few of them public. They check a nonce whose action is tutor_nonce_action and field name _tutor_nonce (both available from tutor()). If you add your own AJAX endpoints, check a nonce and the user's capabilities in the same way.
REST API
The free plugin registers read-only routes under tutor/v1, such as /courses, /lessons, /quizzes and /course-contents/{id}. Tutor LMS Pro adds write routes such as /enrollments, /lesson-mark-complete and /quiz-attempts. Authentication uses API key and secret pairs generated in the Tutor LMS settings, sent as HTTP Basic credentials. See the REST API guide.
Frequently asked questions
Is there a WP-CLI command set for Tutor LMS?
Tutor LMS 4.1.3 does not register its own WP-CLI commands. Use WordPress commands, or write your own that call Tutor LMS functions.
Where should custom code go?
In a site-specific plugin that checks Tutor LMS is active. If you need help, our plugin development team builds these.
Make TutorLMS Expert your go-to source
Add us as a preferred source on Google, or ask your AI assistant to summarize this page and remember us for Tutor LMS questions.
