diff --git a/src/client_server.rs b/src/client_server.rs
index a2045d8f..67480823 100644
--- a/src/client_server.rs
+++ b/src/client_server.rs
@@ -29,7 +29,7 @@ use ruma_client_api::{
         push::{self, get_pushrules_all, set_pushrule, set_pushrule_enabled},
         read_marker::set_read_marker,
         room::create_room,
-        session::{get_login_types, login},
+        session::{get_login_types, login, logout},
         state::{
             create_state_event_for_empty_key, create_state_event_for_key, get_state_events,
             get_state_events_for_empty_key, get_state_events_for_key,
@@ -311,6 +311,19 @@ pub fn login_route(
     }))
 }
 
+#[post("/_matrix/client/r0/logout", data = "<body>")]
+pub fn logout_route(
+    db: State<'_, Database>,
+    body: Ruma<logout::Request>,
+) -> MatrixResult<logout::Response> {
+    let user_id = body.user_id.as_ref().expect("user is authenticated");
+    let device_id = body.device_id.as_ref().expect("user is authenticated");
+
+    db.users.remove_device(&user_id, &device_id).unwrap();
+
+    MatrixResult(Ok(logout::Response))
+}
+
 #[get("/_matrix/client/r0/capabilities")]
 pub fn get_capabilities_route() -> MatrixResult<get_capabilities::Response> {
     // TODO
diff --git a/src/database/users.rs b/src/database/users.rs
index bf1f2145..81a7bb8a 100644
--- a/src/database/users.rs
+++ b/src/database/users.rs
@@ -123,6 +123,37 @@ impl Users {
         Ok(())
     }
 
+    /// Removes a device from a user
+    pub fn remove_device(&self, user_id: &UserId, device_id: &DeviceId) -> Result<()> {
+        let mut userdeviceid = user_id.to_string().as_bytes().to_vec();
+        userdeviceid.push(0xff);
+        userdeviceid.extend_from_slice(device_id.as_bytes());
+
+        // Remove device keys
+        self.userdeviceid_devicekeys.remove(&userdeviceid)?;
+
+        // Remove tokens
+        if let Some(old_token) = self.userdeviceid_token.remove(&userdeviceid)? {
+            self.token_userdeviceid.remove(&old_token)?;
+        }
+
+        // Remove todevice events
+        let mut prefix = userdeviceid.clone();
+        prefix.push(0xff);
+
+        for result in self.todeviceid_events.scan_prefix(&prefix) {
+            let (key, value) = result?;
+            self.todeviceid_events.remove(key)?;
+        }
+
+        // TODO: Remove onetimekeys
+
+        // Remove the device
+        self.userdeviceids.remove(userdeviceid)?;
+
+        Ok(())
+    }
+
     /// Returns an iterator over all device ids of this user.
     pub fn all_device_ids(&self, user_id: &UserId) -> impl Iterator<Item = Result<DeviceId>> {
         let mut prefix = user_id.to_string().as_bytes().to_vec();
diff --git a/src/main.rs b/src/main.rs
index bf331045..3e34ded3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -29,6 +29,7 @@ fn setup_rocket() -> rocket::Rocket {
                 client_server::register_route,
                 client_server::get_login_route,
                 client_server::login_route,
+                client_server::logout_route,
                 client_server::get_capabilities_route,
                 client_server::get_pushrules_all_route,
                 client_server::set_pushrule_route,