diff --git a/.env.example b/.env.example
index 6589e22..51bad83 100644
--- a/.env.example
+++ b/.env.example
@@ -4,12 +4,16 @@ DATABASE_URL="sqlite:///./db.sqlite"
 # AUTH SETTINGS / PASSWORT RESET
 # Important: No Backslash at the end!
 PASSWORD_RESET_LINK="127.0.0.1"
+
+ACTIVATE_ACCOUNT_LINK="127.0.0.1"
 #In Sec = 20min 
 JWT_VALID_TIME_ACCESS=1200 
 #In Sec = one week
 JWT_VALID_TIME_REFRESH=604800 
 #In Sec = 10min
 JWT_VALID_TIME_PWD_RESET=600 
+#In Sec = 10h
+JWT_VALID_TIME_ACTIVATE_ACCOUNT=36000
 JWT_SECRET="secret"
 JWT_ALGORITHM="HS256"
 MAIL_USERNAME="kosjenka.readingapp@gmail.com"
diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml
index 14c54a2..d05250d 100644
--- a/.github/workflows/dev.yml
+++ b/.github/workflows/dev.yml
@@ -41,6 +41,7 @@ jobs:
           echo "JWT_VALID_TIME_ACCESS=1200" >> .env
           echo "JWT_VALID_TIME_REFRESH=604800" >> .env
           echo "JWT_VALID_TIME_PWD_RESET=600" >> .env
+          echo "JWT_VALID_TIME_ACTIVATE_ACCOUNT=36000" >> .env
           echo "JWT_ALGORITHM=HS256" >> .env
           echo "MAIL_USERNAME=kosjenka.readingapp@gmail.com" >> .env
           echo "MAIL_PORT=587" >> .env
@@ -49,6 +50,7 @@ jobs:
           echo "SUPERADMIN_LOGIN=superadmin@gmail.com" >> .env
           echo "SUPERADMIN_PASSWORD={{ secrets.DEV_SUPERADMIN_PASSWORD }}" >> .env
           echo "PASSWORD_RESET_LINK=https://admin-kosjenka-dev.vercel.app/password/confirm" >> .env
+          echo "ACTIVATE_ACCOUNT_LINK=https://admin-kosjenka-dev.vercel.app/admins/confirm" >> .env
 
       - name: Build and push Docker image
         uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml
index 0c97c37..cdb909d 100644
--- a/.github/workflows/pipeline.yml
+++ b/.github/workflows/pipeline.yml
@@ -8,9 +8,11 @@ on:
 env:
   DATABASE_URL: "sqlite:///./db.sqlite"
   PASSWORD_RESET_LINK: "127.0.0.1" 
+  ACTIVATE_ACCOUNT_LINK: "127.0.0.1:8000"
   JWT_VALID_TIME_ACCESS: 1200 
   JWT_VALID_TIME_REFRESH: 604800
   JWT_VALID_TIME_PWD_RESET: 600 
+  JWT_VALID_TIME_ACTIVATE_ACCOUNT: 36000
   JWT_SECRET: "secret"
   JWT_ALGORITHM: "HS256"
   MAIL_USERNAME: "kosjenka.readingapp@gmail.com"
diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml
index 462edf7..ad652c5 100644
--- a/.github/workflows/prod.yml
+++ b/.github/workflows/prod.yml
@@ -13,6 +13,7 @@ env:
   JWT_VALID_TIME_ACCESS: 1200 
   JWT_VALID_TIME_REFRESH: 604800
   JWT_VALID_TIME_PWD_RESET: 600 
+  JWT_VALID_TIME_ACTIVATE_ACCOUNT: 36000
   JWT_ALGORITHM: "HS256"
   MAIL_USERNAME: "kosjenka.readingapp@gmail.com"
   MAIL_PORT: 587
@@ -57,8 +58,10 @@ jobs:
           echo "MAIL_PORT=587" >> .env
           echo "MAIL_SERVER=smtp.gmail.com" >> .env
           echo "MAIL_FROM_NAME=Kosjenka Support" >> .env
+          echo "SUPERADMIN_LOGIN=superadmin@gmail.com" >> .env
           echo "SUPERADMIN_PASSWORD=${{ secrets.PROD_SUPERADMIN_PASSWORD }}" >> .env
           echo "PASSWORD_RESET_LINK=https://admin-kosjenka.vercel.app/password/confirm" >> .env
