diff --git a/backend/app/crud.py b/backend/app/crud.py
index a7bd760106c7ae78176e1628b317bf11c154e3f9..57d3c04439f71427113109accc186d84b9205319 100644
--- a/backend/app/crud.py
+++ b/backend/app/crud.py
@@ -86,9 +86,7 @@ def get_contact_sessions(db: Session, user_id: int, contact_id: int):
 
 
 def create_session(db: Session, user: schemas.User):
-    print("before")
     db_session = models.Session(is_active=True, users=[user])
-    print(db_session.created_at)
     db.add(db_session)
     db.commit()
     db.refresh(db_session)
@@ -112,11 +110,13 @@ def create_session_with_users(
 
 
 def get_session(db: Session, session_id: int):
-    return db.query(models.Session).filter(models.Session.id == session_id).first()
+    session = db.query(models.Session).filter(models.Session.id == session_id).first()
+
+    return session
 
 
 def get_sessions(db: Session, user: schemas.User, skip: int = 0):
-    return (
+    sessions = (
         db.query(models.Session)
         .filter(models.Session.users.any(models.User.id == user.id))
         .filter(models.Session.is_active or user.type < 2)
@@ -126,9 +126,20 @@ def get_sessions(db: Session, user: schemas.User, skip: int = 0):
         .all()
     )
 
+    return sessions
+
 
 def get_all_sessions(db: Session, skip: int = 0):
-    return db.query(models.Session).offset(skip).all()
+    sessions = db.query(models.Session).offset(skip).all()
+
+    for session in sessions:
+        session.length = (
+            db.query(models.Message)
+            .filter(models.Message.session_id == session.id)
+            .count()
+        )
+
+    return sessions
 
 
 def delete_session(db: Session, session_id: int):
diff --git a/backend/app/main.py b/backend/app/main.py
index 677d8b0d96a1f49ff4be954cd0abd9aaebf89137..8b578828de724fb4154e16cc7539fae291a2129d 100644
--- a/backend/app/main.py
+++ b/backend/app/main.py
@@ -15,9 +15,12 @@ from fastapi import (
 from sqlalchemy.orm import Session
 from fastapi.middleware.cors import CORSMiddleware
 from fastapi.websockets import WebSocket
+from fastapi.responses import StreamingResponse
 from contextlib import asynccontextmanager
 import json
 from jose import jwt
+from io import StringIO
+import csv
 
 import schemas
 import crud
@@ -409,7 +412,10 @@ def create_session(
     #        status_code=401, detail="You do not have permission to create a session"
     #    )
 
-    return crud.create_session(db, current_user)
+    rep = crud.create_session(db, current_user)
+    rep.length = 0
+
+    return rep
 
 
 @sessionsRouter.get("/{session_id}", response_model=schemas.Session)
@@ -465,6 +471,34 @@ def update_session(
 
     crud.update_session(db, session, session_id)
 
+@sessionsRouter.get("/{session_id}/download/messages")
+def download_session(
+    session_id: int,
+    db: Session = Depends(get_db),
+    current_user: schemas.User = Depends(get_jwt_user),
+):
+    db_session = crud.get_session(db, session_id)
+    if db_session is None:
+        raise HTTPException(status_code=404, detail="Session not found")
+
+    if not check_user_level(current_user, models.UserType.ADMIN):
+        raise HTTPException(
+            status_code=401, detail="You do not have permission to download this session"
+        )
+
+    data = crud.get_messages(db, session_id)
+
+    output = StringIO()
+    writer = csv.writer(output)
+
+    writer.writerow(models.Message.__table__.columns.keys())
+    for row in data:
+        writer.writerow(row.raw())
+
+    output.seek(0)
+
+    return StreamingResponse(output, media_type="text/csv", headers={"Content-Disposition": f"attachment; filename={session_id}-messages.csv"})
+
 
 @sessionsRouter.post(
     "/{session_id}/users/{user_id}", status_code=status.HTTP_201_CREATED
diff --git a/backend/app/models.py b/backend/app/models.py
index 04fd61c3cfe762fef5c73b0ebb030da8410f76a4..c2db8afb652089e4f40e4db186b69b497a98eb3c 100644
--- a/backend/app/models.py
+++ b/backend/app/models.py
@@ -130,6 +130,16 @@ class Message(Base):
 
     feedbacks = relationship("MessageFeedback", backref="message")
 
+    def raw(self):
+        return [
+            self.id,
+            self.message_id,
+            self.content,
+            self.user_id,
+            self.session_id,
+            self.created_at,
+        ]
+
 
 class MessageMetadata(Base):
     __tablename__ = "message_metadata"
diff --git a/backend/app/schemas.py b/backend/app/schemas.py
index 634a2f7861ba86c358b7a4b2e448cc315959ef0b..721a36b533e115ad7ae87f7526279e689c6766ca 100644
--- a/backend/app/schemas.py
+++ b/backend/app/schemas.py
@@ -82,6 +82,7 @@ class Session(BaseModel):
     start_time: NaiveDatetime
     end_time: NaiveDatetime
     language: str
+    length: int | None = None
 
     class Config:
         from_attributes = True
diff --git a/frontend/src/lang/fr.json b/frontend/src/lang/fr.json
index b1569c9ddd63824e2fc1fe6042baf624ee72d2aa..80642565ae413a791ab8a6eb181d5488ec9c1028 100644
--- a/frontend/src/lang/fr.json
+++ b/frontend/src/lang/fr.json
@@ -9,7 +9,10 @@
 		"tutorSelection": "Tuteur",
 		"language": "Langue",
 		"availability": "Disponibilités",
-		"admin": "Administration"
+		"admin": {
+			"users": "Utilisateurs",
+			"sessions": "Sessions"
+		}
 	},
 	"chatbox": {
 		"placeholder": "Écrivez votre message ici...",
@@ -190,6 +193,9 @@
 			"admin": "Admin",
 			"tutor": "Tuteur",
 			"student": "Étudiant",
+			"admins": "Admin(s)",
+			"tutors": "Tuteur(s)",
+			"students": "Étudiant(s)",
 			"0": "Admin",
 			"1": "Tuteur",
 			"2": "Étudiant"
@@ -296,6 +302,11 @@
 		"bool": {
 			"true": "Oui",
 			"false": "Non"
+		},
+		"words": {
+			"date": "Date",
+			"messages": "Messages",
+			"actions": "Actions"
 		}
 	},
 	"inputs": {
diff --git a/frontend/src/lib/components/header.svelte b/frontend/src/lib/components/header.svelte
index 2fb790361613b733e6e4eef132a0bd9e2bb0dcd9..3f320e1f3a04e434c6237bd64a4ec145a2505603 100644
--- a/frontend/src/lib/components/header.svelte
+++ b/frontend/src/lib/components/header.svelte
@@ -95,13 +95,17 @@
 							<summary class="p-3">
 								<Icon src={Cog6Tooth} class="h-5 w-5" />
 							</summary>
-							<ul class="menu menu-sm dropdown-content absolute right-0">
+							<ul class="menu menu-sm dropdown-content absolute right-0 z-10">
 								<li>
 									<a data-sveltekit-reload href="/admin">
-										{$t('header.admin')}
+										{$t('header.admin.users')}
+									</a>
+								</li>
+								<li>
+									<a data-sveltekit-reload href="/admin/sessions">
+										{$t('header.admin.sessions')}
 									</a>
 								</li>
-								<li><a>Submenu 2</a></li>
 							</ul>
 						</details>
 					</li>
diff --git a/frontend/src/lib/types/session.ts b/frontend/src/lib/types/session.ts
index 19c2d1ec9062a6425df82c9d608e528e34d5b291..2fbdbb65211ae4376f927c328b393e6a3272ccb6 100644
--- a/frontend/src/lib/types/session.ts
+++ b/frontend/src/lib/types/session.ts
@@ -38,6 +38,7 @@ export default class Session {
 	private _lastTyping: Writable<Date | null> = writable(null);
 	private _onlineUsers: Writable<Set<number>> = writable(new Set());
 	private _onlineTimers: Map<number, number> = new Map();
+	private _length: number;
 
 	private constructor(
 		id: number,
@@ -47,7 +48,8 @@ export default class Session {
 		created_at: Date,
 		start_time: Date,
 		end_time: Date,
-		language: string
+		language: string,
+		length: number
 	) {
 		this._id = id;
 		this._token = token;
@@ -58,6 +60,7 @@ export default class Session {
 		this._start_time = start_time;
 		this._end_time = end_time;
 		this._language = language;
+		this._length = length;
 	}
 
 	get id(): number {
@@ -108,6 +111,10 @@ export default class Session {
 		return this._onlineUsers;
 	}
 
+	get length(): number {
+		return this._length;
+	}
+
 	usersList(maxLength = 30): string {
 		const users = this._users
 			.filter((u) => u.id != get(user)?.id)
@@ -375,7 +382,8 @@ export default class Session {
 			parseToLocalDate(json.created_at),
 			parseToLocalDate(json.start_time),
 			parseToLocalDate(json.end_time),
-			json.language
+			json.language,
+			json.length
 		);
 
 		session._users = User.parseAll(json.users);
diff --git a/frontend/src/routes/admin/+page.svelte b/frontend/src/routes/admin/+page.svelte
index 841c103ef900f578c8c501928c20e98a4f11ff20..e3a114a93ded997e4e4d428edd024247aab0cb2a 100644
--- a/frontend/src/routes/admin/+page.svelte
+++ b/frontend/src/routes/admin/+page.svelte
@@ -3,7 +3,6 @@
 	import User, { users } from '$lib/types/user';
 	import { getUsersAPI } from '$lib/api/users';
 	import { t } from '$lib/services/i18n';
-	import { Icon, Trash } from 'svelte-hero-icons';
 	import UserItem from '$lib/components/users/userItem.svelte';
 
 	let ready = false;
diff --git a/frontend/src/routes/admin/sessions/+page.svelte b/frontend/src/routes/admin/sessions/+page.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..36fe14165f20a05b97f0cc4e665fe69bfbfdc2ac
--- /dev/null
+++ b/frontend/src/routes/admin/sessions/+page.svelte
@@ -0,0 +1,63 @@
+<script lang="ts">
+	import { getSessionsAPI } from '$lib/api/sessions';
+	import Session from '$lib/types/session';
+	import { onMount } from 'svelte';
+	import { t } from '$lib/services/i18n';
+	import { displayTime } from '$lib/utils/date';
+	import { ArrowDownTray, ArrowRightStartOnRectangle, Icon } from 'svelte-hero-icons';
+	import config from '$lib/config';
+
+	let sessions: Session[] = [];
+
+	onMount(async () => {
+		sessions = Session.parseAll(await getSessionsAPI());
+	});
+</script>
+
+<table class="table">
+	<thead>
+		<tr>
+			<th>#</th>
+			<th>{$t('utils.words.date')}</th>
+			<th>{$t('users.type.tutors')}</th>
+			<th>{$t('users.type.students')}</th>
+			<th># {$t('utils.words.messages')}</th>
+			<th>{$t('utils.words.actions')}</th>
+		</tr>
+	</thead>
+	<tbody>
+		{#each sessions as session}
+			<tr>
+				<td>{session.id}</td>
+				<td>{displayTime(session.start_time)}</td>
+				<td>
+					{session.users
+						.filter((u) => u.is_tutor || u.is_admin)
+						.map((u) => u.nickname)
+						.join(', ')}
+				</td>
+				<td>
+					{session.users
+						.filter((u) => !u.is_tutor && !u.is_admin)
+						.map((u) => u.nickname)
+						.join(', ')}
+				</td>
+				<td>
+					{session.length}
+				</td>
+				<td>
+					<a class="button" title="Join" href={`/session?id=${session.id}`}>
+						<Icon src={ArrowRightStartOnRectangle} size="24" />
+					</a>
+					<a
+						class="button"
+						title="Download"
+						href={`${config.API_URL}/sessions/${session.id}/download/messages`}
+					>
+						<Icon src={ArrowDownTray} size="24" />
+					</a>
+				</td>
+			</tr>
+		{/each}
+	</tbody>
+</table>