diff --git a/src/dto_helpers.rs b/src/dto_helpers.rs
new file mode 100644
index 0000000000000000000000000000000000000000..915376cbe86986798edd77298ab929acbfea84f7
--- /dev/null
+++ b/src/dto_helpers.rs
@@ -0,0 +1,110 @@
+use diesel::*;
+
+use crate::dto::*;
+use crate::models::*;
+use crate::schema::*;
+
+pub fn load_title(db: &PgConnection, title: Title) -> QueryResult<TitleDto> {
+    let title_names: Vec<TitleName> = TitleName::belonging_to(&title)
+        .load::<TitleName>(db)?;
+    let title_descriptions: Vec<TitleDescription> = TitleDescription::belonging_to(&title)
+        .load::<TitleDescription>(db)?;
+    let title_cast: Vec<(TitleCast, Person)> = TitleCast::belonging_to(&title)
+        .inner_join(people::table)
+        .load::<(TitleCast, Person)>(db)?;
+    let title_genres: Vec<(TitleGenre, Genre)> = TitleGenre::belonging_to(&title)
+        .inner_join(genres::table)
+        .load::<(TitleGenre, Genre)>(db)?;
+    let title_ratings: Vec<TitleRating> = TitleRating::belonging_to(&title)
+        .load::<TitleRating>(db)?;
+    let title_images: Vec<TitleImage> = TitleImage::belonging_to(&title)
+        .load::<TitleImage>(db)?;
+    let title_media: Vec<TitleMedium> = TitleMedium::belonging_to(&title)
+        .load::<TitleMedium>(db)?;
+    let title_subtitles: Vec<TitleSubtitle> = TitleSubtitle::belonging_to(&title)
+        .load::<TitleSubtitle>(db)?;
+    Ok(process_title(
+        title, title_names, title_descriptions,
+        title_cast, title_genres, title_ratings,
+        title_images, title_media, title_subtitles,
+    ))
+}
+
+pub fn load_titles(db: &PgConnection, titles: Vec<Title>) -> QueryResult<Vec<TitleDto>> {
+    let title_names: Vec<Vec<TitleName>> = TitleName::belonging_to(&titles)
+        .load::<TitleName>(db)?
+        .grouped_by(&titles);
+    let title_descriptions: Vec<Vec<TitleDescription>> = TitleDescription::belonging_to(&titles)
+        .load::<TitleDescription>(db)?
+        .grouped_by(&titles);
+    let title_cast: Vec<Vec<(TitleCast, Person)>> = TitleCast::belonging_to(&titles)
+        .inner_join(people::table)
+        .load::<(TitleCast, Person)>(db)?
+        .grouped_by(&titles);
+    let title_genres: Vec<Vec<(TitleGenre, Genre)>> = TitleGenre::belonging_to(&titles)
+        .inner_join(genres::table)
+        .load::<(TitleGenre, Genre)>(db)?
+        .grouped_by(&titles);
+    let title_ratings: Vec<Vec<TitleRating>> = TitleRating::belonging_to(&titles)
+        .load::<TitleRating>(db)?
+        .grouped_by(&titles);
+    let title_images: Vec<Vec<TitleImage>> = TitleImage::belonging_to(&titles)
+        .load::<TitleImage>(db)?
+        .grouped_by(&titles);
+    let title_media: Vec<Vec<TitleMedium>> = TitleMedium::belonging_to(&titles)
+        .load::<TitleMedium>(db)?
+        .grouped_by(&titles);
+    let title_subtitles: Vec<Vec<TitleSubtitle>> = TitleSubtitle::belonging_to(&titles)
+        .load::<TitleSubtitle>(db)?
+        .grouped_by(&titles);
+    Ok(titles.into_iter()
+        .zip(title_names)
+        .zip(title_descriptions)
+        .zip(title_cast)
+        .zip(title_genres)
+        .zip(title_ratings)
+        .zip(title_images)
+        .zip(title_media)
+        .zip(title_subtitles)
+        .map(|tuple| {
+            let ((((((((title, akas), descriptions),
+                cast), genres), ratings),
+                images), media), subtitles) = tuple;
+            process_title(title, akas, descriptions, cast, genres, ratings, images, media, subtitles)
+        }).collect::<Vec<TitleDto>>())
+}
+
+fn process_title(
+    title: Title, names: Vec<TitleName>, descriptions: Vec<TitleDescription>,
+    cast: Vec<(TitleCast, Person)>, genres: Vec<(TitleGenre, Genre)>, ratings: Vec<TitleRating>,
+    images: Vec<TitleImage>, media: Vec<TitleMedium>, subtitles: Vec<TitleSubtitle>
+) -> TitleDto {
+    TitleDto::of(
+        title,
+        names.into_iter().map(|src| {
+            TitleNameDto::from(src)
+        }).collect::<Vec<_>>(),
+        descriptions.into_iter().map(|src| {
+            TitleDescriptionDto::from(src)
+        }).collect::<Vec<_>>(),
+        cast.into_iter().map(|src| {
+            let (cast, person) = src;
+            TitleCastDto::of(cast, person)
+        }).collect::<Vec<_>>(),
+        genres.into_iter().map(|(_, src)| {
+            GenreDto::from(src)
+        }).collect::<Vec<_>>(),
+        ratings.into_iter().map(|src| {
+            TitleRatingDto::from(src)
+        }).collect::<Vec<_>>(),
+        images.into_iter().map(|src| {
+            TitleImageDto::from(src)
+        }).collect::<Vec<_>>(),
+        media.into_iter().map(|src| {
+            TitleMediaDto::from(src)
+        }).collect::<Vec<_>>(),
+        subtitles.into_iter().map(|src| {
+            TitleSubtitleDto::from(src)
+        }).collect::<Vec<_>>(),
+    )
+}
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index aab3a82d6f448849444cc00ce150d2ec49393620..51672dc16a88d820a3a533d5ad0e93eab71171ec 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,4 +4,6 @@ extern crate dotenv;
 
 pub mod schema;
 pub mod models;