+          echo "ACTIVATE_ACCOUNT_LINK=echo "PASSWORD_RESET_LINK=https://admin-kosjenka.vercel.app/admins/confirm" >> .env
 
       - name: Build and push Docker image
         uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
diff --git a/auth.py b/auth.py
index dfcddc3..88d9d0e 100644
--- a/auth.py
+++ b/auth.py
@@ -18,6 +18,7 @@
 JWT_VALID_TIME_PWD_RESET = int(
     os.environ["JWT_VALID_TIME_PWD_RESET"]
 )  # 60 * 10  # 10min
+JWT_VALID_TIME_ACTIVATE_ACCOUNT = int(os.environ["JWT_VALID_TIME_ACTIVATE_ACCOUNT"])
 JWT_SECRET = os.environ["JWT_SECRET"]  # "C0ddVvlcaL4UuChF8ckFQoVCGbtizyvK"
 JWT_ALGORITHM = os.environ["JWT_ALGORITHM"]  # "HS256"
 
@@ -154,3 +155,48 @@ def reset_password(db: Session, new_password: str, token: str):
         return "SUCCESS"
     except:
         return "ERROR"
+
+
+# Admin Password set
+def create_account_activation_token(
+    email: EmailStr, is_superadmin: bool, valid_time: int
+):
+    payload = {
+        "email": email,
+        "is_superadmin": is_superadmin,
+        "expires": time.time() + valid_time,
+    }
+    token = jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)
+    return token
+
+
+async def send_account_password_mail(account: schemas.AccountPostAdminIn):
+    token = create_account_activation_token(
+        email=account.email,
+        is_superadmin=account.is_superadmin,
+        valid_time=JWT_VALID_TIME_ACTIVATE_ACCOUNT,
+    )
+    link_base = os.environ["ACTIVATE_ACCOUNT_LINK"]
+    template_body = {
+        "user": account.email,
+        "url": f"{link_base}?token={token}",
+        "expire_in_hours": int(JWT_VALID_TIME_ACTIVATE_ACCOUNT / 60 / 60),
+    }
+    message = MessageSchema(
+        subject="Kosjenka - Account Registration",
+        recipients=[account.email],
+        template_body=template_body,
+        subtype=MessageType.html,
+    )
+    fm = FastMail(conf)
+    await fm.send_message(message, template_name="activate_account_email.html")
+
+
+def check_account_activation_token(token: str):
+    try:
+        decoded_token = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
+        if decoded_token["expires"] < time.time():
+            return None
+        return decoded_token
+    except:
+        return None
diff --git a/crud.py b/crud.py
index 5f7928f..8b501c1 100644
--- a/crud.py
+++ b/crud.py
@@ -56,25 +56,13 @@ def get_exercises(
     user_id: int | None = None,
 ):
     exercises = select(models.Exercise)
-    # first, filter the exercises by complexity, category and title
-    if complexity:
-        exercises = exercises.filter(models.Exercise.complexity == complexity)
-    if categories:
-        for category in categories:
-            exercises = exercises.filter(models.Exercise.category.contains(category))
-    if title_like:
-        if case_sensitive:
-            exercises = exercises.filter(models.Exercise.title.like(f"%{title_like}%"))
-        else:
-            exercises = exercises.filter(models.Exercise.title.ilike(f"%{title_like}%"))
-    # then, sort the exercises
+    # sort the exercises
     if order_by:
         # sort by completion (completion is in DoExercise table)
         if order_by == schemas.ExerciseOrderBy.completion:
