diff --git a/src/database/guild.rs b/src/database/guild.rs
index 9368007ed081b52926c23035ec948687728e95fd..5ae9bc27941279151c70be669ef88614e3118915 100644
--- a/src/database/guild.rs
+++ b/src/database/guild.rs
@@ -36,7 +36,6 @@ pub struct Guild {
     pub description: String,
     pub owner: String,
 
-    pub channels: Vec<String>,
     pub invites: Vec<Invite>,
     pub bans: Vec<Ban>,
 
diff --git a/src/guards/guild.rs b/src/guards/guild.rs
index b7da66905ba13a208b931e6dda168791e299abd5..cf23d509fa23635edf112ff70ecb2c18e1dc273b 100644
--- a/src/guards/guild.rs
+++ b/src/guards/guild.rs
@@ -15,7 +15,6 @@ pub struct GuildRef {
     pub description: String,
     pub owner: String,
 
-    pub channels: Vec<String>,
     pub bans: Vec<Ban>,
 
     pub default_permissions: i32,
@@ -30,7 +29,6 @@ impl GuildRef {
                     "name": 1,
                     "description": 1,
                     "owner": 1,
-                    "channels": 1,
                     "bans": 1,
                     "default_permissions": 1
                 })
diff --git a/src/routes/guild.rs b/src/routes/guild.rs
index 7a11d51c789308f60963960162236f7242ef94b3..5fbb9fbb31fd16c3f17eced1016cca7f9d120809 100644
--- a/src/routes/guild.rs
+++ b/src/routes/guild.rs
@@ -89,17 +89,11 @@ pub fn my_guilds(user: UserRef) -> Response {
 pub fn guild(user: UserRef, target: GuildRef) -> Option<Response> {
     with_permissions!(user, target);
 
-    let mut targets = vec![];
-    for channel in target.channels {
-        targets.push(Bson::String(channel));
-    }
-
     let col = database::get_collection("channels");
     match col.find(
         doc! {
-            "_id": {
-                "$in": targets,
-            }
+            "type": 2,
+            "guild": &target.id,
         },
         None,
     ) {
@@ -112,7 +106,6 @@ pub fn guild(user: UserRef, target: GuildRef) -> Option<Response> {
                     {
                         channels.push(json!({
                             "id": channel.id,
-                            "last_message": channel.last_message,
                             "name": channel.name,
                             "description": channel.description,
                         }));
@@ -134,6 +127,73 @@ pub fn guild(user: UserRef, target: GuildRef) -> Option<Response> {
     }
 }
 
+#[derive(Serialize, Deserialize)]
+pub struct CreateChannel {
+    nonce: String,
+    name: String,
+    description: Option<String>,
+}
+
+/// create a new channel
+#[post("/<target>/channels", data = "<info>")]
+pub fn create_channel(
+    user: UserRef,
+    target: GuildRef,
+    info: Json<CreateChannel>,
+) -> Option<Response> {
+    let (permissions, _) = with_permissions!(user, target);
+
+    if !permissions.get_manage_channels() {
+        return Some(Response::LackingPermission(Permission::ManageChannels));
+    }
+
+    let nonce: String = info.nonce.chars().take(32).collect();
+    let name: String = info.name.chars().take(32).collect();
+    let description: String = info
+        .description
+        .clone()
+        .unwrap_or(String::new())
+        .chars()
+        .take(255)
+        .collect();
+
+    if let Ok(result) =
+        database::get_collection("channels").find_one(doc! { "nonce": &nonce }, None)
+    {
+        if result.is_some() {
+            return Some(Response::BadRequest(
+                json!({ "error": "Channel already created." }),
+            ));
+        }
+
+        let id = Ulid::new().to_string();
+        if database::get_collection("channels")
+            .insert_one(
+                doc! {
+                    "_id": &id,
+                    "nonce": &nonce,
+                    "type": 2,
+                    "guild": &target.id,
+                    "name": name,
+                    "description": description,
+                },
+                None,
+            )
+            .is_ok()
+        {
+            Some(Response::Success(json!({ "id": &id })))
+        } else {
+            Some(Response::BadRequest(
+                json!({ "error": "Couldn't create channel." }),
+            ))
+        }
+    } else {
+        Some(Response::BadRequest(
+            json!({ "error": "Failed to check if channel was made." }),
+        ))
+    }
+}
+
 #[derive(Serialize, Deserialize)]
 pub struct CreateGuild {
     name: String,
@@ -176,6 +236,7 @@ pub fn create_guild(user: UserRef, info: Json<CreateGuild>) -> Response {
                 "_id": channel_id.clone(),
                 "type": ChannelType::GUILDCHANNEL as u32,
                 "name": "general",
+                "description": "",
                 "guild": id.clone(),
             },
             None,
@@ -212,9 +273,6 @@ pub fn create_guild(user: UserRef, info: Json<CreateGuild>) -> Response {
                 "name": name,
                 "description": description,
                 "owner": &user.id,
-                "channels": [
-                    &channel_id
-                ],
                 "invites": [],
                 "bans": [],
                 "default_permissions": 51,
@@ -416,7 +474,7 @@ pub fn unban_member(user: UserRef, target: GuildRef, other: String) -> Option<Re
                     }
                 }
             },
-            doc! { }
+            doc! {},
         )
         .is_none()
     {
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
index 830cce982e464b67fa5157eeada09ecc070a932a..6e68b4128751fd1e40ba2415928c8b8168cf3de1 100644
--- a/src/routes/mod.rs
+++ b/src/routes/mod.rs
@@ -106,6 +106,7 @@ pub fn mount(rocket: Rocket) -> Rocket {
             routes![
                 guild::my_guilds,
                 guild::guild,
+                guild::create_channel,
                 guild::create_guild,
                 guild::fetch_members,
                 guild::fetch_member,