diff --git a/app/Http/Controllers/Server/AuthController.php b/app/Http/Controllers/Server/AuthController.php
index 11fb010b73dae1b1470d1f7390c40471d1efc854..eb7dd883e8e2499b2745311f5507635bb777f2dc 100644
--- a/app/Http/Controllers/Server/AuthController.php
+++ b/app/Http/Controllers/Server/AuthController.php
@@ -176,4 +176,37 @@ public function heartbeat(ServerHeartbeatRequest $request)
         $server->heartbeat($request->input("ip"), $request->input("port"), $request->input("pubkey"));
         return response()->noContent();
     }
+
+    /**
+     *  @OA\Post(
+     *    tags={"Servers:Authentication"},
+     *    path="/auth/server/stop",
+     *    summary="Singla to the API that the server has stopped",
+     *    @OA\Response(
+     *      response="401",
+     *      ref="#/components/responses/401"
+     *    ),
+     *    @OA\Response(
+     *      response="403",
+     *      description="Server is offline",
+     *    ),
+     *    @OA\Response(
+     *      response="204",
+     *      description="OK",
+     *    ),
+     *  )
+     */
+    public function stop(Request $request)
+    {
+        $server = Auth::guard('server')->user();
+
+        if (!$server->online) {
+            return response()->json([
+                'message' => 'Server is offline',
+            ], 403);
+        }
+
+        $server->stop();
+        return response()->noContent();
+    }
 }
diff --git a/app/Jobs/CheckServers.php b/app/Jobs/CheckServers.php
index 2b0db6a20f5888749eef67b9a069ed39fa3f730d..35dfedc410e9e40f5f249f1ae6641b8034b6ba10 100644
--- a/app/Jobs/CheckServers.php
+++ b/app/Jobs/CheckServers.php
@@ -35,22 +35,7 @@ public function handle()
         // We grab the server that are marked online but didn't do a heartbeat in the last two minutes.
         // This happens when a server crashes or goes offline.
         Server::where("online", true)->where('last_heartbeat_at', '<', Carbon::now()->subSeconds(120)->toDateTimeString())->lazyById()->each(function ($server) {
-            // We fetch all the users connected to the server and mark them as disconnected.
-            // NOTE: The users will have to wait at least one minute and at most three minutes
-            // since the server crashes before connecting to another server.
-            $server->users->each(function ($user) {
-                $user->disconnect();
-            });
-
-            // We fetch all the game that were running, detach their users (thus deleting the pivot data)
-            // and delete the game. This makes it as the game never happened.
-            $server->games->whereIn("state", ["created", "playing"])->each(function($game) {
-                $game->users()->detach();
-                $game->delete();
-            });
-
-            // We mark the server as offline
-            $server->offline();
+            $server->stop();
         });
     }
 }
diff --git a/app/Models/Server.php b/app/Models/Server.php
index 27613dec705dea4235d398c10a751d7ec8c388e1..cd2355a19e909c1f264176d1efe59f046a62decf 100644
--- a/app/Models/Server.php
+++ b/app/Models/Server.php
@@ -113,4 +113,24 @@ public function offline()
         $this->pubkey = null;
         $this->save();
     }
+
+    public function stop()
+    {
+        // We fetch all the users connected to the server and mark them as disconnected.
+        // NOTE: The users will have to wait at least one minute and at most three minutes
+        // since the server crashes before connecting to another server.
+        $this->users->each(function ($user) {
+            $user->disconnect();
+        });
+
+        // We fetch all the game that were running, detach their users (thus deleting the pivot data)
+        // and delete the game. This makes it as the game never happened.
+        $this->games->whereIn("state", ["created", "playing"])->each(function($game) {
+            $game->users()->detach();
+            $game->delete();
+        });
+
+        // We mark the server as offline
+        $this->offline();
+    }
 }
