diff --git a/backend/app/crud.py b/backend/app/crud.py
index 4f0f61f0eaca99d8b2c6b6f97173114144422cd3..088d63418c9280369285eb3063dc720c45cd883d 100644
--- a/backend/app/crud.py
+++ b/backend/app/crud.py
@@ -187,9 +187,131 @@ def create_test_typing_entry(
     return db_entry
 
 
-def create_test_vocabulary(db: Session, test: schemas.TestVocabularyCreate):
-    db_test = models.TestVocabulary(**test.dict())
-    db.add(db_test)
+def create_survey(db: Session, survey: schemas.SurveyCreate):
+    db_survey = models.Survey(**survey.dict())
+    db.add(db_survey)
+    db.commit()
+    db.refresh(db_survey)
+    return db_survey
+
+
+def get_survey(db: Session, survey_id: int):
+    return db.query(models.Survey).filter(models.Survey.id == survey_id).first()
+
+
+def get_surveys(db: Session, skip: int = 0, limit: int = 100):
+    return db.query(models.Survey).offset(skip).limit(limit).all()
+
+
+def delete_survey(db: Session, survey_id: int):
+    db.query(models.Survey).filter(models.Survey.id == survey_id).delete()
+    db.commit()
+
+
+def create_survey_group(
+    db: Session, survey_id: int, survey_group: schemas.SurveyGroupCreate
+):
+    db_survey_group = models.SurveyGroup(survey_id=survey_id, **survey_group.dict())
+    db.add(db_survey_group)
+    db.commit()
+    db.refresh(db_survey_group)
+    return db_survey_group
+
+
+def get_survey_group(db: Session, survey_group_id: int):
+    return (
+        db.query(models.SurveyGroup)
+        .filter(models.SurveyGroup.id == survey_group_id)
+        .first()
+    )
+
+
+def get_survey_groups(db: Session, survey_id: int, skip: int = 0, limit: int = 100):
+    return (
+        db.query(models.SurveyGroup)
+        .filter(models.SurveyGroup.survey_id == survey_id)
+        .offset(skip)
+        .limit(limit)
+        .all()
+    )
+
+
+def delete_survey_group(db: Session, survey_group_id: int):
+    db.query(models.SurveyGroup).filter(
+        models.SurveyGroup.id == survey_group_id
+    ).delete()
+    db.commit()
+
+
+def create_survey_question(
+    db: Session, survey_group_id: int, survey_question: schemas.SurveyQuestionCreate
+):
+    db_survey_question = models.SurveyQuestion(
+        group_id=survey_group_id, **survey_question.dict()
+    )
+    db.add(db_survey_question)
+    db.commit()
+    db.refresh(db_survey_question)
+    return db_survey_question
+
+
+def get_survey_question(db: Session, survey_question_id: int):
+    return (
+        db.query(models.SurveyQuestion)
+        .filter(models.SurveyQuestion.id == survey_question_id)
+        .first()
+    )
+
+
+def get_survey_questions(db: Session, group_id: int, skip: int = 0, limit: int = 100):
+    return (
+        db.query(models.SurveyQuestion)
+        .filter(models.SurveyQuestion.group_id == group_id)
+        .offset(skip)
+        .limit(limit)
+        .all()
+    )
+
+
+def delete_survey_question(db: Session, survey_question_id: int):
+    db.query(models.SurveyQuestion).filter(
+        models.SurveyQuestion.id == survey_question_id
+    ).delete()
+    db.commit()
+
+
+def create_survey_option(
+    db: Session, survey_question_id: int, survey_option: schemas.SurveyOptionCreate
+):
+    db_survey_option = models.SurveyOption(
+        question_id=survey_question_id, **survey_option.dict()
+    )
+    db.add(db_survey_option)
+    db.commit()
+    db.refresh(db_survey_option)
+    return db_survey_option
+
+
+def get_survey_option(db: Session, survey_option_id: int):
+    return (
+        db.query(models.SurveyOption)
+        .filter(models.SurveyOption.id == survey_option_id)
+        .first()
+    )
+
+
+def get_survey_options(db: Session, question_id: int, skip: int = 0, limit: int = 100):
+    return (
+        db.query(models.SurveyOption)
+        .filter(models.SurveyOption.question_id == question_id)
+        .offset(skip)
+        .limit(limit)
+        .all()
+    )
+
+
+def delete_survey_option(db: Session, survey_option_id: int):
+    db.query(models.SurveyOption).filter(
+        models.SurveyOption.id == survey_option_id
+    ).delete()
     db.commit()
-    db.refresh(db_test)
-    return db_test
diff --git a/backend/app/main.py b/backend/app/main.py
index 3436696f7ad7cc20eb7a6c810f59b26eb398eb09..645564d5050daf2d8fab0b9d9f11054a4e8ef697 100644
--- a/backend/app/main.py
+++ b/backend/app/main.py
@@ -68,7 +68,7 @@ usersRouter = APIRouter(prefix="/users", tags=["users"])
 sessionsRouter = APIRouter(prefix="/sessions", tags=["sessions"])
 websocketRouter = APIRouter(prefix="/ws", tags=["websocket"])
 webhookRouter = APIRouter(prefix="/webhooks", tags=["webhook"])
-stats = APIRouter(prefix="/stats", tags=["stats"])
+surveyRouter = APIRouter(prefix="/surveys", tags=["surveys"])
 
 
 @v1Router.get("/health", status_code=status.HTTP_204_NO_CONTENT)
@@ -604,13 +604,6 @@ def propagate_presence(
     return
 
 
-@v1Router.post("/tests/vocabulary", status_code=status.HTTP_201_CREATED)
-def create_test_vocabulary(
-    content: schemas.TestVocabularyCreate, db: Session = Depends(get_db)
-):
-    return crud.create_test_vocabulary(db, content).id
-
-
 @websocketRouter.websocket("/sessions/{session_id}")
 async def websocket_session(
     session_id: int,
@@ -691,10 +684,308 @@ async def webhook_session(
     raise HTTPException(status_code=400, detail="Invalid trigger event")
 
 
+@surveyRouter.post("", status_code=status.HTTP_201_CREATED)
+def create_survey(
+    survey: schemas.SurveyCreate,
+    db: Session = Depends(get_db),
+    current_user: schemas.User = Depends(get_jwt_user),
+):
+    if not check_user_level(current_user, models.UserType.ADMIN):
+        raise HTTPException(
+            status_code=401, detail="You do not have permission to create a survey"
+        )
+
+    return crud.create_survey(db, survey).id
+
+
+@surveyRouter.get("", response_model=list[schemas.Survey])
+def get_surveys(
+    db: Session = Depends(get_db),
+):
+    return crud.get_surveys(db)
+
+
+@surveyRouter.get("/{survey_id}", response_model=schemas.Survey)
+def get_survey(
+    survey_id: int,
+    db: Session = Depends(get_db),
+):
+    survey = crud.get_survey(db, survey_id)
+    if survey is None:
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    return survey
+
+
+@surveyRouter.delete("/{survey_id}", status_code=status.HTTP_204_NO_CONTENT)
+def delete_survey(
+    survey_id: int,
+    db: Session = Depends(get_db),
+    current_user: schemas.User = Depends(get_jwt_user),
+):
+    if not check_user_level(current_user, models.UserType.ADMIN):
+        raise HTTPException(
+            status_code=401, detail="You do not have permission to delete a survey"
+        )
+
+    crud.delete_survey(db, survey_id)
+
+
+@surveyRouter.post("/{survey_id}/groups", status_code=status.HTTP_201_CREATED)
+def create_survey_group(
+    survey_id: int,
+    group: schemas.SurveyGroupCreate,
+    db: Session = Depends(get_db),
+    current_user: schemas.User = Depends(get_jwt_user),
+):
+    if not check_user_level(current_user, models.UserType.ADMIN):
+        raise HTTPException(
+            status_code=401,
+            detail="You do not have permission to create a survey group",
+        )
+
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    return crud.create_survey_group(db, survey_id, group).id
+
+
+@surveyRouter.get("/{survey_id}/groups", response_model=list[schemas.SurveyGroup])
+def get_survey_groups(
+    survey_id: int,
+    db: Session = Depends(get_db),
+):
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    return crud.get_survey_groups(db, survey_id)
+
+
+@surveyRouter.get("/{survey_id}/groups/{group_id}", response_model=schemas.SurveyGroup)
+def get_survey_group(
+    survey_id: int,
+    group_id: int,
+    db: Session = Depends(get_db),
+):
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    group = crud.get_survey_group(db, group_id)
+    if group is None:
+        raise HTTPException(status_code=404, detail="Survey group not found")
+
+    return group
+
+
+@surveyRouter.delete(
+    "/{survey_id}/groups/{group_id}", status_code=status.HTTP_204_NO_CONTENT
+)
+def delete_survey_group(
+    survey_id: int,
+    group_id: int,
+    db: Session = Depends(get_db),
+    current_user: schemas.User = Depends(get_jwt_user),
+):
+    if not check_user_level(current_user, models.UserType.ADMIN):
+        raise HTTPException(
+            status_code=401,
+            detail="You do not have permission to delete a survey group",
+        )
+
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    if not crud.get_survey_group(db, group_id):
+        raise HTTPException(status_code=404, detail="Survey group not found")
+
+    crud.delete_survey_group(db, group_id)
+
+
+@surveyRouter.post(
+    "/{survey_id}/groups/{group_id}/questions", status_code=status.HTTP_201_CREATED
+)
+def create_survey_question(
+    survey_id: int,
+    group_id: int,
+    question: schemas.SurveyQuestionCreate,
+    db: Session = Depends(get_db),
+    current_user: schemas.User = Depends(get_jwt_user),
+):
+    if not check_user_level(current_user, models.UserType.ADMIN):
+        raise HTTPException(
+            status_code=401,
+            detail="You do not have permission to create a survey question",
+        )
+
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    if not crud.get_survey_group(db, group_id):
+        raise HTTPException(status_code=404, detail="Survey group not found")
+
+    return crud.create_survey_question(db, group_id, question).id
+
+
+@surveyRouter.get(
+    "/{survey_id}/groups/{group_id}/questions",
+    response_model=list[schemas.SurveyQuestion],
+)
+def get_survey_questions(
+    survey_id: int,
+    group_id: int,
+    db: Session = Depends(get_db),
+):
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    if not crud.get_survey_group(db, group_id):
+        raise HTTPException(status_code=404, detail="Survey group not found")
+
+    return crud.get_survey_questions(db, group_id)
+
+
+@surveyRouter.get(
+    "/{survey_id}/groups/{group_id}/questions/{question_id}",
+    response_model=schemas.SurveyQuestion,
+)
+def get_survey_question(
+    survey_id: int,
+    group_id: int,
+    question_id: int,
+    db: Session = Depends(get_db),
+):
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    if not crud.get_survey_group(db, group_id):
+        raise HTTPException(status_code=404, detail="Survey group not found")
+
+    question = crud.get_survey_question(db, question_id)
+    if question is None:
+        raise HTTPException(status_code=404, detail="Survey question not found")
+
+    return question
+
+
+@surveyRouter.delete(
+    "/{survey_id}/groups/{group_id}/questions/{question_id}",
+    status_code=status.HTTP_204_NO_CONTENT,
+)
+def delete_survey_question(
+    survey_id: int,
+    group_id: int,
+    question_id: int,
+    db: Session = Depends(get_db),
+    current_user: schemas.User = Depends(get_jwt_user),
+):
+    if not check_user_level(current_user, models.UserType.ADMIN):
+        raise HTTPException(
+            status_code=401,
+            detail="You do not have permission to delete a survey question",
+        )
+
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    if not crud.get_survey_group(db, group_id):
+        raise HTTPException(status_code=404, detail="Survey group not found")
+
+    if not crud.get_survey_question(db, question_id):
+        raise HTTPException(status_code=404, detail="Survey question not found")
+
+    crud.delete_survey_question(db, question_id)
+
+
+@surveyRouter.post(
+    "/{survey_id}/groups/{group_id}/questions/{question_id}/options",
+    status_code=status.HTTP_201_CREATED,
+)
+def create_survey_option(
+    survey_id: int,
+    group_id: int,
+    question_id: int,
+    option: schemas.SurveyOptionCreate,
+    db: Session = Depends(get_db),
+    current_user: schemas.User = Depends(get_jwt_user),
+):
+    if not check_user_level(current_user, models.UserType.ADMIN):
+        raise HTTPException(
+            status_code=401,
+            detail="You do not have permission to create a survey option",
+        )
+
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    if not crud.get_survey_group(db, group_id):
+        raise HTTPException(status_code=404, detail="Survey group not found")
+
+    if not crud.get_survey_question(db, question_id):
+        raise HTTPException(status_code=404, detail="Survey question not found")
+
+    return crud.create_survey_option(db, question_id, option).id
+
+
+@surveyRouter.get(
+    "/{survey_id}/groups/{group_id}/questions/{question_id}/options",
+    response_model=list[schemas.SurveyOption],
+)
+def get_survey_options(
+    survey_id: int,
+    group_id: int,
+    question_id: int,
+    db: Session = Depends(get_db),
+):
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    if not crud.get_survey_group(db, group_id):
+        raise HTTPException(status_code=404, detail="Survey group not found")
+
+    if not crud.get_survey_question(db, question_id):
+        raise HTTPException(status_code=404, detail="Survey question not found")
+
+    return crud.get_survey_options(db, question_id)
+
+
+@surveyRouter.delete(
+    "/{survey_id}/groups/{group_id}/questions/{question_id}/options/{option_id}",
+    status_code=status.HTTP_204_NO_CONTENT,
+)
+def delete_survey_option(
+    survey_id: int,
+    group_id: int,
+    question_id: int,
+    option_id: int,
+    db: Session = Depends(get_db),
+    current_user: schemas.User = Depends(get_jwt_user),
+):
+    if not check_user_level(current_user, models.UserType.ADMIN):
+        raise HTTPException(
+            status_code=401,
+            detail="You do not have permission to delete a survey option",
+        )
+
+    if not crud.get_survey(db, survey_id):
+        raise HTTPException(status_code=404, detail="Survey not found")
+
+    if not crud.get_survey_group(db, group_id):
+        raise HTTPException(status_code=404, detail="Survey group not found")
+
+    if not crud.get_survey_question(db, question_id):
+        raise HTTPException(status_code=404, detail="Survey question not found")
+
+    if not crud.get_survey_option(db, option_id):
+        raise HTTPException(status_code=404, detail="Survey option not found")
+
+    crud.delete_survey_option(db, option_id)
+
+
 v1Router.include_router(authRouter)
 v1Router.include_router(usersRouter)
 v1Router.include_router(sessionsRouter)
 v1Router.include_router(websocketRouter)
 v1Router.include_router(webhookRouter)
+v1Router.include_router(surveyRouter)
 apiRouter.include_router(v1Router)
 app.include_router(apiRouter)
diff --git a/backend/app/models.py b/backend/app/models.py
index 56f44030d81ce5c7484576ddd5bd4a3b95ed1e5b..e337c2f91770a7cdf2a592a8ca85bd4b1c213574 100644
--- a/backend/app/models.py
+++ b/backend/app/models.py
@@ -131,8 +131,39 @@ class TestTypingEntry(Base):
     keyValue = Column(String)
 
 
-class TestVocabulary(Base):
-    __tablename__ = "test_vocabulary"
+class SurveyOption(Base):
+    __tablename__ = "survey_options"
 
     id = Column(Integer, primary_key=True, index=True)
-    content = Column(String)
+    question_id = Column(Integer, ForeignKey("survey_questions.id"))
+    correct = Column(Boolean)
+    type = Column(String)
+    value = Column(String)
+
+
+class SurveyQuestion(Base):
+    __tablename__ = "survey_questions"
+
+    id = Column(Integer, primary_key=True, index=True)
+    group_id = Column(Integer, ForeignKey("survey_groups.id"))
+    title = Column(String)
+    question_type = Column(String)
+    question_value = Column(String)
+    options = relationship("SurveyOption", backref="question")
+
+
+class SurveyGroup(Base):
+    __tablename__ = "survey_groups"
+
+    id = Column(Integer, primary_key=True, index=True)
+    survey_id = Column(Integer, ForeignKey("surveys.id"))
+    title = Column(String)
+    questions = relationship("SurveyQuestion", backref="group")
+
+
+class Survey(Base):
+    __tablename__ = "surveys"
+
+    id = Column(Integer, primary_key=True, index=True)
+    title = Column(String)
+    groups = relationship("SurveyGroup", backref="survey")
diff --git a/backend/app/schemas.py b/backend/app/schemas.py
index c41e7692fa1cb022c4e5aa3fa8d51ea8fa4d40a1..d0398d68ac2ce546f67340777bfc3996798b4b46 100644
--- a/backend/app/schemas.py
+++ b/backend/app/schemas.py
@@ -140,3 +140,52 @@ class CalComWebhook(BaseModel):
     triggerEvent: str
     createdAt: datetime.datetime
     payload: dict
+
+
+class SurveyOption(BaseModel):
+    id: int
+    question_id: int
+    correct: bool
+    type: str
+    value: str
+
+
+class SurveyOptionCreate(BaseModel):
+    correct: bool
+    type: str
+    value: str
+
+
+class SurveyQuestionCreate(BaseModel):
+    title: str
+    question_type: str
+    question_value: str
+
+
+class SurveyQuestion(BaseModel):
+    id: int
+    group_id: int
+    title: str
+    question_type: str
+    question_value: str
+    options: list[SurveyOption]
+
+
+class SurveyGroupCreate(BaseModel):
+    title: str
+
+
+class SurveyGroup(BaseModel):
+    id: int
+    survey_id: int
+    title: str
+    questions: list[SurveyQuestion]
+
+
+class SurveyCreate(BaseModel):
+    title: str
+
+
+class Survey(BaseModel):
+    id: int
+    groups: list[SurveyGroup]