-            exercises = (
-                select(models.Exercise)
-                .join(models.DoExercise)
-                .filter(models.DoExercise.user_id == user_id)
+            # assert user_id
+            exercises = exercises.join(models.DoExercise, isouter=True).filter(
+                models.DoExercise.user_id == user_id
             )
             exercises = exercises.order_by(
                 exercise_order_by_column[order_by].desc()
@@ -83,11 +71,22 @@ def get_exercises(
             )
         # sort with elements in exercise's table
         else:
+            # assert not user_id
             exercises = exercises.order_by(
                 exercise_order_by_column[order_by].desc()
                 if order == schemas.Order.desc
                 else exercise_order_by_column[order_by]
             )
+    if complexity:
+        exercises = exercises.filter(models.Exercise.complexity == complexity)
+    if categories:
+        for category in categories:
+            exercises = exercises.filter(models.Exercise.category.contains(category))
+    if title_like:
+        if case_sensitive:
+            exercises = exercises.filter(models.Exercise.title.like(f"%{title_like}%"))
+        else:
+            exercises = exercises.filter(models.Exercise.title.ilike(f"%{title_like}%"))
     # if the id of a user is given then add the completion of the specific user
     if user_id:
         exercises = (
@@ -207,7 +206,7 @@ def get_account(db: Session, auth_user: schemas.AuthSchema, account_id: int):
             db.query(models.Account)
             .filter(
                 models.Account.id_account == account_id,
-                models.Account.account_category == models.AccountType.Admin,
+                models.Account.account_category != models.AccountType.Regular,
             )
             .first()
         )
@@ -386,12 +385,25 @@ def delete_category(db: Session, category: str):
 
 
 def update_category(db: Session, old_category: str, new_category: schemas.Category):
+    stored_new_category = (
+        db.query(models.Category)
+        .filter(models.Category.category == new_category.category)
+        .first()
+    )
     stored_category = (
         db.query(models.Category)
         .filter(models.Category.category == old_category)
         .first()
     )
-    setattr(stored_category, "category", new_category.category)
+    exs_with_old_category = stored_category.exercises
+
+    if not stored_new_category:
+        setattr(stored_category, "category", new_category.category)
+    else:
+        db.delete(stored_category)
+    db.commit()
+
+    for ex in exs_with_old_category:
+        ex.category.append(stored_new_category or stored_category)
     db.commit()
-    db.refresh(stored_category)
     return stored_category
diff --git a/html_templates/activate_account_email.html b/html_templates/activate_account_email.html
new file mode 100644
index 0000000..1cd263d
--- /dev/null
+++ b/html_templates/activate_account_email.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+        <title>Activate your account</title>
+    </head>
+    <body>
+    <h2 style="color: #27a9e1;"> Hey!</h2>
+    <p style="font-size:18px;color: #030303;">It seems a account for you was created!</p>
+    <p style="font-size:18px;color: #030303;">Follow this link to finish the registration and set a password for your account:</p>
+    <p><a style="font-size:18px;display: inline-block; padding: 10px 20px; background-color: #27a9e1; color: #ffffff; text-decoration: none; border-radius: 5px;" href="{{url}}">Set password</a></p>
+    <b style="font-size:18px;color: #ff9999;">Note: This link will expire in {{expire_in_hours}} hours.</b>
+    <br>
+    <hr style="border: 1px solid #CCCCCC;">
+    <p style="font-size:14px;color: #888888;">If you've received this mail without filling a reqeust, it's likely that a user entered your email address by mistake. In that case, just ignore it.</p>
+    </body>
+</html>
diff --git a/main.py b/main.py
index fd5b6b5..3b64171 100644
--- a/main.py
+++ b/main.py
@@ -224,21 +224,42 @@ def track_exercise_completion(
     return db_do_exercise
 
 
-@app.post("/accounts", response_model=schemas.AccountOut)
-def create_account(
-    account_in: schemas.AccountPostAdmin,
+@app.post("/accounts")
+async def create_account(
+    account_in: schemas.AccountPostAdminIn,
     db: Session = Depends(get_db),
     auth_user: schemas.AuthSchema = Depends(JWTBearer()),
 ):
     validate_access_level(auth_user, models.AccountType.Superadmin)
-    if crud.email_is_registered(db, account_in.email):
-        raise HTTPException(status_code=409, detail="Email already registered")
 
-    if account_in.is_superadmin:
+    try:
+        await auth.send_account_password_mail(account=account_in)
+        return {
+            "result": f"An email has been sent to {account_in.email} with a link for activating the account."
+        }
+    except Exception as e:
+        print(e)
+        raise HTTPException(status_code=500, detail=f"An unexpected error occurred")
+
+
+@app.post("/accounts/activate", response_model=schemas.AccountOut)
+def account_reset_password_result(
+    input: schemas.ActivateAccountSchema,
+    db: Session = Depends(get_db),
+):
+    result = auth.check_account_activation_token(input.token)
+    if result == None:
+        raise HTTPException(status_code=401, detail="Token is expired or not valid")
+    if crud.email_is_registered(db, result["email"]):
+        raise HTTPException(status_code=409, detail="Email already registered")
+    if result["is_superadmin"]:
         type_account = models.AccountType.Superadmin
     else:
         type_account = models.AccountType.Admin
-    account_saved = crud.create_account(db, account_in, type_account)
+    new_account = schemas.AccountPostAdmin
+    new_account.email = result["email"]
+    new_account.password = input.password
+    account_saved = crud.create_account(db, new_account, type_account)
     return account_saved
 
 
diff --git a/models.py b/models.py
index e08c8b3..8ccfe42 100644
--- a/models.py
+++ b/models.py
@@ -62,9 +62,7 @@ class Exercise(Base):
     title = Column(String)
     complexity = Column(Enum(Complexity), nullable=True)
     text = Column(String)
-    category = relationship(
-        "Category", secondary=exercise_category, back_populates="exercises"
-    )
+    category = relationship("Category", secondary=exercise_category)
     users = relationship("DoExercise", back_populates="exercise", lazy="dynamic")
     date = Column(DateTime, default=func.now(), onupdate=func.now())
 
@@ -94,4 +92,6 @@ class Category(Base):
     __tablename__ = "category"
 
     category = Column(String, primary_key=True)
-    exercises = relationship("Exercise", secondary=exercise_category)
+    exercises = relationship(
+        "Exercise", secondary=exercise_category, back_populates="category"
+    )
diff --git a/schemas.py b/schemas.py
index 9d24cf1..6dd96ce 100644
--- a/schemas.py
+++ b/schemas.py
@@ -82,6 +82,11 @@ class AccountIn(BaseModel):
     password: str
 
 
+class AccountPostAdminIn(BaseModel):
+    email: EmailStr
+    is_superadmin: Optional[bool] = False
+
+
 class AccountPostAdmin(AccountIn):
     is_superadmin: Optional[bool] = False
 
@@ -148,3 +153,9 @@ class ResetPasswordSchema(BaseModel):
 
 class ResetPasswordResultSchema(BaseModel):
     details: str
+
+
+# Activate Account
+class ActivateAccountSchema(BaseModel):
+    password: str
+    token: str
diff --git a/test/conftest.py b/test/conftest.py
index b5c4875..e00dd67 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -4,6 +4,7 @@
 from crud import password_hasher
 from database import SessionLocal
 from main import app
+from auth import create_account_activation_token
 import models
 
 
@@ -26,14 +27,16 @@ def regular_token():
 @pytest.fixture(scope="session")
 def admin_token(superadmin_token):
     account_details = {"email": "admin@gmail.com", "password": "admin"}
+    activate = {
+        "token": create_account_activation_token("admin@gmail.com", False, 60000),
+        "password": "admin",
+    }
     resp = client.post("http://localhost:8000/login", json=account_details).json()
     if "detail" in resp and resp["detail"] == "Username/Password wrong":
         resp = client.post(
-            "http://localhost:8000/accounts",
-            json=account_details,
-            headers=auth_header(superadmin_token),
+            "http://localhost:8000/accounts/activate", json=activate
         ).json()
-        resp = client.post("http://localhost:8000/login", json=account_details).json()
+    resp = client.post("http://localhost:8000/login", json=account_details).json()
     access_token = resp["access_token"]
     yield access_token
 
diff --git a/test/test_accounts.py b/test/test_accounts.py
index c4ee824..1b6549e 100644
--- a/test/test_accounts.py
+++ b/test/test_accounts.py
@@ -1,5 +1,7 @@
 from conftest import client, auth_header, good_request, bad_request
 
+from auth import createPasswortResetToken, create_account_activation_token
+
 
 def test_create_account(superadmin_token):
     accounts = client.get(
@@ -13,12 +15,38 @@ def test_create_account(superadmin_token):
         headers=auth_header(superadmin_token),
     )
     assert resp.status_code == 200
+    activate = {
+        "token": create_account_activation_token("email@gmail.com", False, 6000),
+        "password": "secret",
+    }
+    activate_result = client.post(
+        "http://localhost:8000/accounts/activate", json=activate
+    )
+    assert activate_result.status_code == 200
     accounts = client.get(
         "http://localhost:8000/accounts", headers=auth_header(superadmin_token)
     ).json()
     assert len(accounts["items"]) == account_count + 1
 
 
+def test_activate_account():
+    account = {"email": "activate@gmail.com", "password": "secret"}
+    resp = client.post("http://localhost:8000/login", json=account)
+    # Check if login is not possible
+    assert resp.status_code == 400
+    token = create_account_activation_token("activate@gmail.com", False, 6000)
+    activate = {
+        "token": token,
+        "password": "secret",
+    }
+
+    resp2 = client.post("http://localhost:8000/accounts/activate", json=activate)
+    assert resp2.status_code == 200
+    # Try to login again
+    resp3 = client.post("http://localhost:8000/login", json=account)
+    assert resp3.status_code == 200
+
+
 def test_update_account(superadmin_token):
     # Get the superadmin
     accounts = client.get(
@@ -192,7 +220,7 @@ def test_update_account_invalid_email(superadmin_token):
     assert resp.status_code == 422  # Expecting a validation error
 
 
-def test_update_account_invalid_email(superadmin_token):
+def test_update_non_existent_account(superadmin_token):
     # Try updating a non-existent account
     non_existent_account_id = 999999  # Assuming this ID doesn't exist
     resp = client.patch(
@@ -201,3 +229,31 @@ def test_update_account_invalid_email(superadmin_token):
         headers=auth_header(superadmin_token),
     )
     assert resp.status_code == 404  # Expecting a not found error
+
+
+def test_delete_superadmin_account(superadmin_token):
+    new_admin = {
+        "email": "new_admin@mail.com",
+        "is_superadmin": True,
+    }
+    new_admin_resp = good_request(
+        client.post,
+        "http://localhost:8000/accounts",
+        headers=auth_header(superadmin_token),
+        json=new_admin,
+    )
+    activate = {
+        "token": create_account_activation_token("new_admin@mail.com", True, 6000),
+        "password": "new_passwrd",
+    }
+    activate_result = client.post(
+        "http://localhost:8000/accounts/activate", json=activate
+    )
+    assert activate_result.status_code == 200
+    activate_result_json = activate_result.json()
+    id_account = activate_result_json["id_account"]
+    good_request(
+        client.delete,
+        f"http://localhost:8000/accounts/{id_account}",
+        headers=auth_header(superadmin_token),
+    )
diff --git a/test/test_categories.py b/test/test_categories.py
index 2020ed8..40e3589 100644
--- a/test/test_categories.py
+++ b/test/test_categories.py
@@ -1,6 +1,6 @@
 import pytest
 
-from conftest import client, auth_header
+from conftest import client, auth_header, good_request
 
 
 @pytest.mark.parametrize("category_name", ["Dogs", "Cats"])
@@ -214,3 +214,38 @@ def test_patch_nonexistent_category(admin_token):
     )
     assert resp.status_code == 404
     assert resp.json()["detail"] == "category not found"
+
+
+def test_patch_category_updates_linked_exercises(create_exercise, admin_token):
+    ex_wood_id = create_exercise(categories=["wood"])["id"]
+    patch_category = {"category": "stone"}
+    good_request(
+        client.patch,
+        "http://localhost:8000/categories/wood",
+        headers=auth_header(admin_token),
+        json=patch_category,
+    )
+    ex = good_request(client.get, f"http://localhost:8000/exercises/{ex_wood_id}")
+    assert ex["category"][0]["category"] == "stone"
+    good_request(
+        client.delete,
+        "http://localhost:8000/categories/stone",
+        headers=auth_header(admin_token),
+    )
+
+
+def test_patch_category_to_existing_category(create_exercise, admin_token):
+    create_exercise(categories=["wood"])["id"]
+    create_exercise(categories=["stone"])["id"]
+    patch_category = {"category": "stone"}
+    good_request(
+        client.patch,
+        "http://localhost:8000/categories/wood",
+        headers=auth_header(admin_token),
+        json=patch_category,
+    )
+    good_request(
+        client.delete,
+        "http://localhost:8000/categories/stone",
+        headers=auth_header(admin_token),
+    )
diff --git a/test/test_do_exercise.py b/test/test_do_exercise.py
index f5f1590..c665d9b 100644
--- a/test/test_do_exercise.py
+++ b/test/test_do_exercise.py
@@ -217,6 +217,10 @@ def test_sort_completion(regular_token, create_user, create_exercise):
     exercise_id1 = create_exercise()["id"]
     exercise_id2 = create_exercise()["id"]
     exercise_id3 = create_exercise()["id"]
+    # Create an exercise without adding completion to
+    # check that an exercise not already started
+    # returns completion 0
+    exercise_id4 = create_exercise()["id"]
 
     exercise_completion1 = {
         "user_id": created_user_id,
@@ -232,7 +236,7 @@ def test_sort_completion(regular_token, create_user, create_exercise):
     }
     exercise_completion3 = {
         "user_id": created_user_id,
-        "completion": 0,
+        "completion": 5,
         "time_spent": 100,
         "position": 29,
     }
@@ -280,3 +284,4 @@ def test_sort_completion(regular_token, create_user, create_exercise):
     for exercise in exercises:
         completions.append(exercise["completion"]["completion"])
     assert completions == sorted(completions)[::-1]
+    # assert 0 in completions