\ No newline at end of file
diff --git a/composer.json b/composer.json
index e4e67a6ab4e210f3382f11b13caa627f5083011f..dcfca6f3ae0d009b7bf4dfe05c8e31c6d1173abd 100644
--- a/composer.json
+++ b/composer.json
@@ -4,7 +4,7 @@
     "description": "The Laravel Framework.",
     "keywords": ["framework", "laravel"],
     "license": "MIT",
-    "version": "1.1.0",
+    "version": "1.2.0",
     "require": {
         "php": "^8.0.2",
         "darkaonline/l5-swagger": "^8.4",
diff --git a/docker-compose.yml b/docker-compose.yml
index 3f2d7449b7b540f2d82ac832213731bb87e165e0..e663b75a265784396f5221bb468499742b4453c2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -18,7 +18,7 @@ services:
       database:
         condition: service_healthy
     build: .
-    command: sh -c "php artisan migrate --force && php artisan serve --host 0.0.0.0"
+    command: sh -c "php artisan migrate --force && php artisan l5-swagger:generate && php artisan serve --host 0.0.0.0"
     image: registry.app.unistra.fr/bombernyan/api
     volumes:
       - storage:/api/storage
diff --git a/routes/api.php b/routes/api.php
index 54c49774a750f9704e90e97f5d1a8a800a004012..778f260e0e10c7eb37af506080073a13517cc3b7 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -38,6 +38,7 @@
             Route::post('refresh', [Server\AuthController::class, 'refresh']);
             Route::get('profile', [Server\AuthController::class, 'profile']);
             Route::post('heartbeat', [Server\AuthController::class, 'heartbeat']);
+            Route::post('stop', [Server\AuthController::class, 'stop']);
         });
     });
     