-pub mod dto;
\ No newline at end of file
+pub mod dto;
+pub mod dto_helpers;
+pub mod param_helpers;
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 4440c1935950f894c69ad8c11f3720644c9009f8..56dd192028c32b3c0c13d392f83e2a0bf49a4e75 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,19 +8,17 @@ extern crate rocket_contrib;
 
 use diesel::prelude::*;
 use dotenv::dotenv;
-use rocket::http::RawStr;
-use rocket::request::FromParam;
 use rocket_contrib::databases::diesel;
 use rocket_contrib::json::Json;
-use uuid::Uuid;
 
-use media_backend::dto::{GenreDto, GenreWithTitlesDto, TitleCastDto, TitleDescriptionDto, TitleDto, TitleImageDto, TitleMediaDto, TitleNameDto, TitleRatingDto, TitleSubtitleDto};
+use media_backend::dto::*;
+use media_backend::dto_helpers::{load_title, load_titles};
 use media_backend::models::*;
+use media_backend::param_helpers::ParamUuid;
 
 #[database("mediaflix")]
 struct MediaflixConnection(diesel::PgConnection);
 
-
 #[get("/api/v1/genres")]
 fn list_genres(db: MediaflixConnection) -> QueryResult<Json<Vec<Genre>>> {
     use media_backend::schema::*;
@@ -28,109 +26,41 @@ fn list_genres(db: MediaflixConnection) -> QueryResult<Json<Vec<Genre>>> {
     Ok(Json(query.load::<Genre>(&db.0)?))
 }
 
-struct ParamUuid(uuid::Uuid);
-
-impl FromParam<'_> for ParamUuid {
-    type Error = uuid::parser::ParseError;
-
-    fn from_param(param: &RawStr) -> Result<Self, Self::Error> {
-        return Ok(ParamUuid(Uuid::parse_str(param.as_str())?));
-    }
-}
-
-
 #[get("/api/v1/genres/<id>")]
 fn get_genre(db: MediaflixConnection, id: ParamUuid) -> QueryResult<Json<GenreWithTitlesDto>> {
     use media_backend::schema::*;
     let genre: Genre = genres::table
-        .find(id.0)
+        .find(id.uuid())
         .first::<Genre>(&db.0)?;
     let titles: Vec<Title> = title_genres::table
         .filter(title_genres::genre_id.eq(genre.id))
         .inner_join(titles::table)
         .select(titles::all_columns)
         .load::<Title>(&db.0)?;
-    let title_names: Vec<Vec<TitleName>> = TitleName::belonging_to(&titles)
-        .load::<TitleName>(&db.0)?
-        .grouped_by(&titles);
-    let title_descriptions: Vec<Vec<TitleDescription>> = TitleDescription::belonging_to(&titles)
-        .load::<TitleDescription>(&db.0)?
-        .grouped_by(&titles);
-    let title_cast: Vec<Vec<(TitleCast, Person)>> = TitleCast::belonging_to(&titles)
-        .inner_join(people::table)
-        .load::<(TitleCast, Person)>(&db.0)?
-        .grouped_by(&titles);
-    let title_genres: Vec<Vec<(TitleGenre, Genre)>> = TitleGenre::belonging_to(&titles)
-        .inner_join(genres::table)
-        .load::<(TitleGenre, Genre)>(&db.0)?
-        .grouped_by(&titles);
-    let title_ratings: Vec<Vec<TitleRating>> = TitleRating::belonging_to(&titles)
-        .load::<TitleRating>(&db.0)?
-        .grouped_by(&titles);
-    let title_images: Vec<Vec<TitleImage>> = TitleImage::belonging_to(&titles)
-        .load::<TitleImage>(&db.0)?
-        .grouped_by(&titles);
-    let title_media: Vec<Vec<TitleMedium>> = TitleMedium::belonging_to(&titles)
-        .load::<TitleMedium>(&db.0)?
-        .grouped_by(&titles);
-    let title_subtitles: Vec<Vec<TitleSubtitle>> = TitleSubtitle::belonging_to(&titles)
-        .load::<TitleSubtitle>(&db.0)?
-        .grouped_by(&titles);
     Ok(Json(GenreWithTitlesDto {
         genre: GenreDto::from(genre),
-        titles: titles.into_iter()
-            .zip(title_names)
-            .zip(title_descriptions)
-            .zip(title_cast)
-            .zip(title_genres)
-            .zip(title_ratings)
-            .zip(title_images)
-            .zip(title_media)
-            .zip(title_subtitles)
-            .map(|tuple| {
-                let ((((((((title, akas), descriptions),
-                    cast), genres), ratings),
-                    images), media), subtitles) = tuple;
-                TitleDto::of(
-                    title,
-                    akas.into_iter().map(|src| {
-                        TitleNameDto::from(src)
-                    }).collect::<Vec<_>>(),
-                    descriptions.into_iter().map(|src| {
-                        TitleDescriptionDto::from(src)
-                    }).collect::<Vec<_>>(),
-                    cast.into_iter().map(|src| {
-                        let (cast, person) = src;
-                        TitleCastDto::of(cast, person)
-                    }).collect::<Vec<_>>(),
-                    genres.into_iter().map(|(_, src)| {
-                        GenreDto::from(src)
-                    }).collect::<Vec<_>>(),
-                    ratings.into_iter().map(|src| {
-                        TitleRatingDto::from(src)
-                    }).collect::<Vec<_>>(),
-                    images.into_iter().map(|src| {
-                        TitleImageDto::from(src)
-                    }).collect::<Vec<_>>(),
-                    media.into_iter().map(|src| {
-                        TitleMediaDto::from(src)
-                    }).collect::<Vec<_>>(),
-                    subtitles.into_iter().map(|src| {
-                        TitleSubtitleDto::from(src)
-                    }).collect::<Vec<_>>(),
-                )
-            }).collect::<Vec<TitleDto>>(),
+        titles: load_titles(&db.0, titles)?,
     }))
 }
 
