diff --git a/.gitignore b/.gitignore index ee211dc08b..128366ed4c 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,6 @@ assets/.rsdoctor *storybook.log storybook-static + +# Bruno Local Environment +docs/api/environments/local.bru diff --git a/docs/api/Courses/course-announcement-{id}.bru b/docs/api/Courses/course-announcement-{id}.bru new file mode 100644 index 0000000000..c5fcfabdda --- /dev/null +++ b/docs/api/Courses/course-announcement-{id}.bru @@ -0,0 +1,63 @@ +meta { + name: course-announcement/{id} + type: http + seq: 4 +} + +get { + url: {{base_url}}/course-announcement/1 + body: none + auth: basic +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Course Announcements + + Retrieves all broadcast announcements published by the course instructors for a specific course. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/course-announcement/:id` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Path Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `id` | `integer` | **Yes** | The WordPress Post ID of the course. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Announcement retrieved successfully", + "data": [ + { + "ID": 401, + "post_title": "Welcome to the Course & Live Q&A Session Schedule", + "post_content": "We will be hosting a weekly live stream every Friday at 3 PM UTC.", + "post_name": "welcome-live-qa-schedule" + } + ] + } + ``` + + ### 404 Not Found + ```json + { + "code": "not_found", + "message": "Announcement not found for given ID", + "data": [] + } + ``` +} diff --git a/docs/api/Courses/course-contents-{id}.bru b/docs/api/Courses/course-contents-{id}.bru new file mode 100644 index 0000000000..307edb0e26 --- /dev/null +++ b/docs/api/Courses/course-contents-{id}.bru @@ -0,0 +1,78 @@ +meta { + name: course-contents/{id} + type: http + seq: 3 +} + +get { + url: {{base_url}}/course-contents/1 + body: none + auth: basic +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Course Contents Tree + + Retrieves the complete hierarchical curriculum structure for a course, grouping topics and their nested child items (lessons, quizzes, assignments). + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/course-contents/:id` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Path Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `id` | `integer` | **Yes** | The WordPress Post ID of the course. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Course contents retrieved successfully", + "data": [ + { + "id": 201, + "title": "Module 1: Introduction to Web APIs", + "summary": "Overview of REST architecture and HTTP fundamentals.", + "contents": [ + { + "ID": 301, + "post_title": "Lesson 1: What is a REST API?", + "post_content": "Detailed overview text...", + "post_name": "what-is-a-rest-api", + "post_type": "lesson" + }, + { + "ID": 302, + "post_title": "Quiz 1: HTTP Basics", + "post_content": "Test your knowledge of status codes.", + "post_name": "quiz-1-http-basics", + "post_type": "tutor_quiz" + } + ] + } + ] + } + ``` + + ### 404 Not Found + ```json + { + "code": "not_found", + "message": "Contents for this course with the given course id not found", + "data": [] + } + ``` +} diff --git a/docs/api/Courses/course-rating-{id}.bru b/docs/api/Courses/course-rating-{id}.bru new file mode 100644 index 0000000000..901b029a62 --- /dev/null +++ b/docs/api/Courses/course-rating-{id}.bru @@ -0,0 +1,86 @@ +meta { + name: course-rating/{id} + type: http + seq: 5 +} + +get { + url: {{base_url}}/course-rating/1 + body: none + auth: basic +} + +params:query { + ~offset: 0 + ~limit: 10 +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Course Ratings & Reviews + + Retrieves overall rating statistics (count, average rating, star breakdown) and a paginated list of approved student reviews for a course. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/course-rating/:id` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Path Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `id` | `integer` | **Yes** | The WordPress Post ID of the course. | + + ## Query Parameters + + | Parameter | Type | Default | Description | + | :--- | :--- | :--- | :--- | + | `offset` | `integer` | `0` | Offset for pagination of reviews. | + | `limit` | `integer` | `10` | Number of reviews to return per request. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Course rating retrieved successfully", + "data": { + "rating_count": 8, + "rating_avg": 4.88, + "five_star_count": 7, + "four_star_count": 1, + "three_star_count": 0, + "two_star_count": 0, + "one_star_count": 0, + "reviews": [ + { + "comment_ID": "85", + "comment_post_ID": "105", + "comment_author": "Alex Smith", + "comment_content": "Exceptional course! Very clear and concise.", + "rating": 5, + "review_title": "Great practical examples" + } + ] + } + } + ``` + + ### 404 Not Found + ```json + { + "code": "not_found", + "message": "Rating not found for given ID", + "data": [] + } + ``` +} diff --git a/docs/api/Courses/courses-{id}.bru b/docs/api/Courses/courses-{id}.bru new file mode 100644 index 0000000000..aa973088d4 --- /dev/null +++ b/docs/api/Courses/courses-{id}.bru @@ -0,0 +1,76 @@ +meta { + name: courses/{id} + type: http + seq: 2 +} + +get { + url: {{base_url}}/courses/1 + body: none + auth: basic +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Course Details + + Retrieves detailed metadata, settings, requirements, benefits, target audience, and video settings for a single course. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/courses/:id` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Path Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `id` | `integer` | **Yes** | The WordPress Post ID of the course. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "course_detail", + "message": "Course detail retrieved successfully", + "data": { + "course_settings": { + "maximum_students": "100", + "is_public": "no" + }, + "course_price_type": "paid", + "course_duration": { + "hours": "4", + "minutes": "30" + }, + "course_level": "all_levels", + "course_benefits": "Learn modern web development principles and build complete apps.", + "course_requirements": "Basic knowledge of HTML and CSS.", + "course_target_audience": "Beginner developers looking to expand their frontend skills.", + "course_material_includes": "Source code repository access, Certificate of Completion.", + "video": { + "source": "youtube", + "source_youtube": "https://www.youtube.com/watch?v=example" + }, + "disable_qa": false + } + } + ``` + + ### 404 / Not Found + ```json + { + "code": "course_detail", + "message": "Detail not found for given ID", + "data": [] + } + ``` +} diff --git a/docs/api/Courses/courses.bru b/docs/api/Courses/courses.bru new file mode 100644 index 0000000000..d18e314a43 --- /dev/null +++ b/docs/api/Courses/courses.bru @@ -0,0 +1,123 @@ +meta { + name: courses + type: http + seq: 1 +} + +get { + url: {{base_url}}/courses + body: none + auth: basic +} + +params:query { + ~paged: 1 + ~order: ASC + ~orderby: title + ~categories: design,development + ~tags: beginner +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get All Courses + + Retrieves a paginated list of published courses along with categories, tags, author info, rating summary, price, and thumbnail. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/courses` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Query Parameters + + | Parameter | Type | Default | Description | + | :--- | :--- | :--- | :--- | + | `paged` | `integer` | `1` | Page number for pagination. | + | `order` | `string` | `ASC` | Sort order direction: `ASC` or `DESC`. | + | `orderby` | `string` | `title` | Sort by field: `title`, `date`, `price`, `ID`, `rand`, etc. When `orderby=price` is used, WooCommerce product prices are queried. | + | `categories` | `string` | _None_ | Comma-separated category names (e.g. `web-development,design`). | + | `tags` | `string` | _None_ | Comma-separated tag names (e.g. `javascript,beginners`). | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Course retrieved successfully", + "data": { + "posts": [ + { + "ID": 105, + "post_author": { + "ID": "1", + "user_login": "instructor_jane", + "user_nicename": "instructor_jane", + "user_email": "jane@example.com", + "display_name": "Jane Doe" + }, + "post_date": "2026-01-15 10:00:00", + "post_title": "Modern JavaScript from Scratch", + "post_content": "Course description and syllabus overview...", + "post_status": "publish", + "post_name": "modern-javascript-from-scratch", + "thumbnail_url": "http://tutor-dev.local/wp-content/uploads/course-js.jpg", + "ratings": { + "rating_count": 12, + "rating_avg": 4.75 + }, + "course_category": [ + { + "term_id": 4, + "name": "Web Development", + "slug": "web-development" + } + ], + "course_tag": [ + { + "term_id": 9, + "name": "JavaScript", + "slug": "javascript" + } + ], + "price": "49.00", + "additional_info": { + "course_duration": "6 hours 30 mins", + "course_level": "beginner" + } + } + ], + "total_course": 25, + "total_page": 3 + } + } + ``` + + ### 404 Not Found + ```json + { + "code": "not_found", + "message": "Course not found", + "data": [] + } + ``` + + ### 401 / 403 Forbidden + ```json + { + "code": "rest_forbidden", + "message": "Sorry, you are not allowed to do that.", + "data": { + "status": 401 + } + } + ``` +} diff --git a/docs/api/Courses/folder.bru b/docs/api/Courses/folder.bru new file mode 100644 index 0000000000..a30f18d3c7 --- /dev/null +++ b/docs/api/Courses/folder.bru @@ -0,0 +1,4 @@ +meta { + name: Courses + seq: 1 +} diff --git a/docs/api/Curriculum/folder.bru b/docs/api/Curriculum/folder.bru new file mode 100644 index 0000000000..d116b8aba7 --- /dev/null +++ b/docs/api/Curriculum/folder.bru @@ -0,0 +1,4 @@ +meta { + name: Curriculum + seq: 2 +} diff --git a/docs/api/Curriculum/lessons.bru b/docs/api/Curriculum/lessons.bru new file mode 100644 index 0000000000..6995d1a2e5 --- /dev/null +++ b/docs/api/Curriculum/lessons.bru @@ -0,0 +1,90 @@ +meta { + name: lessons + type: http + seq: 2 +} + +get { + url: {{base_url}}/lessons + body: none + auth: basic +} + +params:query { + ~topic_id: 1 +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Lessons by Topic + + Retrieves all lessons belonging to a specific topic, including lesson descriptions, downloadable attachments, video player settings, and thumbnails. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/lessons` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Query Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `topic_id` | `integer` | **Yes** | The WordPress Post ID of the parent topic. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Lesson retrieved successfully", + "data": [ + { + "ID": 301, + "post_title": "1.1 Setting Up Your Development Workspace", + "post_content": "Full instructional text and transcript...", + "post_name": "1-1-setting-up-workspace", + "topic_id": 201, + "attachments": [ + "http://tutor-dev.local/wp-content/uploads/starter-kit.zip" + ], + "thumbnail": "http://tutor-dev.local/wp-content/uploads/lesson-thumb.jpg", + "video": [ + { + "source": "html5", + "source_video_id": 450, + "poster": "http://tutor-dev.local/wp-content/uploads/poster.jpg" + } + ] + } + ] + } + ``` + + ### Error Responses + + When `topic_id` is missing: + ```json + { + "code": "not_found", + "message": "topic_id is required", + "data": [] + } + ``` + + When no lessons exist for the topic ID: + ```json + { + "code": "not_found", + "message": "Lesson not found for the given topic ID", + "data": [] + } + ``` +} diff --git a/docs/api/Curriculum/topics.bru b/docs/api/Curriculum/topics.bru new file mode 100644 index 0000000000..60555c833e --- /dev/null +++ b/docs/api/Curriculum/topics.bru @@ -0,0 +1,84 @@ +meta { + name: topics + type: http + seq: 1 +} + +get { + url: {{base_url}}/topics + body: none + auth: basic +} + +params:query { + ~course_id: 1 +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Topics by Course + + Retrieves all topic modules belonging to a specific course. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/topics` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Query Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `course_id` | `integer` | **Yes** | The WordPress Post ID of the course. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "get_topic", + "message": "Topic retrieved successfully", + "data": [ + { + "ID": "201", + "post_title": "Getting Started with the Environment", + "post_content": "Detailed overview of tools, IDE plugins, and prerequisites.", + "post_name": "getting-started-environment" + }, + { + "ID": "202", + "post_title": "Core Concepts & Deep Dive", + "post_content": "Deep exploration of architecture and API patterns.", + "post_name": "core-concepts-deep-dive" + } + ] + } + ``` + + ### 404 / Missing Param Errors + + When `course_id` is missing: + ```json + { + "code": "get_topic", + "message": "course_id is required", + "data": [] + } + ``` + + When no topics exist for the provided ID: + ```json + { + "code": "not_found", + "message": "Topic not found for given course ID", + "data": [] + } + ``` +} diff --git a/docs/api/Ecommerce & Webhooks/ecommerce-webhook-{payment-method}.bru b/docs/api/Ecommerce & Webhooks/ecommerce-webhook-{payment-method}.bru new file mode 100644 index 0000000000..f4b97062ba --- /dev/null +++ b/docs/api/Ecommerce & Webhooks/ecommerce-webhook-{payment-method}.bru @@ -0,0 +1,54 @@ +meta { + name: ecommerce-webhook/{payment-method} + type: http + seq: 1 +} + +post { + url: {{base_url}}/ecommerce-webhook/paypal + body: json + auth: none +} + +body:json { + { + "event_type": "PAYMENT.CAPTURE.COMPLETED", + "resource": { + "id": "PAY-1234567890", + "status": "COMPLETED", + "amount": { + "value": "49.00", + "currency_code": "USD" + }, + "custom_id": "order_789" + } + } +} + +docs { + # Handle Ecommerce Payment Webhook + + Public webhook receiver endpoint for handling asynchronous transaction notifications and order status updates from integrated payment gateways (e.g., PayPal, Stripe, etc.). + + ## HTTP Method & Route + - **Method:** `POST` / `GET` / `PUT` / `PATCH` (`WP_REST_Server::ALLMETHODS`) + - **Route:** `/wp-json/tutor/v1/ecommerce-webhook/:payment_method` + + ## Authentication + - **Type:** Public (`__return_true`) + - **Verification:** Security and payload signatures are verified per gateway driver inside the handler. + + ## Path Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `payment_method` | `string` | No | Identifier slug of the payment gateway (e.g. `paypal`, `stripe`). | + + ## Request Body + Accepts raw webhook payload sent by the payment provider (JSON or form-urlencoded). + + ## Responses + + ### 200 OK (Webhook Processed) + Standard HTTP 200/204 response returned to notify the payment provider that the webhook event was received. +} diff --git a/docs/api/Ecommerce & Webhooks/folder.bru b/docs/api/Ecommerce & Webhooks/folder.bru new file mode 100644 index 0000000000..8105808c43 --- /dev/null +++ b/docs/api/Ecommerce & Webhooks/folder.bru @@ -0,0 +1,4 @@ +meta { + name: Ecommerce & Webhooks + seq: 3 +} diff --git a/docs/api/Instructors/author-information-{id}.bru b/docs/api/Instructors/author-information-{id}.bru new file mode 100644 index 0000000000..e759314dfe --- /dev/null +++ b/docs/api/Instructors/author-information-{id}.bru @@ -0,0 +1,70 @@ +meta { + name: author-information/{id} + type: http + seq: 1 +} + +get { + url: {{base_url}}/author-information/1 + body: none + auth: basic +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Instructor Information + + Retrieves public instructor/author details including display name, email, registration date, biographical info, and a list of courses authored by the instructor. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/author-information/:id` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Path Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `id` | `integer` | **Yes** | The WordPress User ID of the instructor/author. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Author details retrieved successfully", + "data": { + "ID": "1", + "user_login": "jane_instructor", + "user_nicename": "jane_instructor", + "user_email": "jane@example.com", + "user_url": "https://example.com", + "user_registered": "2025-01-01 12:00:00", + "user_status": "0", + "display_name": "Jane Doe", + "courses": [ + "105", + "110", + "120" + ] + } + } + ``` + + ### 404 / Invalid ID + ```json + { + "code": "invalid_id", + "message": "Author not found", + "data": [] + } + ``` +} diff --git a/docs/api/Instructors/folder.bru b/docs/api/Instructors/folder.bru new file mode 100644 index 0000000000..411e86362c --- /dev/null +++ b/docs/api/Instructors/folder.bru @@ -0,0 +1,4 @@ +meta { + name: Instructors + seq: 4 +} diff --git a/docs/api/Quizzes/folder.bru b/docs/api/Quizzes/folder.bru new file mode 100644 index 0000000000..12be87dad3 --- /dev/null +++ b/docs/api/Quizzes/folder.bru @@ -0,0 +1,4 @@ +meta { + name: Quizzes + seq: 5 +} diff --git a/docs/api/Quizzes/quiz-attempt-details-{id}.bru b/docs/api/Quizzes/quiz-attempt-details-{id}.bru new file mode 100644 index 0000000000..054c48c281 --- /dev/null +++ b/docs/api/Quizzes/quiz-attempt-details-{id}.bru @@ -0,0 +1,72 @@ +meta { + name: quiz-attempt-details/{id} + type: http + seq: 4 +} + +get { + url: {{base_url}}/quiz-attempt-details/1 + body: none + auth: basic +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Quiz Attempt Details + + Retrieves historical attempt records, passing status, marks obtained, and earned grades for a given quiz ID. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/quiz-attempt-details/:id` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Path Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `id` | `integer` | **Yes** | The WordPress Post ID of the quiz. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Quiz attempt detail retrieved successfully", + "data": [ + { + "attempt_id": 88, + "course_id": 105, + "quiz_id": 501, + "user_id": 14, + "total_questions": 10, + "total_answered_questions": 10, + "total_marks": "100.00", + "earned_marks": "90.00", + "attempt_status": "review_required", + "attempt_info": "...", + "attempt_started_at": "2026-02-01 14:20:00", + "attempt_ended_at": "2026-02-01 14:45:00", + "is_manually_reviewed": 0 + } + ] + } + ``` + + ### 404 Not Found + ```json + { + "code": "not_found", + "message": "Quiz attempt detail not found for given ID", + "data": [] + } + ``` +} diff --git a/docs/api/Quizzes/quiz-question-answer-{id}.bru b/docs/api/Quizzes/quiz-question-answer-{id}.bru new file mode 100644 index 0000000000..1cfd89abe1 --- /dev/null +++ b/docs/api/Quizzes/quiz-question-answer-{id}.bru @@ -0,0 +1,77 @@ +meta { + name: quiz-question-answer/{id} + type: http + seq: 3 +} + +get { + url: {{base_url}}/quiz-question-answer/1 + body: none + auth: basic +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Quiz Question Answers + + Retrieves a flattened list of all questions and their configured answers for a given quiz ID. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/quiz-question-answer/:id` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Path Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `id` | `integer` | **Yes** | The WordPress Post ID of the quiz. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Quiz question and answer retrieved successfully", + "data": [ + { + "question_id": 12, + "question_title": "Which HTTP method is idempotent?", + "question_description": "Select the correct answer.", + "question_type": "single_choice", + "question_mark": 1, + "answer_id": 45, + "answer_title": "GET", + "is_correct": 1 + }, + { + "question_id": 12, + "question_title": "Which HTTP method is idempotent?", + "question_description": "Select the correct answer.", + "question_type": "single_choice", + "question_mark": 1, + "answer_id": 46, + "answer_title": "POST", + "is_correct": 0 + } + ] + } + ``` + + ### 404 Not Found + ```json + { + "code": "not_found", + "message": "Quiz question not found for given ID", + "data": [] + } + ``` +} diff --git a/docs/api/Quizzes/quizzes-{id}.bru b/docs/api/Quizzes/quizzes-{id}.bru new file mode 100644 index 0000000000..3a88cfca42 --- /dev/null +++ b/docs/api/Quizzes/quizzes-{id}.bru @@ -0,0 +1,96 @@ +meta { + name: quizzes/{id} + type: http + seq: 2 +} + +get { + url: {{base_url}}/quizzes/1 + body: none + auth: basic +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Quiz Details + + Retrieves complete details for a specific quiz, including all questions, question types, point values, descriptions, and answer options. + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/quizzes/:id` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Path Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `id` | `integer` | **Yes** | The WordPress Post ID of the quiz. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Quiz retrieved successfully", + "data": { + "ID": 501, + "post_title": "Module 1 Knowledge Check", + "post_content": "Assessment quiz...", + "post_name": "module-1-knowledge-check", + "quiz_settings": [ + { + "time_limit": { + "time_value": "30", + "time_type": "minutes" + }, + "attempts_allowed": "3", + "passing_grade": "80" + } + ], + "questions": [ + { + "question_id": 12, + "question_title": "Which HTTP method is idempotent?", + "question_description": "Select the correct answer.", + "question_type": "single_choice", + "question_mark": 1, + "question_settings": { + "answer_required": "1", + "randomize_question": "0" + }, + "answers": [ + { + "answer_id": 45, + "answer_title": "GET", + "is_correct": 1 + }, + { + "answer_id": 46, + "answer_title": "POST", + "is_correct": 0 + } + ] + } + ] + } + } + ``` + + ### 404 Not Found + ```json + { + "code": "not_found", + "message": "Quiz not found for given ID", + "data": [] + } + ``` +} diff --git a/docs/api/Quizzes/quizzes.bru b/docs/api/Quizzes/quizzes.bru new file mode 100644 index 0000000000..5ac2fb7793 --- /dev/null +++ b/docs/api/Quizzes/quizzes.bru @@ -0,0 +1,79 @@ +meta { + name: quizzes + type: http + seq: 1 +} + +get { + url: {{base_url}}/quizzes + body: none + auth: basic +} + +params:query { + ~topic_id: 1 +} + +auth:basic { + username: {{api_key}} + password: {{api_secret}} +} + +docs { + # Get Quizzes by Topic + + Retrieves all quizzes configured under a specific topic module, including quiz settings (time limits, passing grades, attempt limits). + + ## HTTP Method & Route + - **Method:** `GET` + - **Route:** `/wp-json/tutor/v1/quizzes` + + ## Authentication + - **Type:** Basic Auth (`api_key` / `api_secret`) + - **Required Permission:** `Read` or `All` + + ## Query Parameters + + | Parameter | Type | Required | Description | + | :--- | :--- | :--- | :--- | + | `topic_id` | `integer` | **Yes** | The WordPress Post ID of the parent topic. | + + ## Responses + + ### 200 OK (Success) + ```json + { + "code": "success", + "message": "Quiz retrieved successfully", + "data": [ + { + "ID": 501, + "post_title": "Module 1 Knowledge Check", + "post_content": "Short 10-question evaluation of module 1 concepts.", + "post_name": "module-1-knowledge-check", + "topic_id": 201, + "quiz_settings": [ + { + "time_limit": { + "time_value": "30", + "time_type": "minutes" + }, + "attempts_allowed": "3", + "passing_grade": "80", + "max_questions_for_answer": "10" + } + ] + } + ] + } + ``` + + ### 404 / Missing Param Errors + ```json + { + "code": "not_found", + "message": "topic_id is required", + "data": [] + } + ``` +} diff --git a/docs/api/README.md b/docs/api/README.md new file mode 100644 index 0000000000..8872195789 --- /dev/null +++ b/docs/api/README.md @@ -0,0 +1,75 @@ +# Tutor LMS REST API Documentation + +This directory contains the complete, interactive API documentation and executable request collection for the **Tutor LMS** WordPress plugin, built with [Bruno](https://www.usebruno.com/). + +--- + +## 🚀 Getting Started + +### 1. Open in Bruno GUI +1. Download and install [Bruno](https://www.usebruno.com/downloads). +2. Open Bruno, click **"Open Collection"**, and select the `wp-content/plugins/tutor/docs/api` directory. + +### 2. Configure Environment & Authentication +Tutor LMS REST API uses Basic Authentication with **API Keys** and **API Secrets**. + +1. In your WordPress admin dashboard, navigate to **Tutor LMS > Settings > REST API / API**. +2. Generate an API Key & Secret with the desired permission level (`Read`, `Write`, or `All`). +3. Set up your local environment file: + - Make a copy of `environments/local.bru.example` named `environments/local.bru`: + ```bash + cp docs/api/environments/local.bru.example docs/api/environments/local.bru + ``` + - In Bruno, select the **local** environment from the top-right dropdown. + - Configure `base_url`, `api_key`, and `api_secret` in the environment settings (or directly in `environments/local.bru`). Note that `local.bru` is gitignored so your credentials won't be committed. +4. For production environments, configure `environments/production.bru`. + +--- + +## 📁 Collection Structure + +The collection is organized into the following categories: + +- **`environments/`**: Contains `local.bru.example` and `production.bru`. +- **`Authentication/`**: Overview of authentication mechanisms, key management, and headers. +- **`Courses/`**: Endpoints for querying course listings, course details, complete curriculum trees, announcements, and ratings/reviews. +- **`Curriculum/`**: Topic modules and lesson querying endpoints. +- **`Quizzes/`**: Quiz structures, questions, answers, and student attempt histories. +- **`Instructors/`**: Author/instructor profiles, bio, and associated course references. +- **`Ecommerce & Webhooks/`**: Payment gateway webhooks and processing handlers. + +--- + +## 💻 Running Requests via CLI + +You can execute this collection in terminal or CI/CD pipelines using the Bruno CLI: + +```bash +# Run against the local environment +npx @usebruno/cli run docs/api --env local + +# Run against production +npx @usebruno/cli run docs/api --env production + +# Run a specific folder (e.g., Courses) +npx @usebruno/cli run docs/api/Courses --env local +``` + +--- + +## 📡 API Response Format + +All Tutor LMS REST API endpoints return a standardized JSON envelope: + +```json +{ + "code": "success", + "message": "Human readable message", + "data": { ... } +} +``` + +### Common Status Codes: +- `200 OK`: Request succeeded. +- `401 Unauthorized` / `403 Forbidden`: Missing, invalid, or insufficient API keys / user capabilities. +- `404 Not Found`: Resource (Course, Topic, Lesson, Quiz, or Instructor) does not exist for the provided ID. diff --git a/docs/api/bruno.json b/docs/api/bruno.json new file mode 100644 index 0000000000..fb9e466ea4 --- /dev/null +++ b/docs/api/bruno.json @@ -0,0 +1,9 @@ +{ + "version": "1", + "name": "Tutor LMS REST API", + "type": "collection", + "ignore": [ + "node_modules", + ".git" + ] +} diff --git a/docs/api/environments/local.bru.example b/docs/api/environments/local.bru.example new file mode 100644 index 0000000000..8a27de6cf9 --- /dev/null +++ b/docs/api/environments/local.bru.example @@ -0,0 +1,7 @@ +vars { + base_url: http://tutor-dev.local/wp-json/tutor/v1 + api_key: +} +vars:secret [ + api_secret +] diff --git a/docs/api/environments/production.bru b/docs/api/environments/production.bru new file mode 100644 index 0000000000..4df2c2565c --- /dev/null +++ b/docs/api/environments/production.bru @@ -0,0 +1,7 @@ +vars { + base_url: https://example.com/wp-json/tutor/v1 + api_key: +} +vars:secret [ + api_secret +] diff --git a/gulpfile.mjs b/gulpfile.mjs index 7162a1bbeb..7877fa85be 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -84,6 +84,7 @@ function copy() { '!phpstan.neon', '!.claude', '!.cursor', + '!docs/**', ], { allowEmpty: true,