diff --git a/tests/Feature/StopTest.php b/tests/Feature/StopTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d23042dda52a147e0d23ea78b13e6dd0e7304671
--- /dev/null
+++ b/tests/Feature/StopTest.php
@@ -0,0 +1,190 @@
+<?php
+
+namespace Tests\Feature;
+
+use App\Jobs\CheckServers;
+use App\Models\Game;
+use App\Models\Server;
+use App\Models\User;
+use Carbon\Carbon;
+use Illuminate\Foundation\Testing\RefreshDatabase;
+use Illuminate\Foundation\Testing\WithFaker;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Hash;
+use Tests\TestCase;
+
+class StopTest extends TestCase
+{
+    use RefreshDatabase;
+    
+    public function test_stop()
+    {
+        $user = User::create([
+            'username' => 'test',
+            'email' => 'test@localhost',
+            'password' => Hash::make('test'),
+        ]);
+        $user2 = User::create([
+            'username' => 'test2',
+            'email' => 'test2@localhost',
+            'password' => Hash::make('test'),
+        ]);
+
+        $server = Server::create([
+            'login' => 'test',
+            'password' => Hash::make('test'),
+            'owner_id' => $user->id,
+            'public' => true
+        ]);
+
+        $user->server_id = $server->id;
+        $user->server_state = 'connected';
+        $user->server_token = null;
+        $user->save();
+        
+        $user2->server_id = $server->id;
+        $user2->server_state = 'connected';
+        $user2->server_token = null;
+        $user2->save();
+
+        $server->heartbeat('127.0.0.1', 12345, 'pubkey');
+        $server->last_heartbeat_at = Carbon::now()->subMinutes(5);
+        $server->save();
+
+        $game = Game::create([
+            "server_id" => $server->id
+        ]);
+
+        $game->users()->attach($user->id);
+        $game->users()->attach($user2->id);
+        
+        $server = $server->refresh();
+        $this->assertEquals(true, $server->online);
+        $this->assertEquals("127.0.0.1", $server->ip);
+        $this->assertEquals(12345, $server->port);
+        $this->assertEquals("pubkey", $server->pubkey);
+
+        $server_token = Auth::guard('server')->login($server);
+
+        $response = $this->withHeaders([
+            "Authorization" => "Bearer " . $server_token
+        ])->post('/api/auth/server/stop');
+        $response->assertStatus(204);
+
+        $server = $server->refresh();
+        $this->assertEquals(null, $server->online);
+        $this->assertEquals(null, $server->ip);
+        $this->assertEquals(null, $server->port);
+        $this->assertEquals(null, $server->pubkey);
+        
+        $user = $user->refresh();
+        $this->assertEquals(null, $user->server_id);
+        $this->assertEquals("offline", $user->server_state);
+        $this->assertEquals(null, $user->server_token);
+        $user2 = $user2->refresh();
+        $this->assertEquals(null, $user2->server_id);
+        $this->assertEquals("offline", $user2->server_state);
+        $this->assertEquals(null, $user2->server_token);
+
+        $this->assertDatabaseCount("games", 0);
+        $this->assertDatabaseCount("users_games", 0);
+    }
+
+    public function test_stop_game_finished()
+    {
+        $user = User::create([
+            'username' => 'test',
+            'email' => 'test@localhost',
+            'password' => Hash::make('test'),
+        ]);
+        $user2 = User::create([
+            'username' => 'test2',
+            'email' => 'test2@localhost',
+            'password' => Hash::make('test'),
+        ]);
+
+        $server = Server::create([
+            'login' => 'test',
+            'password' => Hash::make('test'),
+            'owner_id' => $user->id,
+            'public' => true
+        ]);
+
+        $user->server_id = $server->id;
+        $user->server_state = 'connected';
+        $user->server_token = null;
+        $user->save();
+        
+        $user2->server_id = $server->id;
+        $user2->server_state = 'connected';
+        $user2->server_token = null;
+        $user2->save();
+
+        $server->heartbeat('127.0.0.1', 12345, 'pubkey');
+        $server->last_heartbeat_at = Carbon::now()->subMinutes(5);
+        $server->save();
+
+        $game = Game::create([
+            "server_id" => $server->id
+        ]);
+
+        $game->users()->attach($user->id);
+        $game->users()->attach($user2->id);
+        $game->state = 'finished';
+        $game->save();
+        
+        $server = $server->refresh();
+        $this->assertEquals(true, $server->online);
+        $this->assertEquals("127.0.0.1", $server->ip);
+        $this->assertEquals(12345, $server->port);
+        $this->assertEquals("pubkey", $server->pubkey);
+
+        $server_token = Auth::guard('server')->login($server);
+
+        $response = $this->withHeaders([
+            "Authorization" => "Bearer " . $server_token
+        ])->post('/api/auth/server/stop');
+        $response->assertStatus(204);
+
+        $server = $server->refresh();
+        $this->assertEquals(null, $server->online);
+        $this->assertEquals(null, $server->ip);
+        $this->assertEquals(null, $server->port);
+        $this->assertEquals(null, $server->pubkey);
+        
+        $user = $user->refresh();
+        $this->assertEquals(null, $user->server_id);
+        $this->assertEquals("offline", $user->server_state);
+        $this->assertEquals(null, $user->server_token);
+        $user2 = $user2->refresh();
+        $this->assertEquals(null, $user2->server_id);
+        $this->assertEquals("offline", $user2->server_state);
+        $this->assertEquals(null, $user2->server_token);
+
+        $this->assertDatabaseCount("games", 1);
+        $this->assertDatabaseCount("users_games", 2);
+    }
+
+    public function test_stop_offline()
+    {
+        $user = User::create([
+            'username' => 'test',
+            'email' => 'test@localhost',
+            'password' => Hash::make('test'),
+        ]);
+
+        $server = Server::create([
+            'login' => 'test',
+            'password' => Hash::make('test'),
+            'owner_id' => $user->id,
+            'public' => true
+        ]);
+
+        $server_token = Auth::guard('server')->login($server);
+
+        $response = $this->withHeaders([
+            "Authorization" => "Bearer " . $server_token
+        ])->post('/api/auth/server/stop');
+        $response->assertStatus(403);
+    }
+}