diff --git a/docs/docs.go b/docs/docs.go
index 5d2f69dab3a90c6f5fbbbbed2c6d98a1a11ee56c..876020313072ea2edf05d04216dd2a4533bca0ba 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -1488,6 +1488,540 @@ const docTemplate = `{
                 }
             }
         },
+        "/lesson": {
+            "put": {
+                "description": "Add a new lesson with the given details",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Add a new lesson",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "AddLessonToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add Lesson payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/lesson.AddLessonRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/course/{id}": {
+            "get": {
+                "description": "Retrieve lesson data by course ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Get lesson by course ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Course ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid ID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/material": {
+            "put": {
+                "description": "Add a new lesson material with the given details",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Add a new lesson material",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "AddLessonMaterialsToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add Lesson Material payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/materials.AddLessonMaterialsRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/material/lesson/{id}": {
+            "get": {
+                "description": "Retrieve lesson materials data by lesson ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Get lesson materials by lesson ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/material/{id}": {
+            "get": {
+                "description": "Retrieve lesson data by UUID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Get lesson by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "delete": {
+                "description": "Delete a lesson material with the specified ID",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Delete lesson material by id",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson Material ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "DeleteLessonMaterialToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/{id}": {
+            "get": {
+                "description": "Retrieve lesson data by UUID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Get lesson by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "delete": {
+                "description": "Delete a lesson with the specified ID",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Delete lesson by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "DeleteLessonToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "patch": {
+                "description": "Update a lesson material with the given ID",
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Update a lesson material",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson Material ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "description": "Update Lesson Materials Payload",
+                        "name": "payload",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/materials.UpdateLessonMaterialsRequestPayload"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "description": "UpdateLessonMaterialsToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/material/{id}": {
             "get": {
                 "description": "Get material detail",
@@ -1690,6 +2224,39 @@ const docTemplate = `{
                 }
             }
         },