+#[get("/api/v1/titles")]
+fn list_titles(db: MediaflixConnection) -> QueryResult<Json<Vec<TitleDto>>> {
+    use media_backend::schema::*;
+    let titles = titles::table
+        .load::<Title>(&db.0)?;
+    Ok(Json(load_titles(&db.0, titles)?))
+}
 
 #[get("/api/v1/titles/<title>")]
-fn get_title(db: MediaflixConnection, title: ParamUuid) -> QueryResult<Json<Title>> {
+fn get_title(db: MediaflixConnection, title: ParamUuid) -> QueryResult<Json<TitleDto>> {
     use media_backend::schema::*;
-    let query = titles::table
-        .find(title.0)
-        .into_boxed();
-    Ok(Json(query.first::<Title>(&db.0)?))
+    let title = load_title(
+        &db.0,
+        titles::table
+            .find(title.uuid())
+            .first::<Title>(&db.0)?,
+    )?;
+    Ok(Json(title))
 }
 
 fn main() {
@@ -143,6 +73,7 @@ fn main() {
             rocket::routes![
                 list_genres,
                 get_genre,
+                list_titles,
                 get_title
             ],
         )
diff --git a/src/param_helpers.rs b/src/param_helpers.rs
new file mode 100644
index 0000000000000000000000000000000000000000..324100e09816d8f4b7310f6a7a57aec81d2649ba
--- /dev/null
+++ b/src/param_helpers.rs
@@ -0,0 +1,19 @@
+use rocket::request::FromParam;
+use rocket::http::RawStr;
+use uuid::Uuid;
+
+pub struct ParamUuid(uuid::Uuid);
+
+impl ParamUuid {
+    pub fn uuid(&self) -> uuid::Uuid {
+        self.0
+    }
+}
+
+impl FromParam<'_> for ParamUuid {
+    type Error = uuid::parser::ParseError;
+
+    fn from_param(param: &RawStr) -> Result<Self, Self::Error> {
+        return Ok(ParamUuid(Uuid::parse_str(param.as_str())?));
+    }
+}
\ No newline at end of file