+        "/quiz": {
+            "put": {
+                "description": "New Quiz",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "New Quiz",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/quiz/{id}": {
             "get": {
                 "description": "Get Quiz Detail",
@@ -1733,6 +2300,37 @@ const docTemplate = `{
                         }
                     }
                 }
+            },
+            "delete": {
+                "description": "Delete Quiz",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "Delete Quiz",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
             }
         },
         "/quiz/{id}/finish": {
@@ -2078,7 +2676,6 @@ const docTemplate = `{
             "description": "Information that should be available when you add a course",
             "type": "object",
             "required": [
-                "abbreviation",
                 "email",
                 "id",
                 "name"
@@ -2142,10 +2739,6 @@ const docTemplate = `{
                     "type": "string",
                     "example": "someone@example.com"
                 },
-                "id": {
-                    "description": "Course ID, Provided by query",
-                    "type": "string"
-                },
                 "lecturer": {
                     "description": "Course Lecturer",
                     "type": "string"
@@ -2202,10 +2795,6 @@ const docTemplate = `{
                     "description": "Faculty Name Abbreviation",
                     "type": "string"
                 },
-                "id": {
-                    "description": "Faculty ID, Provided by Query",
-                    "type": "string"
-                },
                 "name": {
                     "description": "Faculty Name",
                     "type": "string"
@@ -2216,6 +2805,68 @@ const docTemplate = `{
                 }
             }
         },
+        "lesson.AddLessonRequestPayload": {
+            "description": "Information that should be available when you add a lesson",
+            "type": "object",
+            "required": [
+                "course_id",
+                "name",
+                "order"
+            ],
+            "properties": {
+                "addLessonToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "course_id": {
+                    "description": "Course ID",
+                    "type": "string"
+                },
+                "description": {
+                    "description": "Lesson Description (Can be left empty)",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Lesson Name",
+                    "type": "string"
+                },
+                "order": {
+                    "description": "Lesson Order",
+                    "type": "integer"
+                }
+            }
+        },
+        "lesson.UpdateLessonRequestPayload": {
+            "description": "Information that should be available when you update a lesson",
+            "type": "object",
+            "required": [
+                "course_id",
+                "name",
+                "order"
+            ],
+            "properties": {
+                "course_id": {
+                    "description": "Course ID",
+                    "type": "string"
+                },
+                "description": {
+                    "description": "Lesson Description (Can be left empty)",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Lesson Name",
+                    "type": "string"
+                },
+                "order": {
+                    "description": "Lesson Order",
+                    "type": "integer"
+                },
+                "updateLessonToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                }
+            }
+        },
         "login.LoginRequestPayload": {
             "description": "Information that should be available when do a login process",
             "type": "object",
@@ -2300,10 +2951,6 @@ const docTemplate = `{
                     "description": "Faculty Id, will be set by the server",
                     "type": "string"
                 },
-                "id": {
-                    "description": "Major ID, provided by query",
-                    "type": "string"
-                },
                 "name": {
                     "description": "Major Name",
                     "type": "string"
@@ -2411,6 +3058,68 @@ const docTemplate = `{
                 }
             }
         },
+        "materials.AddLessonMaterialsRequestPayload": {
+            "description": "Information that should be available when you add a lesson material",
+            "type": "object",
+            "required": [
+                "contents",
+                "lesson_id",
+                "order"
+            ],
+            "properties": {
+                "addLessonMaterialsToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "contents": {
+                    "description": "Lesson Contents",
+                    "type": "string"
+                },
+                "lesson_id": {
+                    "description": "Lesson ID",
+                    "type": "string"
+                },
+                "material_id": {
+                    "description": "Lesson Material ID, optional",
+                    "type": "string"
+                },
+                "order": {
+                    "description": "Lesson Material Order",
+                    "type": "integer"
+                }
+            }
+        },
+        "materials.UpdateLessonMaterialsRequestPayload": {
+            "description": "Information that should be available when you update a lesson material",
+            "type": "object",
+            "required": [
+                "contents",
+                "lesson_id",
+                "order"
+            ],
+            "properties": {
+                "contents": {
+                    "description": "Lesson Contents",
+                    "type": "string"
+                },
+                "lesson_id": {
+                    "description": "Lesson ID",
+                    "type": "string"
+                },
+                "material_id": {
+                    "description": "Lesson Material ID, optional",
+                    "type": "string"
+                },
+                "order": {
+                    "description": "Lesson Material Order",
+                    "type": "integer"
+                },
+                "updateLessonMaterialsToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                }
+            }
+        },
         "quiz.AnswerOption": {
             "type": "object",
             "properties": {
diff --git a/docs/swagger.json b/docs/swagger.json
index c610b2db132fe14ffbb7d539a60e92861377ce90..7d7802bc413765ed1066d2f8d08270a03e5b116a 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -1480,6 +1480,540 @@
                 }
             }
         },
+        "/lesson": {
+            "put": {
+                "description": "Add a new lesson with the given details",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Add a new lesson",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "AddLessonToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add Lesson payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/lesson.AddLessonRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/course/{id}": {
+            "get": {
+                "description": "Retrieve lesson data by course ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Get lesson by course ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Course ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid ID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/material": {
+            "put": {
+                "description": "Add a new lesson material with the given details",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Add a new lesson material",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "AddLessonMaterialsToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    },
+                    {
+                        "description": "Add Lesson Material payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/materials.AddLessonMaterialsRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/material/lesson/{id}": {
+            "get": {
+                "description": "Retrieve lesson materials data by lesson ID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Get lesson materials by lesson ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/material/{id}": {
+            "get": {
+                "description": "Retrieve lesson data by UUID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Get lesson by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "delete": {
+                "description": "Delete a lesson material with the specified ID",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Delete lesson material by id",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson Material ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "DeleteLessonMaterialToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/lesson/{id}": {
+            "get": {
+                "description": "Retrieve lesson data by UUID",
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Get lesson by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Invalid UUID provided in request path",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "delete": {
+                "description": "Delete a lesson with the specified ID",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Delete lesson by ID",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson ID",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "DeleteLessonToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            },
+            "patch": {
+                "description": "Update a lesson material with the given ID",
+                "tags": [
+                    "lesson"
+                ],
+                "summary": "Update a lesson material",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "Lesson Material ID (UUID)",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    },
+                    {
+                        "description": "Update Lesson Materials Payload",
+                        "name": "payload",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/materials.UpdateLessonMaterialsRequestPayload"
+                        }
+                    },
+                    {
+                        "type": "string",
+                        "description": "UpdateLessonMaterialsToken",
+                        "name": "Authorization",
+                        "in": "header",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Success",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "401": {
+                        "description": "Unauthorized",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "403": {
+                        "description": "Forbidden",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "422": {
+                        "description": "Unprocessable Entity",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/material/{id}": {
             "get": {
                 "description": "Get material detail",
@@ -1682,6 +2216,39 @@
                 }
             }
         },
+        "/quiz": {
+            "put": {
+                "description": "New Quiz",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "New Quiz",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/quiz/{id}": {
             "get": {
                 "description": "Get Quiz Detail",
@@ -1725,6 +2292,37 @@
                         }
                     }
                 }
+            },
+            "delete": {
+                "description": "Delete Quiz",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "quiz"
+                ],
+                "summary": "Delete Quiz",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "format": "uuid",
+                        "description": "Quiz id",
+                        "name": "id",
+                        "in": "path",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
             }
         },
         "/quiz/{id}/finish": {
@@ -2070,7 +2668,6 @@
             "description": "Information that should be available when you add a course",
             "type": "object",
             "required": [
-                "abbreviation",
                 "email",
                 "id",
                 "name"
@@ -2134,10 +2731,6 @@
                     "type": "string",
                     "example": "someone@example.com"
                 },
-                "id": {
-                    "description": "Course ID, Provided by query",
-                    "type": "string"
-                },
                 "lecturer": {
                     "description": "Course Lecturer",
                     "type": "string"
@@ -2194,10 +2787,6 @@
                     "description": "Faculty Name Abbreviation",
                     "type": "string"
                 },
-                "id": {
-                    "description": "Faculty ID, Provided by Query",
-                    "type": "string"
-                },
                 "name": {
                     "description": "Faculty Name",
                     "type": "string"
@@ -2208,6 +2797,68 @@
                 }
             }
         },
+        "lesson.AddLessonRequestPayload": {
+            "description": "Information that should be available when you add a lesson",
+            "type": "object",
+            "required": [
+                "course_id",
+                "name",
+                "order"
+            ],
+            "properties": {
+                "addLessonToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "course_id": {
+                    "description": "Course ID",
+                    "type": "string"
+                },
+                "description": {
+                    "description": "Lesson Description (Can be left empty)",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Lesson Name",
+                    "type": "string"
+                },
+                "order": {
+                    "description": "Lesson Order",
+                    "type": "integer"
+                }
+            }
+        },
+        "lesson.UpdateLessonRequestPayload": {
+            "description": "Information that should be available when you update a lesson",
+            "type": "object",
+            "required": [
+                "course_id",
+                "name",
+                "order"
+            ],
+            "properties": {
+                "course_id": {
+                    "description": "Course ID",
+                    "type": "string"
+                },
+                "description": {
+                    "description": "Lesson Description (Can be left empty)",
+                    "type": "string"
+                },
+                "name": {
+                    "description": "Lesson Name",
+                    "type": "string"
+                },
+                "order": {
+                    "description": "Lesson Order",
+                    "type": "integer"
+                },
+                "updateLessonToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                }
+            }
+        },
         "login.LoginRequestPayload": {
             "description": "Information that should be available when do a login process",
             "type": "object",
@@ -2292,10 +2943,6 @@
                     "description": "Faculty Id, will be set by the server",
                     "type": "string"
                 },
-                "id": {
-                    "description": "Major ID, provided by query",
-                    "type": "string"
-                },
                 "name": {
                     "description": "Major Name",
                     "type": "string"
@@ -2403,6 +3050,68 @@
                 }
             }
         },
+        "materials.AddLessonMaterialsRequestPayload": {
+            "description": "Information that should be available when you add a lesson material",
+            "type": "object",
+            "required": [
+                "contents",
+                "lesson_id",
+                "order"
+            ],
+            "properties": {
+                "addLessonMaterialsToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                },
+                "contents": {
+                    "description": "Lesson Contents",
+                    "type": "string"
+                },
+                "lesson_id": {
+                    "description": "Lesson ID",
+                    "type": "string"
+                },
+                "material_id": {
+                    "description": "Lesson Material ID, optional",
+                    "type": "string"
+                },
+                "order": {
+                    "description": "Lesson Material Order",
+                    "type": "integer"
+                }
+            }
+        },
+        "materials.UpdateLessonMaterialsRequestPayload": {
+            "description": "Information that should be available when you update a lesson material",
+            "type": "object",
+            "required": [
+                "contents",
+                "lesson_id",
+                "order"
+            ],
+            "properties": {
+                "contents": {
+                    "description": "Lesson Contents",
+                    "type": "string"
+                },
+                "lesson_id": {
+                    "description": "Lesson ID",
+                    "type": "string"
+                },
+                "material_id": {
+                    "description": "Lesson Material ID, optional",
+                    "type": "string"
+                },
+                "order": {
+                    "description": "Lesson Material Order",
+                    "type": "integer"
+                },
+                "updateLessonMaterialsToken": {
+                    "description": "Web Token that was appended to the link",
+                    "type": "string"
+                }
+            }
+        },
         "quiz.AnswerOption": {
             "type": "object",
             "properties": {
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index a2f545dc973227bf9562a6120358f9a35a4ddd09..b39336da946758345aadf855e855615703b341ab 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -85,7 +85,6 @@ definitions:
         description: Course Name
         type: string
     required:
-    - abbreviation
     - email
     - id
     - name
@@ -103,9 +102,6 @@ definitions:
         description: Contributor Email
         example: someone@example.com
         type: string
-      id:
-        description: Course ID, Provided by query
-        type: string
       lecturer:
         description: Course Lecturer
         type: string
@@ -149,9 +145,6 @@ definitions:
       abbreviation:
         description: Faculty Name Abbreviation
         type: string
-      id:
-        description: Faculty ID, Provided by Query
-        type: string
       name:
         description: Faculty Name
         type: string
@@ -162,6 +155,52 @@ definitions:
     - abbreviation
     - name
     type: object
+  lesson.AddLessonRequestPayload:
+    description: Information that should be available when you add a lesson
+    properties:
+      addLessonToken:
+        description: Web Token that was appended to the link
+        type: string
+      course_id:
+        description: Course ID
+        type: string
+      description:
+        description: Lesson Description (Can be left empty)
+        type: string
+      name:
+        description: Lesson Name
+        type: string
+      order:
+        description: Lesson Order
+        type: integer
+    required:
+    - course_id
+    - name
+    - order
+    type: object
+  lesson.UpdateLessonRequestPayload:
+    description: Information that should be available when you update a lesson
+    properties:
+      course_id:
+        description: Course ID
+        type: string
+      description:
+        description: Lesson Description (Can be left empty)
+        type: string
+      name:
+        description: Lesson Name
+        type: string
+      order:
+        description: Lesson Order
+        type: integer
+      updateLessonToken:
+        description: Web Token that was appended to the link
+        type: string
+    required:
+    - course_id
+    - name
+    - order
+    type: object
   login.LoginRequestPayload:
     description: Information that should be available when do a login process
     properties:
@@ -221,9 +260,6 @@ definitions:
       faculty_id:
         description: Faculty Id, will be set by the server
         type: string
-      id:
-        description: Major ID, provided by query
-        type: string
       name:
         description: Major Name
         type: string
@@ -298,6 +334,52 @@ definitions:
       upload_link:
         type: string
     type: object
+  materials.AddLessonMaterialsRequestPayload:
+    description: Information that should be available when you add a lesson material
+    properties:
+      addLessonMaterialsToken:
+        description: Web Token that was appended to the link
+        type: string
+      contents:
+        description: Lesson Contents
+        type: string
+      lesson_id:
+        description: Lesson ID
+        type: string
+      material_id:
+        description: Lesson Material ID, optional
+        type: string
+      order:
+        description: Lesson Material Order
+        type: integer
+    required:
+    - contents
+    - lesson_id
+    - order
+    type: object
+  materials.UpdateLessonMaterialsRequestPayload:
+    description: Information that should be available when you update a lesson material
+    properties:
+      contents:
+        description: Lesson Contents
+        type: string
+      lesson_id:
+        description: Lesson ID
+        type: string
+      material_id:
+        description: Lesson Material ID, optional
+        type: string
+      order:
+        description: Lesson Material Order
+        type: integer
+      updateLessonMaterialsToken:
+        description: Web Token that was appended to the link
+        type: string
+    required:
+    - contents
+    - lesson_id
+    - order
+    type: object
   quiz.AnswerOption:
     properties:
       answer:
@@ -1417,6 +1499,361 @@ paths:
       summary: Get courses by major
       tags:
       - course
+  /lesson:
+    put:
+      consumes:
+      - application/json
+      description: Add a new lesson with the given details
+      parameters:
+      - description: AddLessonToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Add Lesson payload
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/lesson.AddLessonRequestPayload'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Add a new lesson
+      tags:
+      - lesson
+  /lesson/{id}:
+    delete:
+      consumes:
+      - application/json
+      description: Delete a lesson with the specified ID
+      parameters:
+      - description: Lesson ID
+        in: path
+        name: id
+        required: true
+        type: string
+      - description: DeleteLessonToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Delete lesson by ID
+      tags:
+      - lesson
+    get:
+      description: Retrieve lesson data by UUID
+      parameters:
+      - description: Lesson ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Invalid UUID provided in request path
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get lesson by ID
+      tags:
+      - lesson
+    patch:
+      description: Update a lesson material with the given ID
+      parameters:
+      - description: Lesson Material ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      - description: Update Lesson Materials Payload
+        in: body
+        name: payload
+        required: true
+        schema:
+          $ref: '#/definitions/materials.UpdateLessonMaterialsRequestPayload'
+      - description: UpdateLessonMaterialsToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Update a lesson material
+      tags:
+      - lesson
+  /lesson/course/{id}:
+    get:
+      description: Retrieve lesson data by course ID
+      parameters:
+      - description: Course ID
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Invalid ID provided in request path
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get lesson by course ID
+      tags:
+      - lesson
+  /lesson/material:
+    put:
+      consumes:
+      - application/json
+      description: Add a new lesson material with the given details
+      parameters:
+      - description: AddLessonMaterialsToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      - description: Add Lesson Material payload
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/materials.AddLessonMaterialsRequestPayload'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Add a new lesson material
+      tags:
+      - lesson
+  /lesson/material/{id}:
+    delete:
+      consumes:
+      - application/json
+      description: Delete a lesson material with the specified ID
+      parameters:
+      - description: Lesson Material ID
+        in: path
+        name: id
+        required: true
+        type: string
+      - description: DeleteLessonMaterialToken
+        in: header
+        name: Authorization
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "403":
+          description: Forbidden
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "422":
+          description: Unprocessable Entity
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Delete lesson material by id
+      tags:
+      - lesson
+    get:
+      description: Retrieve lesson data by UUID
+      parameters:
+      - description: Lesson ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Invalid UUID provided in request path
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get lesson by ID
+      tags:
+      - lesson
+  /lesson/material/lesson/{id}:
+    get:
+      description: Retrieve lesson materials data by lesson ID
+      parameters:
+      - description: Lesson ID (UUID)
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: Success
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Invalid UUID provided in request path
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "401":
+          description: Unauthorized
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Get lesson materials by lesson ID
+      tags:
+      - lesson
   /material/{id}:
     delete:
       consumes:
@@ -1548,7 +1985,50 @@ paths:
       summary: Delete Content
       tags:
       - content
+  /quiz:
+    put:
+      consumes:
+      - application/json
+      description: New Quiz
+      parameters:
+      - description: Quiz id
+        format: uuid
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: New Quiz
+      tags:
+      - quiz
   /quiz/{id}:
+    delete:
+      consumes:
+      - application/json
+      description: Delete Quiz
+      parameters:
+      - description: Quiz id
+        format: uuid
+        in: path
+        name: id
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Delete Quiz
+      tags:
+      - quiz
     get:
       consumes:
       - application/json
diff --git a/handler/di.go b/handler/di.go
index 399ef81ecbb23c9d70b0431c6129610c92d5dadc..aefdce321930ee174f0b93d23d3eadc8f3988adc 100644
--- a/handler/di.go
+++ b/handler/di.go
@@ -6,6 +6,7 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/handler/auth"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/common"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/course"
+	"gitlab.informatika.org/ocw/ocw-backend/handler/lesson"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/material"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/handler/reset"
@@ -37,6 +38,10 @@ var HandlerSet = wire.NewSet(
 	wire.Struct(new(course.CourseHandlerImpl), "*"),
 	wire.Bind(new(course.CourseHandler), new(*course.CourseHandlerImpl)),
 
+	// Lesson
+	wire.Struct(new(lesson.LessonHandlerImpl), "*"),
+	wire.Bind(new(lesson.LessonHandler), new(*lesson.LessonHandlerImpl)),
+	
 	// Material
 	wire.Struct(new(material.MaterialHandlerImpl), "*"),
 	wire.Bind(new(material.MaterialHandler), new(*material.MaterialHandlerImpl)),
diff --git a/handler/lesson/addLesson.go b/handler/lesson/addLesson.go
new file mode 100644
index 0000000000000000000000000000000000000000..162892b3af78a0b9d12b1c463139004e67c589e7
--- /dev/null
+++ b/handler/lesson/addLesson.go
@@ -0,0 +1,100 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+	"strings"
+
+	"github.com/go-playground/validator/v10"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+)
+
+// Index godoc
+//
+//	@Summary		Add a new lesson
+//	@Description	Add a new lesson with the given details
+//	@Tags			lesson
+//	@Accept			json
+//	@Produce		json
+//	@Param			Authorization	header		string							true	"AddLessonToken"
+//	@Param			data			body		lesson.AddLessonRequestPayload	true	"Add Lesson payload"
+//	@Success		200				{object}	web.BaseResponse				"Success"
+//	@Failure		400				{object}	web.BaseResponse				"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse				"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse				"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse				"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse				"Internal Server Error"
+//	@Router			/lesson [put]
+func (l LessonHandlerImpl) AddLesson(w http.ResponseWriter, r *http.Request) {
+	payload := lesson.AddLessonRequestPayload{}
+
+	// Validate payload
+	if r.Header.Get("Content-Type") != "application/json" {
+		payload := l.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	if err := l.HttpUtil.ParseJson(r, &payload); err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error())
+		l.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	validate := validator.New()
+	if err := validate.Struct(payload); err != nil {
+		if _, ok := err.(*validator.InvalidValidationError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+			l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors))
+		payload := l.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	// Confirm Valid Website Token
+	validateTokenHeader := r.Header.Get("Authorization")
+	if validateTokenHeader == "" {
+		payload := l.WrapperUtil.ErrorResponseWrap("token is required", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+		return
+	}
+
+	token := strings.Split(validateTokenHeader, " ")
+	if len(token) != 2 {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+		return
+	}
+
+	if token[0] != "Bearer" {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+		return
+	}
+
+	payload.AddLessonToken = token[1]
+	err := l.LessonService.AddLesson(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[LESSON] some error happened when validating URL: %s", err.Error()),
+		)
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(nil)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
\ No newline at end of file
diff --git a/handler/lesson/addLessonMaterial.go b/handler/lesson/addLessonMaterial.go
new file mode 100644
index 0000000000000000000000000000000000000000..bd549025b68e6fcc72e63dbfc18b0964d4dc9281
--- /dev/null
+++ b/handler/lesson/addLessonMaterial.go
@@ -0,0 +1,102 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+	"strings"
+
+	"github.com/go-playground/validator/v10"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+)
+
+// Index godoc
+//
+//	@Summary		Add a new lesson material
+//	@Description	Add a new lesson material with the given details
+//	@Tags			lesson
+//	@Accept			json
+//	@Produce		json
+//	@Param			Authorization	header		string							true	"AddLessonMaterialsToken"
+//	@Param			data			body		materials.AddLessonMaterialsRequestPayload	true	"Add Lesson Material payload"
+//	@Success		200				{object}	web.BaseResponse				"Success"
+//	@Failure		400				{object}	web.BaseResponse				"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse				"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse				"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse				"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse				"Internal Server Error"
+//	@Router			/lesson/material [put]
+func (l LessonHandlerImpl) AddLessonMaterial(w http.ResponseWriter, r *http.Request) {
+	payload := materials.AddLessonMaterialsRequestPayload{}
+
+	// Validate payload
+	if r.Header.Get("Content-Type") != "application/json" {
+		payload := l.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	if err := l.HttpUtil.ParseJson(r, &payload); err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error())
+		l.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	validate := validator.New()
+	if err := validate.Struct(payload); err != nil {
+		if _, ok := err.(*validator.InvalidValidationError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+			l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors))
+		payload := l.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	// Confirm Valid Website Token
+	validateTokenHeader := r.Header.Get("Authorization")
+
+	if validateTokenHeader == "" {
+		payload := l.WrapperUtil.ErrorResponseWrap("token is required", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+		return
+	}
+
+	token := strings.Split(validateTokenHeader, " ")
+
+	if len(token) != 2 {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+		return
+	}
+
+	if token[0] != "Bearer" {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+		return
+	}
+
+	payload.AddLessonMaterialsToken = token[1]
+	err := l.LessonService.AddLessonMaterial(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[LESSON] some error happened when validating URL: %s", err.Error()),
+		)
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(nil)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/lesson/deleteLesson.go b/handler/lesson/deleteLesson.go
new file mode 100644
index 0000000000000000000000000000000000000000..e00f057f39a8a931716c2f24cb6d3a0781ad8b3a
--- /dev/null
+++ b/handler/lesson/deleteLesson.go
@@ -0,0 +1,84 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+	"strings"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+)
+
+// Index godoc
+//
+//	@Summary		Delete lesson by ID
+//	@Description	Delete a lesson with the specified ID
+//	@Tags			lesson
+//	@Accept			json
+//	@Produce		json
+//  @Param          id			  path        string                          true        "Lesson ID"
+//	@Param			Authorization	header		string							true	"DeleteLessonToken"
+//	@Success		200				{object}	web.BaseResponse				"Success"
+//	@Failure		400				{object}	web.BaseResponse				"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse				"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse				"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse				"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse				"Internal Server Error"
+//	@Router			/lesson/{id} [delete]
+func (l LessonHandlerImpl) DeleteLesson(w http.ResponseWriter, r *http.Request) {
+	payload := lesson.DeleteByUUIDRequestPayload{}
+	validateTokenHeader := r.Header.Get("Authorization")
+
+	if validateTokenHeader == "" {
+		payload := l.WrapperUtil.ErrorResponseWrap("token is required", nil)
+		l.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+		return
+	}
+
+	token := strings.Split(validateTokenHeader, " ")
+
+	if len(token) != 2 {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	if token[0] != "Bearer" {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	id, err := uuid.Parse(chi.URLParam(r, "id"))
+
+	if err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid id", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	payload.DeleteLessonToken = token[1]
+	payload.ID = id
+	err = l.LessonService.DeleteLesson(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[LESSON] some error happened when validating URL: %s", err.Error()),
+		)
+
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(nil)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
\ No newline at end of file
diff --git a/handler/lesson/deleteLessonMaterial.go b/handler/lesson/deleteLessonMaterial.go
new file mode 100644
index 0000000000000000000000000000000000000000..ee814d240edca4162133a8ad6515e53b83d5d51d
--- /dev/null
+++ b/handler/lesson/deleteLessonMaterial.go
@@ -0,0 +1,85 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+	"strings"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+)
+
+// Index godoc
+//
+//	@Summary		Delete lesson material by id
+//	@Description	Delete a lesson material with the specified ID
+//  @Tags			lesson
+//	@Accept			json
+//	@Produce		json
+//  @Param          id			  path        string                          true        "Lesson Material ID"
+//	@Param			Authorization	header		string							true	"DeleteLessonMaterialToken"
+//	@Success		200				{object}	web.BaseResponse				"Success"
+//	@Failure		400				{object}	web.BaseResponse				"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse				"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse				"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse				"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse				"Internal Server Error"
+//	@Router			/lesson/material/{id} [delete]
+func (l LessonHandlerImpl) DeleteLessonMaterial(w http.ResponseWriter, r *http.Request) {
+	payload := materials.DeleteByUUIDRequestPayload{}
+	validateTokenHeader := r.Header.Get("Authorization")
+
+	if validateTokenHeader == "" {
+		payload := l.WrapperUtil.ErrorResponseWrap("token is required", nil)
+		l.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+		return
+	}
+
+	token := strings.Split(validateTokenHeader, " ")
+
+	if len(token) != 2 {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	if token[0] != "Bearer" {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	id, err := uuid.Parse(chi.URLParam(r, "id"))
+
+	if err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid id", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+
+	payload.DeleteLessonMaterialsToken = token[1]
+	payload.ID = id
+	err = l.LessonService.DeleteLessonMaterial(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[LESSON] some error happened when validating URL: %s", err.Error()),
+		)
+
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(nil)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/lesson/getLesson.go b/handler/lesson/getLesson.go
new file mode 100644
index 0000000000000000000000000000000000000000..6fe56562324ca2a8e58330ceb1fb593eb09f2301
--- /dev/null
+++ b/handler/lesson/getLesson.go
@@ -0,0 +1,55 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+)
+
+// Index godoc
+//
+//	@Summary		Get lesson by ID
+//	@Description	Retrieve lesson data by UUID
+//	@Tags			lesson
+//	@Produce		json
+//	@Param			id	path		string				true	"Lesson ID (UUID)"
+//	@Success		200	{object}	web.BaseResponse	"Success"
+//	@Failure		400	{object}	web.BaseResponse	"Invalid UUID provided in request path"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/lesson/{id} [get]
+func (l LessonHandlerImpl) GetLesson(w http.ResponseWriter, r *http.Request) {
+	payload := lesson.GetByUUIDRequestPayload{}
+	id, err := uuid.Parse(chi.URLParam(r, "id"))
+
+	if err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid id", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	payload.ID = id
+	packet, err := l.LessonService.GetLesson(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[LESSON] some error happened when validating URL: %s", err.Error()),
+		)
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(packet)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
\ No newline at end of file
diff --git a/handler/lesson/getLessonMaterial.go b/handler/lesson/getLessonMaterial.go
new file mode 100644
index 0000000000000000000000000000000000000000..f6449cd6b95a01cdf6418f47b72849a553cadd12
--- /dev/null
+++ b/handler/lesson/getLessonMaterial.go
@@ -0,0 +1,55 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+)
+
+// Index godoc
+//
+//	@Summary		Get lesson by ID
+//	@Description	Retrieve lesson data by UUID
+//	@Tags			lesson
+//	@Produce		json
+//	@Param			id	path		string				true	"Lesson ID (UUID)"
+//	@Success		200	{object}	web.BaseResponse	"Success"
+//	@Failure		400	{object}	web.BaseResponse	"Invalid UUID provided in request path"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/lesson/material/{id} [get]
+func (l LessonHandlerImpl) GetLessonMaterial(w http.ResponseWriter, r *http.Request) {
+	payload := materials.GetByUUIDRequestPayload{}
+	id, err := uuid.Parse(chi.URLParam(r, "id"))
+
+	if err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid id", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+	
+	payload.ID = id
+	packet, err := l.LessonService.GetLessonMaterial(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[LESSON] some error happened when validating URL: %s", err.Error()),
+		)
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(packet)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
\ No newline at end of file
diff --git a/handler/lesson/getLessonMaterialsByLesson.go b/handler/lesson/getLessonMaterialsByLesson.go
new file mode 100644
index 0000000000000000000000000000000000000000..dcb37eb5dfee8fd45a338d9a480b17b20c77218b
--- /dev/null
+++ b/handler/lesson/getLessonMaterialsByLesson.go
@@ -0,0 +1,55 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+	
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+)
+
+// Index godoc
+//
+//	@Summary		Get lesson materials by lesson ID
+//	@Description	Retrieve lesson materials data by lesson ID
+//	@Tags			lesson
+//	@Produce		json
+//	@Param			id	path		string				true	"Lesson ID (UUID)"
+//	@Success		200	{object}	web.BaseResponse	"Success"
+//	@Failure		400	{object}	web.BaseResponse	"Invalid UUID provided in request path"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/lesson/material/lesson/{id} [get]
+func (l LessonHandlerImpl) GetLessonMaterialsByLesson(w http.ResponseWriter, r *http.Request) {
+	payload := materials.GetByUUIDRequestPayload{}
+	id, err := uuid.Parse(chi.URLParam(r, "id"))
+
+	if err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid id", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+	
+	payload.ID = id
+	packet, err := l.LessonService.GetLessonMaterials(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[LESSON] some error happened when validating URL: %s", err.Error()),
+		)
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(packet)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
\ No newline at end of file
diff --git a/handler/lesson/getLessonsByCourse.go b/handler/lesson/getLessonsByCourse.go
new file mode 100644
index 0000000000000000000000000000000000000000..fd2956b7f2cd1a90fb428dcd1d7945783c2dfd50
--- /dev/null
+++ b/handler/lesson/getLessonsByCourse.go
@@ -0,0 +1,47 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+
+	"github.com/go-chi/chi/v5"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+)
+
+// Index godoc
+//
+//	@Summary		Get lesson by course ID
+//	@Description	Retrieve lesson data by course ID
+//	@Tags			lesson
+//	@Produce		json
+//	@Param			id	path		string				true	"Course ID"
+//	@Success		200	{object}	web.BaseResponse	"Success"
+//	@Failure		400	{object}	web.BaseResponse	"Invalid ID provided in request path"
+//	@Failure		401	{object}	web.BaseResponse	"Unauthorized"
+//	@Failure		500	{object}	web.BaseResponse	"Internal Server Error"
+//	@Router			/lesson/course/{id} [get]
+func (l LessonHandlerImpl) GetLessonsByCourse(w http.ResponseWriter, r *http.Request) {
+	payload := lesson.GetByStringRequestPayload{}
+
+	payload.ID = chi.URLParam(r, "id")
+	packet, err := l.LessonService.GetLessons(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[LESSON] some error happened when validating URL: %s", err.Error()),
+		)
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(packet)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
\ No newline at end of file
diff --git a/handler/lesson/handler.go b/handler/lesson/handler.go
new file mode 100644
index 0000000000000000000000000000000000000000..874c8ea2727ebf3075a106c7b57eb6dad29ca08e
--- /dev/null
+++ b/handler/lesson/handler.go
@@ -0,0 +1,17 @@
+package lesson
+
+import (
+	r "gitlab.informatika.org/ocw/ocw-backend/repository/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/service/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/service/logger"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/httputil"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/wrapper"
+)
+
+type LessonHandlerImpl struct {
+	r.LessonRepository
+	lesson.LessonService
+	httputil.HttpUtil
+	wrapper.WrapperUtil
+	logger.Logger
+}
\ No newline at end of file
diff --git a/handler/lesson/types.go b/handler/lesson/types.go
new file mode 100644
index 0000000000000000000000000000000000000000..f04fef9df33be6d8ab41685f97aec022cbb27e07
--- /dev/null
+++ b/handler/lesson/types.go
@@ -0,0 +1,23 @@
+package lesson
+
+import "net/http"
+
+type LessonHandler interface {
+	// Get
+	GetLesson(w http.ResponseWriter, r *http.Request)
+	GetLessonsByCourse(w http.ResponseWriter, r *http.Request)
+	GetLessonMaterial(w http.ResponseWriter, r *http.Request)
+	GetLessonMaterialsByLesson(w http.ResponseWriter, r *http.Request)
+
+	// Add (Put)
+	AddLesson(w http.ResponseWriter, r *http.Request)
+	AddLessonMaterial(w http.ResponseWriter, r *http.Request)
+
+	// Update
+	UpdateLesson(w http.ResponseWriter, r *http.Request)
+	UpdateLessonMaterial(w http.ResponseWriter, r *http.Request)
+
+	// Delete
+	DeleteLesson(w http.ResponseWriter, r *http.Request)
+	DeleteLessonMaterial(w http.ResponseWriter, r *http.Request)
+}
diff --git a/handler/lesson/updateLesson.go b/handler/lesson/updateLesson.go
new file mode 100644
index 0000000000000000000000000000000000000000..5638be670ce3be0b077dd6b2a9a6fbcee91b6381
--- /dev/null
+++ b/handler/lesson/updateLesson.go
@@ -0,0 +1,114 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+	"strings"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/go-playground/validator/v10"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+)
+
+// Index godoc
+//
+//	@Summary		Update a lesson
+//	@Description	Update a lesson with the given ID
+//	@Tags			lesson
+//	@Param			id				path		string								true	"Lesson ID (UUID)"
+//	@Param			payload			body		lesson.UpdateLessonRequestPayload	true	"Update Lesson Payload"
+//	@Param			Authorization	header		string								true	"UpdateLessonToken"
+//	@Success		200				{object}	web.BaseResponse					"Success"
+//	@Failure		400				{object}	web.BaseResponse					"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse					"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse					"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse					"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse					"Internal Server Error"
+//	@Router			/lesson/{id} [patch]
+func (l LessonHandlerImpl) UpdateLesson(w http.ResponseWriter, r *http.Request) {
+	payload := lesson.UpdateLessonRequestPayload{}
+	validate := validator.New()
+
+	// Validate payload
+	if r.Header.Get("Content-Type") != "application/json" {
+		payload := l.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	if err := l.HttpUtil.ParseJson(r, &payload); err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error())
+		l.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	if err := validate.Struct(payload); err != nil {
+		if _, ok := err.(*validator.InvalidValidationError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+			l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors))
+		payload := l.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	// Confirm Valid Website Token
+	validateTokenHeader := r.Header.Get("Authorization")
+
+	if validateTokenHeader == "" {
+		payload := l.WrapperUtil.ErrorResponseWrap("token is required", nil)
+		l.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+		return
+	}
+
+	token := strings.Split(validateTokenHeader, " ")
+
+	if len(token) != 2 {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	if token[0] != "Bearer" {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	id, err := uuid.Parse(chi.URLParam(r, "id"))
+
+	if err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid id", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	payload.UpdateLessonToken = token[1]
+	payload.ID = id
+	err = l.LessonService.UpdateLesson(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[RESET] some error happened when validating URL: %s", err.Error()),
+		)
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(nil)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
+
+	
\ No newline at end of file
diff --git a/handler/lesson/updateLessonMaterial.go b/handler/lesson/updateLessonMaterial.go
new file mode 100644
index 0000000000000000000000000000000000000000..bb3689db902d9918de59840e38d76777d02b9543
--- /dev/null
+++ b/handler/lesson/updateLessonMaterial.go
@@ -0,0 +1,114 @@
+package lesson
+
+import (
+	"fmt"
+	"net/http"
+	"strings"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/go-playground/validator/v10"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+)
+
+// Index godoc
+//
+//	@Summary		Update a lesson material
+//	@Description	Update a lesson material with the given ID
+//	@Tags			lesson
+//	@Param			id				path		string								true	"Lesson Material ID (UUID)"
+//	@Param			payload			body		materials.UpdateLessonMaterialsRequestPayload	true	"Update Lesson Materials Payload"
+//	@Param			Authorization	header		string								true	"UpdateLessonMaterialsToken"
+//	@Success		200				{object}	web.BaseResponse					"Success"
+//	@Failure		400				{object}	web.BaseResponse					"Bad Request"
+//	@Failure		401				{object}	web.BaseResponse					"Unauthorized"
+//	@Failure		403				{object}	web.BaseResponse					"Forbidden"
+//	@Failure		422				{object}	web.BaseResponse					"Unprocessable Entity"
+//	@Failure		500				{object}	web.BaseResponse					"Internal Server Error"
+//	@Router			/lesson/{id} [patch]
+func (l LessonHandlerImpl) UpdateLessonMaterial(w http.ResponseWriter, r *http.Request) {
+	payload := materials.UpdateLessonMaterialsRequestPayload{}
+	validate := validator.New()
+
+	// Validate payload
+	if r.Header.Get("Content-Type") != "application/json" {
+		payload := l.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil)
+		l.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	if err := l.HttpUtil.ParseJson(r, &payload); err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error())
+		l.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	if err := validate.Struct(payload); err != nil {
+		if _, ok := err.(*validator.InvalidValidationError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+			l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors))
+		payload := l.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	// Confirm Valid Website Token
+	validateTokenHeader := r.Header.Get("Authorization")
+
+	if validateTokenHeader == "" {
+		payload := l.WrapperUtil.ErrorResponseWrap("token is required", nil)
+		l.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+		return
+	}
+
+	token := strings.Split(validateTokenHeader, " ")
+
+	if len(token) != 2 {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	if token[0] != "Bearer" {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	id, err := uuid.Parse(chi.URLParam(r, "id"))
+
+	if err != nil {
+		payload := l.WrapperUtil.ErrorResponseWrap("invalid id", nil)
+		l.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	payload.UpdateLessonMaterialsToken = token[1]
+	payload.ID = id
+	err = l.LessonService.UpdateLessonMaterial(payload)
+
+	if err != nil {
+		if errData, ok := err.(web.ResponseError); ok {
+			payload := l.WrapperUtil.ErrorResponseWrap(errData.Error(), errData)
+			l.HttpUtil.WriteJson(w, http.StatusUnauthorized, payload)
+			return
+		}
+
+		l.Logger.Error(
+			fmt.Sprintf("[RESET] some error happened when validating URL: %s", err.Error()),
+		)
+		payload := l.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+		l.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		return
+	}
+
+	responsePayload := l.WrapperUtil.SuccessResponseWrap(nil)
+	l.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
+
+	
\ No newline at end of file
diff --git a/handler/quiz/delete.go b/handler/quiz/delete.go
new file mode 100644
index 0000000000000000000000000000000000000000..642e1661fa478b38a3b591b74c616acd0e4d6b26
--- /dev/null
+++ b/handler/quiz/delete.go
@@ -0,0 +1,86 @@
+package quiz
+
+import (
+	"net/http"
+	"strings"
+
+	"github.com/go-chi/chi/v5"
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/quiz"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+)
+
+// Index godoc
+//
+//	@Tags					quiz
+//	@Summary			Delete Quiz
+//	@Description	Delete Quiz
+//	@Produce			json
+//	@Accept				json
+//	@Param				id path string true "Quiz id" Format(uuid)
+//	@Success			200	{object}	web.BaseResponse
+//	@Router				/quiz/{id} [delete]
+func (m QuizHandlerImpl) DeleteQuiz(w http.ResponseWriter, r *http.Request) {
+	payload := quiz.DeleteRequestPayload{}
+	quizId := chi.URLParam(r, "id")
+
+	if quizId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("quiz id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	id, err := uuid.Parse(quizId)
+
+	if err != nil {
+		// invalid uuid
+		payload := m.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	// Confirm Valid Website Token
+	validateTokenHeader := r.Header.Get("Authorization")
+
+	if validateTokenHeader == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("token is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+		return
+	}
+
+	token := strings.Split(validateTokenHeader, " ")
+
+	if len(token) != 2 {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	if token[0] != "Bearer" {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	payload.DeleteToken = token[1]
+	payload.ID = id
+
+	err = m.QuizService.DeleteQuiz(payload)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(nil)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+
+}
\ No newline at end of file
diff --git a/handler/quiz/get.go b/handler/quiz/get.go
index 799ca822a991240a0c6febccb29640720f1b5e67..b88bde2955671872d7ad047c2be17541e450b491 100644
--- a/handler/quiz/get.go
+++ b/handler/quiz/get.go
@@ -2,10 +2,12 @@ package quiz
 
 import (
 	"net/http"
+	"strings"
 
 	"github.com/go-chi/chi/v5"
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/quiz"
 )
 
 // Index godoc
@@ -55,3 +57,77 @@ func (m QuizHandlerImpl) GetQuizDetail(w http.ResponseWriter, r *http.Request) {
 	m.HttpUtil.WriteSuccessJson(w, responsePayload)
 
 }
+
+// Index godoc
+//
+//	@Tags					quiz
+//	@Summary			Get Quiz Link
+//	@Description	Get Quiz Link
+//	@Produce			json
+//	@Accept				json
+//	@Param				id path string true "Quiz id" Format(uuid)
+//	@Success			200	{object}	web.BaseResponse
+//	@Router				/quiz/link/{id} [get]
+
+func (m QuizHandlerImpl) GetQuizLink(w http.ResponseWriter, r *http.Request) {
+	payload := quiz.UpdateQuizRequestPayload{}
+	quizId := chi.URLParam(r, "id")
+
+	if quizId == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("quiz id is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	id, err := uuid.Parse(quizId)
+
+	if err != nil {
+		// invalid uuid
+		payload := m.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+	
+	// Confirm Valid Website Token
+	validateTokenHeader := r.Header.Get("Authorization")
+
+	if validateTokenHeader == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("token is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+		return
+	}
+
+	token := strings.Split(validateTokenHeader, " ")
+
+	if len(token) != 2 {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	if token[0] != "Bearer" {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	payload.UpdateQuizToken = token[1]
+	payload.ID = id
+	response, err := m.QuizService.GetQuiz(payload)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(response)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/quiz/new.go b/handler/quiz/new.go
new file mode 100644
index 0000000000000000000000000000000000000000..ca9ce5ed0b1d32b4d8cab8f568ec5a24221bb175
--- /dev/null
+++ b/handler/quiz/new.go
@@ -0,0 +1,94 @@
+package quiz
+
+import (
+	"net/http"
+	"strings"
+
+	"github.com/go-playground/validator/v10"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/quiz"
+)
+
+// Index godoc
+//
+//	@Tags					quiz
+//	@Summary			New Quiz
+//	@Description	New Quiz
+//	@Produce			json
+//	@Accept				json
+//	@Param				id path string true "Quiz id" Format(uuid)
+//	@Success			200	{object}	web.BaseResponse
+//	@Router				/quiz [put]
+func (m QuizHandlerImpl) NewQuiz(w http.ResponseWriter, r *http.Request) {
+	payload := quiz.AddQuizRequestPayload{}
+
+	// Validate payload
+	if r.Header.Get("Content-Type") != "application/json" {
+		payload := m.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil)
+		m.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	if err := m.HttpUtil.ParseJson(r, &payload); err != nil {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error())
+		m.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	validate := validator.New()
+	if err := validate.Struct(payload); err != nil {
+		if _, ok := err.(*validator.InvalidValidationError); ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors))
+		payload := m.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	// Confirm Valid Website Token
+	validateTokenHeader := r.Header.Get("Authorization")
+
+	if validateTokenHeader == "" {
+		payload := m.WrapperUtil.ErrorResponseWrap("token is required", nil)
+		m.HttpUtil.WriteJson(w, http.StatusForbidden, payload)
+		return
+	}
+
+	token := strings.Split(validateTokenHeader, " ")
+
+	if len(token) != 2 {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	if token[0] != "Bearer" {
+		payload := m.WrapperUtil.ErrorResponseWrap("invalid token", nil)
+		m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	payload.AddQuizToken = token[1]
+
+	response, err := m.QuizService.NewQuiz(payload)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := m.WrapperUtil.ErrorResponseWrap(respErr.Error(), respErr)
+
+			m.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		} else {
+			payload := m.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			m.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := m.WrapperUtil.SuccessResponseWrap(response)
+	m.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
\ No newline at end of file
diff --git a/handler/quiz/type.go b/handler/quiz/type.go
index 8c3bf6f5567cf7f04be9e42b67558279a0f6159d..306cc813840a08bbbe4e7379ad436e268aba38cc 100644
--- a/handler/quiz/type.go
+++ b/handler/quiz/type.go
@@ -9,4 +9,7 @@ type QuizHandler interface {
 	TakeQuiz(w http.ResponseWriter, r *http.Request)
 	GetQuizSolution(w http.ResponseWriter, r *http.Request)
 	FinishQuiz(w http.ResponseWriter, r *http.Request)
+	NewQuiz(w http.ResponseWriter, r *http.Request)
+	GetQuizLink(w http.ResponseWriter, r *http.Request)
+	DeleteQuiz(w http.ResponseWriter, r *http.Request)
 }
diff --git a/model/domain/course/course.go b/model/domain/course/course.go
index 17d592f2301d2bd0097a7fb465e5b8474b46cc09..f57db686acab2cc98221a5bc9cebf2ae85161843 100644
--- a/model/domain/course/course.go
+++ b/model/domain/course/course.go
@@ -13,7 +13,7 @@ type Major struct {
 	ID           uuid.UUID `json:"id" gorm:"primaryKey;type:uuid"`
 	Name         string    `json:"name"`
 	Fac_id       uuid.UUID `json:"fac_id" gorm:"type:uuid"`
-	Faculty      *Faculty  `json:"faculty" gorm:"foreignKey:Fac_id"`
+	Faculty      *Faculty  `json:"-" gorm:"foreignKey:Fac_id"`
 	Abbreviation string    `json:"abbreviation"`
 }
 
@@ -21,7 +21,7 @@ type Course struct {
 	ID           string    `json:"id" gorm:"primaryKey"`
 	Name         string    `json:"name"`
 	Major_id     uuid.UUID `json:"major_id" gorm:"type:uuid"`
-	Major        *Major    `json:"major" gorm:"foreignKey:Major_id"`
+	Major        *Major    `json:"-" gorm:"foreignKey:Major_id"`
 	Description  string    `json:"description"`
 	Email        string    `json:"email"`
 	Abbreviation string    `json:"abbreviation"`
diff --git a/model/domain/lesson/lesson.go b/model/domain/lesson/lesson.go
new file mode 100644
index 0000000000000000000000000000000000000000..621295e7dd5bbf7116654a5fef038cca7981e6ab
--- /dev/null
+++ b/model/domain/lesson/lesson.go
@@ -0,0 +1,34 @@
+package lesson
+
+import (
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/material"
+)
+
+type Lesson struct {
+	ID          uuid.UUID      `json:"id" gorm:"primaryKey;type:uuid"`
+	Name        string         `json:"name"`
+	CourseID    string         `json:"course_id"`
+	Course      *course.Course `json:"-" gorm:"foreignKey:CourseID"`
+	Order       int            `json:"order"`
+	Description string         `json:"description"`
+}
+
+type LessonMaterials struct {
+	ID         uuid.UUID          `json:"id" gorm:"primaryKey;type:uuid"`
+	LessonID   uuid.UUID          `json:"lesson_id"`
+	Lesson     *Lesson            `json:"-" gorm:"foreignKey:LessonID"`
+	Order      int                `json:"order"`
+	MaterialID uuid.UUID          `json:"material_id"`
+	Material   *material.Material `json:"-" gorm:"foreignKey:MaterialID"`
+	Contents   string             `json:"contents"`
+}
+
+func (Lesson) TableName() string {
+	return "lesson"
+}
+
+func (LessonMaterials) TableName() string {
+	return "lesson_materials"
+}
diff --git a/model/web/course/faculty/request.go b/model/web/course/faculty/request.go
index 1c08bddf6fc2410cc7bdec8542c9edc17f5a95e9..2233e13fd7b7232af52e5340b686eb7853721ae0 100644
--- a/model/web/course/faculty/request.go
+++ b/model/web/course/faculty/request.go
@@ -22,7 +22,7 @@ type UpdateFacultyRequestPayload struct {
 	UpdateFacultyToken string
 
 	// Faculty ID, Provided by Query
-	ID uuid.UUID
+	ID uuid.UUID `json:"-" validate:"required"`
 
 	// Faculty Name
 	Name string `json:"name" validate:"required"`
diff --git a/model/web/course/major/request.go b/model/web/course/major/request.go
index 53bc733584b8c437905b7bf7ef9d3a636866262b..1238cbf944d811b7e7c343b174c48974d64faab5 100644
--- a/model/web/course/major/request.go
+++ b/model/web/course/major/request.go
@@ -29,7 +29,7 @@ type UpdateMajorRequestPayload struct {
 	UpdateMajorToken string
 
 	// Major ID, provided by query
-	ID uuid.UUID
+	ID uuid.UUID `json:"-" validate:"required"`
 
 	// Major Name
 	Name string `json:"name" validate:"required"`
diff --git a/model/web/course/request.go b/model/web/course/request.go
index 0fad2befd53b36b1722fa4d295123606277841e3..20b446d8e06a7f4acb316d52e1c16d9e4b4f6607 100644
--- a/model/web/course/request.go
+++ b/model/web/course/request.go
@@ -27,7 +27,7 @@ type AddCourseRequestPayload struct {
 	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
 
 	// Course Name Abbreviation
-	Abbreviation string `json:"abbreviation" validate:"required"`
+	Abbreviation string `json:"abbreviation"`
 }
 
 // DeleteCourse Request Payload
@@ -37,7 +37,7 @@ type DeleteByStringRequestPayload struct {
 	DeleteCourseToken string
 
 	// Course ID, provided by query
-	ID string
+	ID string `json:"-" validate:"required"`
 }
 
 
@@ -45,14 +45,14 @@ type DeleteByStringRequestPayload struct {
 //	@Description	Information that should be available when you get using course id (string)
 type GetByStringRequestPayload struct {
 	// Course ID, provided by query
-	ID string
+	ID string `json:"-" validate:"required"`
 }
 
 // GetUUID Request Payload
 //	@Description	Information that should be available when you get using major/faculty id (string)
 type GetByUUIDRequestPayload struct {
 	// Major/Faculty ID, provided by query
-	ID uuid.UUID
+	ID uuid.UUID `json:"-" validate:"required"`
 }
 
 // UpdateCourse Request Payload
@@ -62,7 +62,7 @@ type UpdateCourseRequestPayload struct {
 	UpdateCourseToken string
 
 	// Course ID, Provided by query
-	ID string `json:"id"`
+	ID string `json:"-" validate:"required"`
 
 	// Course Name
 	Name string `json:"name" validate:"required"`
diff --git a/model/web/error_code.go b/model/web/error_code.go
index 9b29b2d14e9caac4d013f7474592e25ff70b66d5..f150f3f1bf7d5211713144d3c5bfaaac3a11c618 100644
--- a/model/web/error_code.go
+++ b/model/web/error_code.go
@@ -12,7 +12,10 @@ const (
 	FacultyNotExist    string = "FACULTY_NOT_EXIST"
 	MajorNotExist      string = "MAJOR_NOT_EXIST"
 	CourseNotExist     string = "COURSE_NOT_EXIST"
+	LessonNotExist     string = "LESSON_NOT_EXIST"
+	LessonMaterialNotExist string = "LESSON_MATERIAL_NOT_EXIST"
 	IDExists           string = "ID_ALREADY_EXISTS"
+	NotExist           string = "NOT_EXIST"
 
 	TokenError string = "TOKEN_ERROR"
 )
diff --git a/model/web/lesson/materials/request.go b/model/web/lesson/materials/request.go
new file mode 100644
index 0000000000000000000000000000000000000000..b20dcbb537886cd4704dfa401ffd695da77196ef
--- /dev/null
+++ b/model/web/lesson/materials/request.go
@@ -0,0 +1,63 @@
+package materials
+
+import (
+	"github.com/google/uuid"
+)
+
+// AddLessonMaterials Request Payload
+//	@Description	Information that should be available when you add a lesson material
+type AddLessonMaterialsRequestPayload struct {
+	// Web Token that was appended to the link
+	AddLessonMaterialsToken string
+
+	// Lesson ID
+	LessonID uuid.UUID `json:"lesson_id" validate:"required"`
+
+	// Lesson Material Order
+	Order int `json:"order" validate:"required"`
+
+	// Lesson Material ID, optional
+	MaterialID uuid.UUID `json:"material_id"`
+
+	// Lesson Contents
+	Contents string `json:"contents" validate:"required"`
+}
+
+// DeleteLessonMaterials Request Payload
+//	@Description	Information that should be available when you delete using lesson material id (uuid)
+type DeleteByUUIDRequestPayload struct {
+	// Web Token that was appended to the link
+	DeleteLessonMaterialsToken string
+
+	// Lesson Material ID, provided by query
+	ID uuid.UUID `json:"-" validate:"required"`
+}
+
+// UpdateLessonMaterials Request Payload
+//	@Description	Information that should be available when you update a lesson material
+type UpdateLessonMaterialsRequestPayload struct {
+	// Web Token that was appended to the link
+	UpdateLessonMaterialsToken string
+
+	// Lesson Material ID, provided by query
+	ID uuid.UUID `json:"-" validate:"required"`
+
+	// Lesson ID
+	LessonID uuid.UUID `json:"lesson_id" validate:"required"`
+
+	// Lesson Material Order
+	Order int `json:"order" validate:"required"`
+
+	// Lesson Material ID, optional
+	MaterialID uuid.UUID `json:"material_id"`
+
+	// Lesson Contents
+	Contents string `json:"contents" validate:"required"`
+}
+
+// GetUUID Request Payload
+//	@Description	Information that should be available when you get using id or lesson id (uuid)
+type GetByUUIDRequestPayload struct {
+	// Lesson ID, provided by query
+	ID uuid.UUID `json:"-" validate:"required"`
+}
\ No newline at end of file
diff --git a/model/web/lesson/request.go b/model/web/lesson/request.go
new file mode 100644
index 0000000000000000000000000000000000000000..4a999f7d45320e58d51a3bf4bbd18947f9a5c991
--- /dev/null
+++ b/model/web/lesson/request.go
@@ -0,0 +1,68 @@
+package lesson
+
+import "github.com/google/uuid"
+
+// AddLesson Request Payload
+//	@Description	Information that should be available when you add a lesson
+type AddLessonRequestPayload struct {
+	// Web Token that was appended to the link
+	AddLessonToken string
+
+	// Lesson Name
+	Name string `json:"name" validate:"required"`
+
+	// Course ID
+	CourseID string `json:"course_id" validate:"required"`
+	
+	// Lesson Order
+	Order int `json:"order" validate:"required"`
+
+	// Lesson Description (Can be left empty)
+	Description string `json:"description"`
+}
+
+// DeleteLesson Request Payload
+//	@Description	Information that should be available when you delete using lesson id (uuid)
+type DeleteByUUIDRequestPayload struct {
+	// Web Token that was appended to the link
+	DeleteLessonToken string
+
+	// Lesson ID, provided by query
+	ID uuid.UUID `json:"-" validate:"required"`
+}
+
+// UpdateLesson Request Payload
+//	@Description	Information that should be available when you update a lesson
+type UpdateLessonRequestPayload struct {
+	// Web Token that was appended to the link
+	UpdateLessonToken string
+
+	// Lesson ID, provided by query
+	ID uuid.UUID `json:"-" validate:"required"`
+
+	// Lesson Name
+	Name string `json:"name" validate:"required"`
+
+	// Course ID
+	CourseID string `json:"course_id" validate:"required"`
+
+	// Lesson Order
+	Order int `json:"order" validate:"required"`
+
+	// Lesson Description (Can be left empty)
+	Description string `json:"description"`
+}
+
+// GetUUID Request Payload
+//	@Description	Information that should be available when you get using lesson id (uuid)
+type GetByUUIDRequestPayload struct {
+	// Lesson ID, provided by query
+	ID uuid.UUID `json:"-" validate:"required"`
+}
+
+// GetID Request Payload
+//	@Description	Information that should be available when you get using course id (string)
+type GetByStringRequestPayload struct {
+	// Course ID, provided by query
+	ID string `json:"-" validate:"required"`
+}
diff --git a/model/web/quiz/request.go b/model/web/quiz/request.go
new file mode 100644
index 0000000000000000000000000000000000000000..7aa66274179f131c3094b5630c7a0c448e9913fe
--- /dev/null
+++ b/model/web/quiz/request.go
@@ -0,0 +1,57 @@
+package quiz
+
+import (
+	"github.com/google/uuid"
+)
+
+// AddQuiz Request Payload
+//
+//	@Description	Information that should be available when you add a quiz
+type AddQuizRequestPayload struct {
+	// Web Token that was appended to the link
+	AddQuizToken string
+
+	// Quiz Name
+	Name string `json:"name" validate:"required"`
+
+	// Course ID
+	CourseID string `json:"course_id" validate:"required"`
+}
+
+// UpdateQuiz Request Payload
+//
+//	@Description	Information that should be available when you update a quiz
+type UpdateQuizRequestPayload struct {
+	// Web Token that was appended to the link
+	UpdateQuizToken string
+
+	// Quiz ID, Set by param
+	ID uuid.UUID `json:"id"`
+}
+
+// DeleteQuiz Request Payload
+//
+//	@Description	Information that should be available when you delete using uuid
+type DeleteRequestPayload struct {
+	// Web Token that was appended to the link
+	DeleteToken string
+
+	// Quiz ID, Set by param
+	ID uuid.UUID
+}
+
+// GetUUID Request Payload
+//
+//	@Description	Information that should be available when you get using uuid
+type GetRequestPayload struct {
+	// Quiz/Problem/Answer ID, provided by query
+	ID uuid.UUID
+}
+
+// Link Response Payload
+//
+//	@Description	Information that you will get upon successful request
+type LinkResponse struct {
+	UploadLink string `json:"upload_link"`
+}
+
diff --git a/repository/di.go b/repository/di.go
index b564bd5406f7d94427c5c0f80ccc518bc23fd5b2..9a418dca489cf4056d66d76510015e9f79f0b3cd 100644
--- a/repository/di.go
+++ b/repository/di.go
@@ -5,6 +5,7 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/repository/cache"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/content"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/course"
+	"gitlab.informatika.org/ocw/ocw-backend/repository/lesson"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/material"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/transaction"
@@ -24,6 +25,13 @@ var RepositoryBasicSet = wire.NewSet(
 	cache.New,
 	wire.Bind(new(cache.CacheRepository), new(*cache.CacheRepositoryImpl)),
 
+	// Lesson Repository
+	lesson.NewLesson,
+	lesson.NewLessonMaterials,
+	wire.Bind(new(lesson.LessonRepository), new(*lesson.LessonRepositoryImpl)),
+	wire.Bind(new(lesson.LessonMaterialsRepository), new(*lesson.LessonMaterialsRepositoryImpl)),
+
+	// Material Repository
 	material.NewMaterial,
 	material.NewMaterialContent,
 
diff --git a/repository/lesson/lesson.go b/repository/lesson/lesson.go
new file mode 100644
index 0000000000000000000000000000000000000000..e3e1002320c10381a8bad1386da2f3e78eb04c22
--- /dev/null
+++ b/repository/lesson/lesson.go
@@ -0,0 +1,52 @@
+package lesson
+
+import (
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/provider/db"
+	"gorm.io/gorm"
+)
+
+type LessonRepositoryImpl struct {
+	db *gorm.DB
+}
+
+func NewLesson(
+	db db.Database,
+) *LessonRepositoryImpl {
+	return &LessonRepositoryImpl{db.Connect()}
+}
+
+func (repo LessonRepositoryImpl) GetLesson(id uuid.UUID) (*lesson.Lesson, error) {
+	result := &lesson.Lesson{}
+	err := repo.db.First(result, "id = ?", id).Error
+
+	if err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+func (repo LessonRepositoryImpl) GetLessons(courseId string) ([]lesson.Lesson, error) {
+	var result []lesson.Lesson
+	err := repo.db.Where("course_id = ?", courseId).Find(&result).Error
+
+	if err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+func (repo LessonRepositoryImpl) AddLesson(lesson lesson.Lesson) error {
+	return repo.db.Create(lesson).Error
+}
+
+func (repo LessonRepositoryImpl) UpdateLesson(lesson lesson.Lesson) error {
+	return repo.db.Save(lesson).Error
+}
+
+func (repo LessonRepositoryImpl) DeleteLesson(id uuid.UUID) error {
+	return repo.db.Delete(&lesson.Lesson{}, id).Error
+}
diff --git a/repository/lesson/materials.go b/repository/lesson/materials.go
new file mode 100644
index 0000000000000000000000000000000000000000..d0e5ea70a634f4283a8c164089013f5249c55ff7
--- /dev/null
+++ b/repository/lesson/materials.go
@@ -0,0 +1,52 @@
+package lesson
+
+import (
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/provider/db"
+	"gorm.io/gorm"
+)
+
+type LessonMaterialsRepositoryImpl struct {
+	db *gorm.DB
+}
+
+func NewLessonMaterials(
+	db db.Database,
+) *LessonMaterialsRepositoryImpl {
+	return &LessonMaterialsRepositoryImpl{db.Connect()}
+}
+
+func (repo LessonMaterialsRepositoryImpl) GetLessonMaterial(id uuid.UUID) (*lesson.LessonMaterials, error) {
+	result := &lesson.LessonMaterials{}
+	err := repo.db.First(result, "id = ?", id).Error
+
+	if err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+func (repo LessonMaterialsRepositoryImpl) GetLessonMaterials(lessonId uuid.UUID) ([]lesson.LessonMaterials, error) {
+	var result []lesson.LessonMaterials
+	err := repo.db.Where("lesson_id = ?", lessonId).Find(&result).Error
+
+	if err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+func (repo LessonMaterialsRepositoryImpl) AddLessonMaterial(lessonMaterial lesson.LessonMaterials) error {
+	return repo.db.Create(lessonMaterial).Error
+}
+
+func (repo LessonMaterialsRepositoryImpl) UpdateLessonMaterial(lessonMaterial lesson.LessonMaterials) error {
+	return repo.db.Save(lessonMaterial).Error
+}
+
+func (repo LessonMaterialsRepositoryImpl) DeleteLessonMaterial(id uuid.UUID) error {
+	return repo.db.Delete(&lesson.LessonMaterials{}, id).Error
+}
diff --git a/repository/lesson/type.go b/repository/lesson/type.go
new file mode 100644
index 0000000000000000000000000000000000000000..4925c016cd2ed78e256a31fb5166a2c1c2ab828e
--- /dev/null
+++ b/repository/lesson/type.go
@@ -0,0 +1,22 @@
+package lesson
+
+import (
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/lesson"
+	"github.com/google/uuid"
+)
+
+type LessonRepository interface {
+	GetLesson(id uuid.UUID) (*lesson.Lesson, error)
+	GetLessons(courseId string) ([]lesson.Lesson, error)
+	AddLesson(lesson lesson.Lesson) error
+	UpdateLesson(lesson lesson.Lesson) error
+	DeleteLesson(id uuid.UUID) error
+}
+
+type LessonMaterialsRepository interface {
+	GetLessonMaterial(id uuid.UUID) (*lesson.LessonMaterials, error)
+	GetLessonMaterials(lessonId uuid.UUID) ([]lesson.LessonMaterials, error)
+	AddLessonMaterial(lessonMaterial lesson.LessonMaterials) error
+	UpdateLessonMaterial(lessonMaterial lesson.LessonMaterials) error
+	DeleteLessonMaterial(id uuid.UUID) error
+}
\ No newline at end of file
diff --git a/repository/quiz/impl.go b/repository/quiz/impl.go
index 3a6e013af162d89a545cbfb1897a166ecdef1dbe..2b7bc2eb550416215d3a1dc43a777ba47c4e204c 100644
--- a/repository/quiz/impl.go
+++ b/repository/quiz/impl.go
@@ -5,6 +5,7 @@ import (
 	"time"
 
 	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/course"
 	"gitlab.informatika.org/ocw/ocw-backend/model/domain/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
 	"gitlab.informatika.org/ocw/ocw-backend/provider/db"
@@ -65,6 +66,35 @@ func (q *QuizRepositoryImpl) NewTake(quizId uuid.UUID, userEmail string) (uuid.U
 	return id, err
 }
 
+func (q *QuizRepositoryImpl) IsUserContributor(id string, email string) (bool, error) {
+	err := q.db.Where("id = ? AND email = ?", id, email).Find(&course.Course{}).Error
+
+	if err != nil {
+		return false, err
+	}
+
+	return true, nil
+}
+
+func(q *QuizRepositoryImpl) NewQuiz(quiz quiz.Quiz) error {
+	return q.db.Create(&quiz).Error
+}
+
+func(q *QuizRepositoryImpl) GetQuizPath(quizId uuid.UUID) (string, error) {
+	result := quiz.Quiz{}
+	err := q.db.Where("id = ?", quizId).Find(&result).Error
+
+	if err != nil {
+		return "", err
+	}
+
+	return result.QuizPath, nil
+}
+
+func(q *QuizRepositoryImpl) Delete(quizId uuid.UUID) error {
+	return q.db.Delete(&quiz.Quiz{}, quizId).Error
+}
+
 func (q *QuizRepositoryImpl) IsActiveTake(quizId uuid.UUID, userEmail string) (bool, error) {
 	var result int64 = 0
 	err := q.db.
diff --git a/repository/quiz/type.go b/repository/quiz/type.go
index 1b4e0cbeca391ec136dfc8c696d1c058d49e55e4..c558fc0554b39c81c890d36150cd8d8ee80daf6a 100644
--- a/repository/quiz/type.go
+++ b/repository/quiz/type.go
@@ -10,6 +10,10 @@ type QuizRepository interface {
 	GetQuizDetail(quizId uuid.UUID) (*quiz.Quiz, error)
 	UpdateScore(takeId uuid.UUID, score int) error
 	NewTake(quizId uuid.UUID, userEmail string) (uuid.UUID, error)
+	IsUserContributor(id string, email string) (bool, error)
+	NewQuiz(quiz quiz.Quiz) error
+	GetQuizPath(quizId uuid.UUID) (string, error)
+	Delete(quizId uuid.UUID) error 
 	IsActiveTake(quizId uuid.UUID, userEmail string) (bool, error)
 	GetAllTake(quizId uuid.UUID, userEmail string) ([]quiz.QuizTake, error)
 	GetLastTake(quizId uuid.UUID, userEmail string) (*quiz.QuizTake, error)
diff --git a/routes/di.go b/routes/di.go
index ddae40f95c5cde473aadc4f6d26a357c98b5f089..d3129d33efdd8101223d47acb66efa1cd5bd5c73 100644
--- a/routes/di.go
+++ b/routes/di.go
@@ -6,6 +6,7 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/routes/auth"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/common"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/course"
+	"gitlab.informatika.org/ocw/ocw-backend/routes/lesson"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/material"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/reset"
@@ -19,6 +20,7 @@ var routesCollectionSet = wire.NewSet(
 	wire.Struct(new(admin.AdminRoutes), "*"),
 	wire.Struct(new(reset.ResetRoutes), "*"),
 	wire.Struct(new(course.CourseRoutes), "*"),
+	wire.Struct(new(lesson.LessonRoutes), "*"),
 	wire.Struct(new(material.MaterialRoutes), "*"),
 	wire.Struct(new(quiz.QuizRoutes), "*"),
 )
diff --git a/routes/lesson/route.go b/routes/lesson/route.go
new file mode 100644
index 0000000000000000000000000000000000000000..7d19720c746d2a88b4dcb5bb70079bed7bced2db
--- /dev/null
+++ b/routes/lesson/route.go
@@ -0,0 +1,28 @@
+package lesson
+
+import (
+	"github.com/go-chi/chi/v5"
+	"gitlab.informatika.org/ocw/ocw-backend/handler/lesson"
+)
+
+type LessonRoutes struct {
+	lesson.LessonHandler
+}
+
+func (l LessonRoutes) Register(r chi.Router) {
+	r.Route("/lesson", func(r chi.Router) {
+		r.Get("/{id}", l.LessonHandler.GetLesson)
+		r.Get("/course/{id}", l.LessonHandler.GetLessonsByCourse)
+		r.Get("/material/{id}", l.LessonHandler.GetLessonMaterial)
+		r.Get("/material/lesson/{id}", l.LessonHandler.GetLessonMaterialsByLesson)
+
+		r.Put("/", l.LessonHandler.AddLesson)
+		r.Put("/material", l.LessonHandler.AddLessonMaterial)
+
+		r.Post("/{id}", l.LessonHandler.UpdateLesson)
+		r.Post("/material/{id}", l.LessonHandler.UpdateLessonMaterial)
+
+		r.Delete("/{id}", l.LessonHandler.DeleteLesson)
+		r.Delete("/material/{id}", l.LessonHandler.DeleteLessonMaterial)
+	})
+}
diff --git a/routes/quiz/route.go b/routes/quiz/route.go
index b89269412c9add8ccc39a190a965f187a13c15b9..e706bb19fd348df8e3a0e8d62146eb457f09165a 100644
--- a/routes/quiz/route.go
+++ b/routes/quiz/route.go
@@ -14,7 +14,6 @@ type QuizRoutes struct {
 
 func (q QuizRoutes) Register(r chi.Router) {
 	r.Get("/course/{id}/quiz", q.QuizHandler.GetAllQuizes)
-	r.Get("/quiz/{id}", q.QuizHandler.GetQuizDetail)
 
 	guard := q.GuardBuilder.Build(
 		user.Student,
@@ -36,4 +35,18 @@ func (q QuizRoutes) Register(r chi.Router) {
 		r.Use(guard)
 		r.Get("/", q.QuizHandler.GetQuizSolution)
 	})
+
+	r.Route("/quiz/{id}", func(r chi.Router) {
+		r.Get("/", q.QuizHandler.GetQuizDetail)
+		r.Route("/", func(r chi.Router) {
+			r.Use(guard)
+			r.Put("/", q.QuizHandler.NewQuiz)
+			r.Delete("/", q.QuizHandler.DeleteQuiz)
+		})
+	})
+
+	r.Route("/quiz/link/{id}", func(r chi.Router) {
+		r.Use(guard)
+		r.Get("/", q.QuizHandler.GetQuizLink)
+	})
 }
diff --git a/routes/routes.go b/routes/routes.go
index 096f4d5005e2bfe01f82bfe53552edc99b1d0258..34e2036236b737b7b48fd6d1ad026925a4495681 100644
--- a/routes/routes.go
+++ b/routes/routes.go
@@ -5,6 +5,7 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/routes/auth"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/common"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/course"
+	"gitlab.informatika.org/ocw/ocw-backend/routes/lesson"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/material"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/routes/reset"
@@ -22,6 +23,7 @@ type AppRouter struct {
 	reset.ResetRoutes
 	quiz.QuizRoutes
 	course.CourseRoutes
+	lesson.LessonRoutes
 	material.MaterialRoutes
 
 	// Utility
diff --git a/service/di.go b/service/di.go
index 3a133f5fc0ccdaba5c7260c52fa6a068306cf8a2..88695f660eade6c4efbaedb4ec8e9265ee283848 100644
--- a/service/di.go
+++ b/service/di.go
@@ -6,6 +6,7 @@ import (
 	"gitlab.informatika.org/ocw/ocw-backend/service/auth"
 	"gitlab.informatika.org/ocw/ocw-backend/service/common"
 	"gitlab.informatika.org/ocw/ocw-backend/service/course"
+	"gitlab.informatika.org/ocw/ocw-backend/service/lesson"
 	"gitlab.informatika.org/ocw/ocw-backend/service/logger"
 	"gitlab.informatika.org/ocw/ocw-backend/service/logger/hooks"
 	"gitlab.informatika.org/ocw/ocw-backend/service/material"
@@ -71,6 +72,12 @@ var ServiceTestSet = wire.NewSet(
 		wire.Struct(new(quiz.QuizServiceImpl), "*"),
 		wire.Bind(new(quiz.QuizService), new(*quiz.QuizServiceImpl)),
 	),
+
+	// Lesson Service
+	wire.NewSet(
+		wire.Struct(new(lesson.LessonServiceImpl), "*"),
+		wire.Bind(new(lesson.LessonService), new(*lesson.LessonServiceImpl)),
+	),
 )
 
 var ServiceSet = wire.NewSet(
diff --git a/service/lesson/add.go b/service/lesson/add.go
new file mode 100644
index 0000000000000000000000000000000000000000..9258dcb250ce93be1249a0744ceff4268caebb94
--- /dev/null
+++ b/service/lesson/add.go
@@ -0,0 +1,68 @@
+package lesson
+
+import (
+	domLesson "gitlab.informatika.org/ocw/ocw-backend/model/domain/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+)
+
+func (l LessonServiceImpl) AddLesson(payload lesson.AddLessonRequestPayload) error {
+	// Validate Role
+	claim, err := l.TokenUtil.Validate(payload.AddLessonToken, token.Access)
+
+	// Invalid Token
+	if err != nil {
+		return web.NewResponseErrorFromError(err, web.TokenError)
+	}
+
+	// Unauthorized Role
+	if claim.Role == user.Student {
+		return web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+	}
+
+	err = l.LessonRepository.AddLesson(domLesson.Lesson{
+		Name:        payload.Name,
+		CourseID:    payload.CourseID,
+		Order:       payload.Order,
+		Description: payload.Description,
+	})
+
+	if err != nil {
+		// Some uncaught error
+		return err
+	}
+
+	return nil
+}
+
+func (l LessonServiceImpl) AddLessonMaterial(payload materials.AddLessonMaterialsRequestPayload) error {
+	// Validate Role
+	claim, err := l.TokenUtil.Validate(payload.AddLessonMaterialsToken, token.Access)
+
+	// Invalid Token
+	if err != nil {
+		return web.NewResponseErrorFromError(err, web.TokenError)
+	}
+
+	// Unauthorized Role
+	if claim.Role == user.Student {
+		return web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+	}
+
+	err = l.LessonMaterialsRepository.AddLessonMaterial(domLesson.LessonMaterials{
+		LessonID:   payload.LessonID,
+		Order:      payload.Order,
+		MaterialID: payload.MaterialID,
+		Contents:   payload.Contents,
+	})
+
+	if err != nil {
+		// Some uncaught error
+		return err
+	}
+
+	return nil
+}
diff --git a/service/lesson/delete.go b/service/lesson/delete.go
new file mode 100644
index 0000000000000000000000000000000000000000..187b6d07aa07bf103a83b1e21639e1843066247e
--- /dev/null
+++ b/service/lesson/delete.go
@@ -0,0 +1,57 @@
+package lesson
+
+import (
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+)
+
+func (l LessonServiceImpl) DeleteLesson(payload lesson.DeleteByUUIDRequestPayload) error {
+	// Validate Role
+	claim, err := l.TokenUtil.Validate(payload.DeleteLessonToken, token.Access)
+
+	// Invalid Token
+	if err != nil {
+		return web.NewResponseErrorFromError(err, web.TokenError)
+	}
+
+	// Unauthorized Role
+	if claim.Role == user.Student {
+		return web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+	}
+
+	err = l.LessonRepository.DeleteLesson(payload.ID)
+
+	if err != nil {
+		// Uncaught error
+		return err
+	}
+
+	return nil
+}
+
+func (l LessonServiceImpl) DeleteLessonMaterial(payload materials.DeleteByUUIDRequestPayload) error {
+	// Validate Role
+	claim, err := l.TokenUtil.Validate(payload.DeleteLessonMaterialsToken, token.Access)
+
+	// Invalid Token
+	if err != nil {
+		return web.NewResponseErrorFromError(err, web.TokenError)
+	}
+
+	// Unauthorized Role
+	if claim.Role == user.Student {
+		return web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+	}
+
+	err = l.LessonMaterialsRepository.DeleteLessonMaterial(payload.ID)
+
+	if err != nil {
+		// Uncaught error
+		return err
+	}
+
+	return nil
+}
\ No newline at end of file
diff --git a/service/lesson/get.go b/service/lesson/get.go
new file mode 100644
index 0000000000000000000000000000000000000000..3b3798b2057cb51ec65c7d5a2e297de7fa16d4d5
--- /dev/null
+++ b/service/lesson/get.go
@@ -0,0 +1,67 @@
+package lesson
+
+import (
+	"errors"
+
+	domLesson "gitlab.informatika.org/ocw/ocw-backend/model/domain/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+	"gorm.io/gorm"
+)
+
+func (l LessonServiceImpl) GetLesson(payload lesson.GetByUUIDRequestPayload) (*domLesson.Lesson, error) {
+	packet, err := l.LessonRepository.GetLesson(payload.ID)
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, web.NewResponseErrorFromError(err, web.LessonNotExist)
+		}
+		// Some Uncaught error
+		return nil, err
+	}
+	
+	return packet, nil
+}
+
+func (l LessonServiceImpl) GetLessons(payload lesson.GetByStringRequestPayload) ([]domLesson.Lesson, error) {
+	packet, err := l.LessonRepository.GetLessons(payload.ID)
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, web.NewResponseErrorFromError(err, web.LessonNotExist)
+		}
+		// Some Uncaught error
+		return nil, err
+	}
+	
+	return packet, nil
+}
+
+func (l LessonServiceImpl) GetLessonMaterial(payload materials.GetByUUIDRequestPayload) (*domLesson.LessonMaterials, error) {
+	packet, err := l.LessonMaterialsRepository.GetLessonMaterial(payload.ID)
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, web.NewResponseErrorFromError(err, web.LessonMaterialNotExist)
+		}
+		// Some Uncaught error
+		return nil, err
+	}
+	
+	return packet, nil
+}
+
+func (l LessonServiceImpl) GetLessonMaterials(payload materials.GetByUUIDRequestPayload) ([]domLesson.LessonMaterials, error) {
+	packet, err := l.LessonMaterialsRepository.GetLessonMaterials(payload.ID)
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return nil, web.NewResponseErrorFromError(err, web.LessonMaterialNotExist)
+		}
+		// Some Uncaught error
+		return nil, err
+	}
+	
+	return packet, nil
+}
\ No newline at end of file
diff --git a/service/lesson/impl.go b/service/lesson/impl.go
new file mode 100644
index 0000000000000000000000000000000000000000..835b27ac03d42afce5757b6d1efba11282f9986b
--- /dev/null
+++ b/service/lesson/impl.go
@@ -0,0 +1,16 @@
+package lesson
+
+import (
+	"gitlab.informatika.org/ocw/ocw-backend/repository/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/token"
+	"gitlab.informatika.org/ocw/ocw-backend/service/logger"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/env"
+)
+
+type LessonServiceImpl struct {
+	lesson.LessonRepository
+	lesson.LessonMaterialsRepository
+	*env.Environment
+	token.TokenUtil
+	logger.Logger
+}
\ No newline at end of file
diff --git a/service/lesson/type.go b/service/lesson/type.go
new file mode 100644
index 0000000000000000000000000000000000000000..3cdae1a02a5eb6cf2bf5961bb2a917114736dc57
--- /dev/null
+++ b/service/lesson/type.go
@@ -0,0 +1,20 @@
+package lesson
+
+import (
+	domLesson "gitlab.informatika.org/ocw/ocw-backend/model/domain/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+)
+
+type LessonService interface {
+	GetLesson(payload lesson.GetByUUIDRequestPayload) (*domLesson.Lesson, error)
+	GetLessons(payload lesson.GetByStringRequestPayload) ([]domLesson.Lesson, error)
+	AddLesson(payload lesson.AddLessonRequestPayload) error
+	UpdateLesson(payload lesson.UpdateLessonRequestPayload) error
+	DeleteLesson(payload lesson.DeleteByUUIDRequestPayload) error
+	GetLessonMaterial(payload materials.GetByUUIDRequestPayload) (*domLesson.LessonMaterials, error)
+	GetLessonMaterials(payload materials.GetByUUIDRequestPayload) ([]domLesson.LessonMaterials, error)
+	AddLessonMaterial(payload materials.AddLessonMaterialsRequestPayload) error
+	UpdateLessonMaterial(payload materials.UpdateLessonMaterialsRequestPayload) error
+	DeleteLessonMaterial(payload materials.DeleteByUUIDRequestPayload) error
+}
\ No newline at end of file
diff --git a/service/lesson/update.go b/service/lesson/update.go
new file mode 100644
index 0000000000000000000000000000000000000000..4d80a4e10675c9f42a18bd153ec03c4f3487ecd0
--- /dev/null
+++ b/service/lesson/update.go
@@ -0,0 +1,79 @@
+package lesson
+
+import (
+	"errors"
+
+	domLesson "gitlab.informatika.org/ocw/ocw-backend/model/domain/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/lesson/materials"
+	"gorm.io/gorm"
+)
+
+func (l LessonServiceImpl) UpdateLesson(payload lesson.UpdateLessonRequestPayload) error {
+	// Validate Role
+	claim, err := l.TokenUtil.Validate(payload.UpdateLessonToken, token.Access)
+
+	// Invalid Token
+	if err != nil {
+		return web.NewResponseErrorFromError(err, web.TokenError)
+	}
+
+	// Unauthorized Role
+	if claim.Role == user.Student {
+		return web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+	}
+
+	err = l.LessonRepository.UpdateLesson(domLesson.Lesson{
+		ID:          payload.ID,
+		Name:        payload.Name,
+		CourseID:    payload.CourseID,
+		Order:       payload.Order,
+		Description: payload.Description,
+	})
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return web.NewResponseErrorFromError(err, web.LessonNotExist)
+		}
+		// Uncaught error
+		return err
+	}
+
+	return nil
+}
+
+func (l LessonServiceImpl) UpdateLessonMaterial(payload materials.UpdateLessonMaterialsRequestPayload) error {
+	// Validate Role
+	claim, err := l.TokenUtil.Validate(payload.UpdateLessonMaterialsToken, token.Access)
+
+	// Invalid Token
+	if err != nil {
+		return web.NewResponseErrorFromError(err, web.TokenError)
+	}
+
+	// Unauthorized Role
+	if claim.Role == user.Student {
+		return web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+	}
+
+	err = l.LessonMaterialsRepository.UpdateLessonMaterial(domLesson.LessonMaterials{
+		ID:         payload.ID,
+		LessonID:   payload.LessonID,
+		Order:      payload.Order,
+		MaterialID: payload.MaterialID,
+		Contents:   payload.Contents,
+	})
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return web.NewResponseErrorFromError(err, web.LessonMaterialNotExist)
+		}
+		// Uncaught error
+		return err
+	}
+
+	return nil
+}
diff --git a/service/quiz/impl.go b/service/quiz/impl.go
index 1980c82519ccb4b7971dc573ae35b7067791a13f..69c375425f121d4dfb2c740732cb89f7cce8b075 100644
--- a/service/quiz/impl.go
+++ b/service/quiz/impl.go
@@ -4,21 +4,35 @@ import (
 	"bytes"
 	"context"
 	"encoding/json"
+	"errors"
+	"fmt"
+	"strings"
 
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/domain/quiz"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
 	userDomain "gitlab.informatika.org/ocw/ocw-backend/model/domain/user"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+	atoken "gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+	model "gitlab.informatika.org/ocw/ocw-backend/model/web/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/provider/storage"
 	quizRepo "gitlab.informatika.org/ocw/ocw-backend/repository/quiz"
+	"gitlab.informatika.org/ocw/ocw-backend/service/logger"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/env"
+	tokenUtil "gitlab.informatika.org/ocw/ocw-backend/utils/token"
+	"gorm.io/gorm"
 )
 
 type QuizServiceImpl struct {
 	quizRepo.QuizRepository
 	storage.Storage
+	tokenUtil.TokenUtil
+	logger.Logger
+	*env.Environment
 }
 
+// TODO: should be for admins, make ones for users which doesnt expose minio link
 func (q QuizServiceImpl) ListAllQuiz(courseId string) ([]quiz.Quiz, error) {
 	return q.QuizRepository.GetQuizes(courseId)
 }
@@ -176,3 +190,114 @@ func (q QuizServiceImpl) DoFinishQuiz(ctx context.Context, quizId uuid.UUID, ema
 
 	return data, nil
 }
+
+func (q QuizServiceImpl) isQuizContributor(courseId string, email string) error {
+	_, err := q.QuizRepository.IsUserContributor(courseId, email)
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return web.NewResponseError("course and user combination not found", "NOT_OWNER")
+		}
+
+		return err
+	}
+
+	return nil
+}
+
+func (q QuizServiceImpl) NewQuiz(payload model.AddQuizRequestPayload) (*model.LinkResponse, error) {
+	// Validate Role
+	claim, err := q.TokenUtil.Validate(payload.AddQuizToken, atoken.Access)
+
+	// Invalid Token
+	if err != nil {
+		return &model.LinkResponse{}, web.NewResponseErrorFromError(err, web.TokenError)
+	}
+
+	// Unauthorized Role
+	if claim.Role == user.Student {
+		return &model.LinkResponse{}, web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+	}
+
+	// Validate Ownership
+	if err := q.isQuizContributor(payload.CourseID, claim.Email); err != nil {
+		return &model.LinkResponse{}, err
+	}
+
+	path := fmt.Sprintf("%s/%s.json", q.BucketQuizBasePath, strings.ReplaceAll(uuid.New().String(), "-", ""))
+	uploadLink, err := q.Storage.CreatePutSignedLink(context.Background(), path)
+
+	if err != nil {
+		q.Logger.Error("Some error happened when generate link")
+		q.Logger.Error(err.Error())
+		return &model.LinkResponse{}, err
+	}
+
+	return &model.LinkResponse{UploadLink: uploadLink}, nil
+}
+
+func (q QuizServiceImpl) GetQuiz(payload model.UpdateQuizRequestPayload) (*model.LinkResponse, error) {
+	// Validate Role
+	claim, err := q.TokenUtil.Validate(payload.UpdateQuizToken, atoken.Access)
+
+	// Invalid Token
+	if err != nil {
+		return &model.LinkResponse{}, web.NewResponseErrorFromError(err, web.TokenError)
+	}
+
+	// Unauthorized Role
+	if claim.Role == user.Student {
+		return &model.LinkResponse{}, web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+	}
+
+	// Get Quiz Detail
+	quiz, err := q.QuizRepository.GetQuizDetail(payload.ID)
+
+	if err != nil {
+		return &model.LinkResponse{}, err
+	}
+
+	// Validate Ownership
+	if err := q.isQuizContributor(quiz.CourseId, claim.Email); err != nil {
+		return &model.LinkResponse{}, err
+	}
+
+	uploadLink, err := q.QuizRepository.GetQuizPath(payload.ID)
+
+	if err != nil {
+		q.Logger.Error("Some error happened when retrieving link")
+		q.Logger.Error(err.Error())
+		return &model.LinkResponse{}, err
+	}
+
+	return &model.LinkResponse{UploadLink: uploadLink}, nil
+}
+
+func (q QuizServiceImpl) DeleteQuiz(payload model.DeleteRequestPayload) error {
+	// Validate Role
+	claim, err := q.TokenUtil.Validate(payload.DeleteToken, atoken.Access)
+
+	// Invalid Token
+	if err != nil {
+		return web.NewResponseErrorFromError(err, web.TokenError)
+	}
+
+	// Unauthorized Role
+	if claim.Role == user.Student {
+		return web.NewResponseErrorFromError(err, web.UnauthorizedAccess)
+	}
+
+	// Get Quiz Detail
+	quiz, err := q.QuizRepository.GetQuizDetail(payload.ID)
+
+	if err != nil {
+		return err
+	}
+
+	// Validate Ownership
+	if err := q.isQuizContributor(quiz.CourseId, claim.Email); err != nil {
+		return err
+	}
+
+	return q.QuizRepository.Delete(payload.ID)
+}
diff --git a/service/quiz/type.go b/service/quiz/type.go
index 04b299c4c609c291cc84ef23b664ce1fdd2503d5..3f7d2a7f775b68713e3317d2d074aef624bc6129 100644
--- a/service/quiz/type.go
+++ b/service/quiz/type.go
@@ -6,6 +6,7 @@ import (
 	"github.com/google/uuid"
 	"gitlab.informatika.org/ocw/ocw-backend/model/domain/quiz"
 	"gitlab.informatika.org/ocw/ocw-backend/model/web/auth/token"
+	model "gitlab.informatika.org/ocw/ocw-backend/model/web/quiz"
 )
 
 type QuizService interface {
@@ -15,4 +16,8 @@ type QuizService interface {
 	DoTakeQuiz(ctx context.Context, quizId uuid.UUID, email string) (*quiz.QuizDetail, error)
 	DoFinishQuiz(ctx context.Context, quizId uuid.UUID, email string, studentAnswer []quiz.Response) (*quiz.QuizTake, error)
 	GetSolutionQuiz(ctx context.Context, quizId uuid.UUID, user token.UserClaim) (*quiz.QuizDetail, error)
+	isQuizContributor(courseId string, email string) error
+	NewQuiz(payload model.AddQuizRequestPayload) (*model.LinkResponse, error)
+	GetQuiz(payload model.UpdateQuizRequestPayload) (*model.LinkResponse, error)
+	DeleteQuiz(payload model.DeleteRequestPayload) error
 }
diff --git a/utils/env/env.go b/utils/env/env.go
index 85aa99986a2c0a45cb68f07927cbe954137a16e3..50c73820d065affd17ec2d93bf420f994281bdcd 100644
--- a/utils/env/env.go
+++ b/utils/env/env.go
@@ -65,6 +65,7 @@ type Environment struct {
 	BucketSignedGetDuration int64 `env:"BUCKET_SIGNED_GET_DURATION_S" envDefault:"1800"`
 
 	BucketMaterialBasePath string `env:"BUCKET_MATERIAL_BASE_PATH" envDefault:"materials"`
+	BucketQuizBasePath string `env:"BUCKET_MATERIAL_BASE_PATH" envDefault:"quiz"`
 
 	UseBucket bool `env:"USE_BUCKET" envDefault:"true"`
 }