diff --git a/endpoint.c b/endpoint.c
new file mode 100644
index 0000000..7354d3e
--- /dev/null
+++ b/endpoint.c
@@ -0,0 +1,81 @@
+#include <logger.h>
+#include <cJSON.h>
+#include <mongoose.h>
+#include <macros.h>
+#include <endpoint.h>
+
+void
+endpoint_func_index(struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response)
+{
+    (void)args;
+    (void)hm;
+
+    static const char content[] = "Emgauwa";
+    response->status_code = 200;
+    response->content_type = "text/plain";
+    response->content_length = STRLEN(content);;
+    response->content = content;
+    response->alloced_content = false;
+}
+
+void
+endpoint_func_not_found(struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response)
+{
+    (void)args;
+    (void)hm;
+
+    static const char content[] = "404 - NOT FOUND";
+    response->status_code = 404;
+    response->content_type = "text/plain";
+    response->content_length = STRLEN(content);;
+    response->content = content;
+    response->alloced_content = false;
+}
+
+void
+endpoint_response_text(endpoint_response_t *response, int status_code, const char *content, int content_length)
+{
+    if(content == NULL)
+    {
+        content = "";
+        content_length = 0;
+    }
+
+    response->status_code = status_code;
+    response->content_type = "text/plain";
+    if(content_length >= 0)
+    {
+        response->content_length = content_length;
+        response->alloced_content = false;
+    }
+    else
+    {
+        response->content_length = strlen(content);
+        response->alloced_content = true;
+    }
+    response->content = content;
+}
+
+void
+endpoint_response_json(endpoint_response_t *response, int status_code, const cJSON *json_root)
+{
+    if(json_root != NULL)
+    {
+        char *json_str = cJSON_Print(json_root);
+        if (json_str != NULL)
+        {
+            response->status_code = status_code;
+            response->content_type = "application/json";
+            response->content_length = strlen(json_str);
+            response->content = json_str;
+            response->alloced_content = true;
+
+            return;
+        }
+    }
+
+    LOG_ERROR("failed to print schedule json\n");
+
+    static const char content[] = "failed to print json";
+    endpoint_response_text(response, status_code, content, STRLEN(content));
+}
diff --git a/endpoints/api_v1_controllers.c b/endpoints/api_v1_controllers.c
index 64e2dab..1e4de44 100644
--- a/endpoints/api_v1_controllers.c
+++ b/endpoints/api_v1_controllers.c
@@ -23,26 +23,7 @@ api_v1_controllers_GET(struct http_message *hm, endpoint_args_t *args, endpoint_
         cJSON_AddItemToArray(json, json_controller);
     }
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print controllers json\n");
-
-        static const char content[] = "failed to print json for controllers";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     controller_free_list(all_controllers);
 }
diff --git a/endpoints/api_v1_controllers_STR.c b/endpoints/api_v1_controllers_STR.c
index 0d86232..acd3252 100644
--- a/endpoints/api_v1_controllers_STR.c
+++ b/endpoints/api_v1_controllers_STR.c
@@ -18,11 +18,7 @@ api_v1_controllers_STR_GET(struct http_message *hm, endpoint_args_t *args, endpo
         LOG_DEBUG("failed to unparse uid\n");
 
         static const char content[] = "given id was invalid";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -33,37 +29,13 @@ api_v1_controllers_STR_GET(struct http_message *hm, endpoint_args_t *args, endpo
         LOG_DEBUG("could not find a controller for uid '%s'\n", args[0].value.v_str);
 
         static const char content[] = "no controller for id found";
-        response->status_code = 404;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 404, content, STRLEN(content));
         return;
     }
 
     cJSON *json = controller_to_json(controller);
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print controller json\n");
-
-        static const char content[] = "failed to print json for controller";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-        return;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     controller_free(controller);
 }
@@ -79,11 +51,7 @@ api_v1_controllers_STR_PUT(struct http_message *hm, endpoint_args_t *args, endpo
         LOG_DEBUG("failed to unparse uid\n");
 
         static const char content[] = "given id was invalid";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -94,11 +62,7 @@ api_v1_controllers_STR_PUT(struct http_message *hm, endpoint_args_t *args, endpo
         LOG_DEBUG("could not find a controller for uid '%s'\n", args[0].value.v_str);
 
         static const char content[] = "no controller for id found";
-        response->status_code = 404;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 404, content, STRLEN(content));
         return;
     }
 
@@ -107,11 +71,7 @@ api_v1_controllers_STR_PUT(struct http_message *hm, endpoint_args_t *args, endpo
     if(json == NULL)
     {
         static const char content[] = "no valid json was supplied";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
diff --git a/endpoints/api_v1_controllers_STR_relays.c b/endpoints/api_v1_controllers_STR_relays.c
index 7be2d7a..20a8c03 100644
--- a/endpoints/api_v1_controllers_STR_relays.c
+++ b/endpoints/api_v1_controllers_STR_relays.c
@@ -17,11 +17,7 @@ api_v1_controllers_STR_relays_GET(struct http_message *hm, endpoint_args_t *args
         LOG_DEBUG("failed to unparse uid\n");
 
         static const char content[] = "given id was invalid";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -32,11 +28,7 @@ api_v1_controllers_STR_relays_GET(struct http_message *hm, endpoint_args_t *args
         LOG_DEBUG("could not find a controller for uid '%s'\n", args[0].value.v_str);
 
         static const char content[] = "no controller for id found";
-        response->status_code = 404;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 404, content, STRLEN(content));
         return;
     }
         
@@ -51,26 +43,7 @@ api_v1_controllers_STR_relays_GET(struct http_message *hm, endpoint_args_t *args
         cJSON_AddItemToArray(json, json_relay);
     }
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print relays json\n");
-
-        static const char content[] = "failed to print json for relays";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     relay_free_list(all_relays);
     controller_free(controller);
diff --git a/endpoints/api_v1_controllers_STR_relays_INT.c b/endpoints/api_v1_controllers_STR_relays_INT.c
index 2d097e7..0c86094 100644
--- a/endpoints/api_v1_controllers_STR_relays_INT.c
+++ b/endpoints/api_v1_controllers_STR_relays_INT.c
@@ -20,11 +20,7 @@ api_v1_controllers_STR_relays_INT_GET(struct http_message *hm, endpoint_args_t *
         LOG_DEBUG("failed to unparse uid\n");
 
         static const char content[] = "given id was invalid";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -35,11 +31,7 @@ api_v1_controllers_STR_relays_INT_GET(struct http_message *hm, endpoint_args_t *
         LOG_DEBUG("could not find a controller for uid '%s'\n", args[0].value.v_str);
 
         static const char content[] = "no controller for id found";
-        response->status_code = 404;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 404, content, STRLEN(content));
         return;
     }
 
@@ -50,36 +42,13 @@ api_v1_controllers_STR_relays_INT_GET(struct http_message *hm, endpoint_args_t *
         LOG_DEBUG("could not find a relay with num %d for controller '%s'\n", args[1].value.v_int, args[0].value.v_str);
 
         static const char content[] = "no relay for this controller found";
-        response->status_code = 404;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 404, content, STRLEN(content));
         return;
     }
 
     cJSON *json = relay_to_json(relay);
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print relay json\n");
-
-        static const char content[] = "failed to print json for relay";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     relay_free(relay);
     controller_free(controller);
@@ -96,11 +65,7 @@ api_v1_controllers_STR_relays_INT_PUT(struct http_message *hm, endpoint_args_t *
         LOG_DEBUG("failed to unparse uid\n");
 
         static const char content[] = "given id was invalid";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -111,11 +76,7 @@ api_v1_controllers_STR_relays_INT_PUT(struct http_message *hm, endpoint_args_t *
         LOG_DEBUG("could not find a controller for uid '%s'\n", args[0].value.v_str);
 
         static const char content[] = "no controller for id found";
-        response->status_code = 404;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 404, content, STRLEN(content));
         return;
     }
 
@@ -148,11 +109,7 @@ api_v1_controllers_STR_relays_INT_PUT(struct http_message *hm, endpoint_args_t *
     if(json == NULL)
     {
         static const char content[] = "no valid json was supplied";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -179,11 +136,7 @@ api_v1_controllers_STR_relays_INT_PUT(struct http_message *hm, endpoint_args_t *
                 cJSON_Delete(json);
 
                 static const char content[] = "at least one schedule is missing an id";
-                response->status_code = 400;
-                response->content_type = "text/plain";
-                response->content_length = STRLEN(content);;
-                response->content = content;
-                response->alloced_content = false;
+                endpoint_response_text(response, 400, content, STRLEN(content));
                 return;
             }
             uuid_t target_uid;
@@ -193,11 +146,7 @@ api_v1_controllers_STR_relays_INT_PUT(struct http_message *hm, endpoint_args_t *
                 cJSON_Delete(json);
 
                 static const char content[] = "at least one schedule has a bad id";
-                response->status_code = 400;
-                response->content_type = "text/plain";
-                response->content_length = STRLEN(content);;
-                response->content = content;
-                response->alloced_content = false;
+                endpoint_response_text(response, 400, content, STRLEN(content));
                 return;
             }
 
@@ -227,11 +176,7 @@ api_v1_controllers_STR_relays_INT_PUT(struct http_message *hm, endpoint_args_t *
                 cJSON_Delete(json);
 
                 static const char content[] = "active_schedule has a bad id";
-                response->status_code = 400;
-                response->content_type = "text/plain";
-                response->content_length = STRLEN(content);;
-                response->content = content;
-                response->alloced_content = false;
+                endpoint_response_text(response, 400, content, STRLEN(content));
                 return;
             }
             relay->schedules[day_of_week] = schedule_get_by_uid_or_off(target_uid);
@@ -245,12 +190,7 @@ api_v1_controllers_STR_relays_INT_PUT(struct http_message *hm, endpoint_args_t *
         cJSON_Delete(json);
 
         static const char content[] = "failed to save relay to database";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-        return;
+        endpoint_response_text(response, 500, content, STRLEN(content));
         return;
     }
 
@@ -282,26 +222,7 @@ api_v1_controllers_STR_relays_INT_PUT(struct http_message *hm, endpoint_args_t *
 
     command_set_relay_schedule(relay);
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print relay json\n");
-
-        static const char content[] = "failed to print json for relay";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     relay_free(relay);
     controller_free(controller);
diff --git a/endpoints/api_v1_relays.c b/endpoints/api_v1_relays.c
index 69e38d6..355fe4c 100644
--- a/endpoints/api_v1_relays.c
+++ b/endpoints/api_v1_relays.c
@@ -23,26 +23,7 @@ api_v1_relays_GET(struct http_message *hm, endpoint_args_t *args, endpoint_respo
         cJSON_AddItemToArray(json, json_relay);
     }
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print relays json\n");
-
-        static const char content[] = "failed to print json for relays";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     relay_free_list(all_relays);
 }
diff --git a/endpoints/api_v1_relays_tag_STR.c b/endpoints/api_v1_relays_tag_STR.c
index 445ae05..4d465b7 100644
--- a/endpoints/api_v1_relays_tag_STR.c
+++ b/endpoints/api_v1_relays_tag_STR.c
@@ -19,11 +19,7 @@ api_v1_relays_tag_STR_GET(struct http_message *hm, endpoint_args_t *args, endpoi
         LOG_ERROR("failed to load relays for tag from database\n");
 
         static const char content[] = "failed to load relays for tag from database";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 500, content, STRLEN(content));
         return;
     }
 
@@ -44,27 +40,7 @@ api_v1_relays_tag_STR_GET(struct http_message *hm, endpoint_args_t *args, endpoi
         relay_free(relay);
     }
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print relays json\n");
-
-        static const char content[] = "failed to print json for relays";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
-
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     free(relays_ids);
 }
diff --git a/endpoints/api_v1_schedules.c b/endpoints/api_v1_schedules.c
index 8b37f58..5d0e65e 100644
--- a/endpoints/api_v1_schedules.c
+++ b/endpoints/api_v1_schedules.c
@@ -16,11 +16,7 @@ api_v1_schedules_POST(struct http_message *hm, endpoint_args_t *args, endpoint_r
     if(json == NULL)
     {
         static const char content[] = "no valid json was supplied";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -31,11 +27,7 @@ api_v1_schedules_POST(struct http_message *hm, endpoint_args_t *args, endpoint_r
         cJSON_Delete(json);
 
         static const char content[] = "no name for schedule provided";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
     cJSON *json_period;
@@ -66,11 +58,7 @@ api_v1_schedules_POST(struct http_message *hm, endpoint_args_t *args, endpoint_r
             schedule_free(new_schedule);
 
             static const char content[] = "one period is missing a start";
-            response->status_code = 400;
-            response->content_type = "text/plain";
-            response->content_length = STRLEN(content);;
-            response->content = content;
-            response->alloced_content = false;
+            endpoint_response_text(response, 400, content, STRLEN(content));
             return;
         }
         if(!cJSON_IsString(json_period_end) || (json_period_end->valuestring == NULL))
@@ -80,11 +68,7 @@ api_v1_schedules_POST(struct http_message *hm, endpoint_args_t *args, endpoint_r
             schedule_free(new_schedule);
 
             static const char content[] = "one period is missing an end";
-            response->status_code = 400;
-            response->content_type = "text/plain";
-            response->content_length = STRLEN(content);;
-            response->content = content;
-            response->alloced_content = false;
+            endpoint_response_text(response, 400, content, STRLEN(content));
             return;
         }
 
@@ -97,11 +81,7 @@ api_v1_schedules_POST(struct http_message *hm, endpoint_args_t *args, endpoint_r
             schedule_free(new_schedule);
 
             static const char content[] = "the start for one period is invalid";
-            response->status_code = 400;
-            response->content_type = "text/plain";
-            response->content_length = STRLEN(content);;
-            response->content = content;
-            response->alloced_content = false;
+            endpoint_response_text(response, 400, content, STRLEN(content));
             return;
         }
         if(period_helper_parse_hhmm(json_period_end->valuestring, &end))
@@ -111,11 +91,7 @@ api_v1_schedules_POST(struct http_message *hm, endpoint_args_t *args, endpoint_r
             schedule_free(new_schedule);
 
             static const char content[] = "the end for one period is invalid";
-            response->status_code = 400;
-            response->content_type = "text/plain";
-            response->content_length = STRLEN(content);;
-            response->content = content;
-            response->alloced_content = false;
+            endpoint_response_text(response, 400, content, STRLEN(content));
             return;
         }
 
@@ -151,26 +127,7 @@ api_v1_schedules_POST(struct http_message *hm, endpoint_args_t *args, endpoint_r
     cJSON_Delete(json);
     json = schedule_to_json(new_schedule);
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print schedule json\n");
-
-        static const char content[] = "failed to print json for schedule";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 201;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 201, json);
     cJSON_Delete(json);
     schedule_free(new_schedule);
 }
@@ -191,26 +148,7 @@ api_v1_schedules_GET(struct http_message *hm, endpoint_args_t *args, endpoint_re
         cJSON_AddItemToArray(json, json_schedule);
     }
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print schedules json\n");
-
-        static const char content[] = "failed to print json for schedules";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     schedule_free_list(all_schedules);
 }
diff --git a/endpoints/api_v1_schedules_STR.c b/endpoints/api_v1_schedules_STR.c
index 29e68f5..f0d0286 100644
--- a/endpoints/api_v1_schedules_STR.c
+++ b/endpoints/api_v1_schedules_STR.c
@@ -21,11 +21,7 @@ api_v1_schedules_STR_GET(struct http_message *hm, endpoint_args_t *args, endpoin
         LOG_DEBUG("failed to unparse uid\n");
 
         static const char content[] = "given id was invalid";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -36,36 +32,13 @@ api_v1_schedules_STR_GET(struct http_message *hm, endpoint_args_t *args, endpoin
         LOG_DEBUG("could not find a schedule for uid '%s'\n", args[0].value.v_str);
 
         static const char content[] = "no schedule for id found";
-        response->status_code = 404;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 404, content, STRLEN(content));
         return;
     }
 
-    cJSON *json =  schedule_to_json(schedule);
+    cJSON *json = schedule_to_json(schedule);
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print schedules json\n");
-
-        static const char content[] = "failed to print json for schedules";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     schedule_free(schedule);
 }
@@ -81,11 +54,7 @@ api_v1_schedules_STR_PUT(struct http_message *hm, endpoint_args_t *args, endpoin
         LOG_DEBUG("failed to unparse uid\n");
 
         static const char content[] = "given id was invalid";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -96,11 +65,7 @@ api_v1_schedules_STR_PUT(struct http_message *hm, endpoint_args_t *args, endpoin
         LOG_DEBUG("could not find a schedule for uid '%s'\n", args[0].value.v_str);
 
         static const char content[] = "no schedule for id found";
-        response->status_code = 404;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 404, content, STRLEN(content));
         return;
     }
 
@@ -109,11 +74,7 @@ api_v1_schedules_STR_PUT(struct http_message *hm, endpoint_args_t *args, endpoin
     if(json == NULL)
     {
         static const char content[] = "no valid json was supplied";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -179,11 +140,7 @@ api_v1_schedules_STR_PUT(struct http_message *hm, endpoint_args_t *args, endpoin
         cJSON_Delete(json);
 
         static const char content[] = "failed to save schedule to database";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 500, content, STRLEN(content));
         return;
     }
 
@@ -219,26 +176,7 @@ api_v1_schedules_STR_PUT(struct http_message *hm, endpoint_args_t *args, endpoin
     cJSON_Delete(json);
     json = schedule_to_json(schedule);
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print schedule json\n");
-
-        static const char content[] = "failed to print json for schedule";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     relay_free_list(relays);
     schedule_free(schedule);
@@ -257,11 +195,7 @@ api_v1_schedules_STR_DELETE(struct http_message *hm, endpoint_args_t *args, endp
         LOG_DEBUG("failed to unparse uid\n");
 
         static const char content[] = "given id was invalid";
-        response->status_code = 400;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 400, content, STRLEN(content));
         return;
     }
 
@@ -272,22 +206,14 @@ api_v1_schedules_STR_DELETE(struct http_message *hm, endpoint_args_t *args, endp
         LOG_DEBUG("could not find a schedule for uid '%s'\n", args[0].value.v_str);
 
         static const char content[] = "no schedule for id found";
-        response->status_code = 404;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 404, content, STRLEN(content));
         return;
     }
 
     if(schedule_is_protected(schedule))
     {
         static const char content[] = "target schedule is protected";
-        response->status_code = 403;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 403, content, STRLEN(content));
 
         schedule_free(schedule);
         return;
@@ -298,19 +224,11 @@ api_v1_schedules_STR_DELETE(struct http_message *hm, endpoint_args_t *args, endp
         LOG_ERROR("failed to remove schedule from database\n");
 
         static const char content[] = "failed to remove schedule from database";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 500, content, STRLEN(content));
     }
     else
     {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = 0;
-        response->content = "";
-        response->alloced_content = false;
+        endpoint_response_text(response, 200, "", 0);
     }
     schedule_free(schedule);
     return;
diff --git a/endpoints/api_v1_schedules_tag_STR.c b/endpoints/api_v1_schedules_tag_STR.c
index 82b14df..e5c5338 100644
--- a/endpoints/api_v1_schedules_tag_STR.c
+++ b/endpoints/api_v1_schedules_tag_STR.c
@@ -19,11 +19,7 @@ api_v1_schedules_tag_STR_GET(struct http_message *hm, endpoint_args_t *args, end
         LOG_ERROR("failed to load schedules for tag from database\n");
 
         static const char content[] = "failed to load schedules for tag from database";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
+        endpoint_response_text(response, 500, content, STRLEN(content));
         return;
     }
 
@@ -44,27 +40,7 @@ api_v1_schedules_tag_STR_GET(struct http_message *hm, endpoint_args_t *args, end
         schedule_free(schedule);
     }
 
-    char *json_str = cJSON_Print(json);
-    if (json_str == NULL)
-    {
-        LOG_ERROR("failed to print schedules json\n");
-
-        static const char content[] = "failed to print json for schedules";
-        response->status_code = 500;
-        response->content_type = "text/plain";
-        response->content_length = STRLEN(content);;
-        response->content = content;
-        response->alloced_content = false;
-    }
-    else
-    {
-        response->status_code = 200;
-        response->content_type = "application/json";
-        response->content_length = strlen(json_str);
-        response->content = json_str;
-        response->alloced_content = true;
-    }
-
+    endpoint_response_json(response, 200, json);
     cJSON_Delete(json);
     free(schedules_ids);
 }
diff --git a/include/endpoint.h b/include/endpoint.h
new file mode 100644
index 0000000..fbb4b10
--- /dev/null
+++ b/include/endpoint.h
@@ -0,0 +1,62 @@
+#ifndef CORE_ENDPOINT_H
+#define CORE_ENDPOINT_H
+
+#include <cJSON.h>
+
+typedef enum
+{
+    ENDPOINT_ARG_TYPE_INT,
+    ENDPOINT_ARG_TYPE_STR
+} endpoint_arg_type_e;
+
+typedef struct
+{
+    endpoint_arg_type_e type;
+    union
+    {
+        int v_int;
+        const char *v_str;
+    } value;
+} endpoint_args_t;
+
+typedef struct
+{
+    int status_code;
+    const char *content_type;
+    size_t content_length;
+    const char *content;
+    int alloced_content;
+} endpoint_response_t;
+
+typedef void (*endpoint_func_f)(struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response);
+
+typedef struct
+{
+    const char *full_route;
+    char **route;
+    char *route_keeper;
+    int method;
+    int options;
+    endpoint_func_f func;
+    int trailing_slash;
+
+    int args_count;
+    endpoint_args_t *args;
+
+    int possible_route;
+    int args_found;
+} endpoint_t;
+
+void
+endpoint_func_index(struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response);
+
+void
+endpoint_func_not_found(struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response);
+
+void
+endpoint_response_text(endpoint_response_t *response, int status_code, const char *content, int content_length);
+
+void
+endpoint_response_json(endpoint_response_t *response, int status_code, const cJSON *json_root);
+
+#endif /* CORE_ENDPOINT_H */
diff --git a/include/router.h b/include/router.h
index fe93032..b52ba89 100644
--- a/include/router.h
+++ b/include/router.h
@@ -2,14 +2,9 @@
 #define CORE_ROUTER_H
 
 #include <mongoose.h>
+#include <endpoint.h>
 
-#define ENDPOINTS_MAX_COUNT 128
-
-typedef enum
-{
-    ENDPOINT_ARG_TYPE_INT,
-    ENDPOINT_ARG_TYPE_STR
-} endpoint_arg_type_e;
+#define ROUTER_ENDPOINTS_MAX_COUNT 128
 
 typedef enum
 {
@@ -20,44 +15,6 @@ typedef enum
     HTTP_METHOD_OPTIONS = (1 << 4)
 } http_method_e;
 
-typedef struct
-{
-    endpoint_arg_type_e type;
-    union
-    {
-        int v_int;
-        const char *v_str;
-    } value;
-} endpoint_args_t;
-
-typedef struct
-{
-    int status_code;
-    const char *content_type;
-    size_t content_length;
-    const char *content;
-    int alloced_content;
-} endpoint_response_t;
-
-typedef void (*endpoint_func_f)(struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response);
-
-typedef struct
-{
-    const char *full_route;
-    char **route;
-    char *route_keeper;
-    int method;
-    int options;
-    endpoint_func_f func;
-    int trailing_slash;
-
-    int args_count;
-    endpoint_args_t *args;
-
-    int possible_route;
-    int args_found;
-} endpoint_t;
-
 void
 router_init();
 
diff --git a/router.c b/router.c
index 3a23b2c..bd4734f 100644
--- a/router.c
+++ b/router.c
@@ -3,45 +3,18 @@
 #include <logger.h>
 #include <router.h>
 #include <macros.h>
+#include <endpoint.h>
 
 #include <endpoints/api_v1_schedules.h>
 #include <endpoints/api_v1_controllers.h>
 #include <endpoints/api_v1_relays.h>
 
-static endpoint_t endpoints[ENDPOINTS_MAX_COUNT];
+static endpoint_t endpoints[ROUTER_ENDPOINTS_MAX_COUNT];
 static endpoint_t endpoint_index;
 static endpoint_t endpoint_not_found;
 static int endpoints_registered = 0;
 static const char delimiter[2] = "/";
 
-static void
-endpoint_index_func(struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response)
-{
-    (void)args;
-    (void)hm;
-
-    static const char content[] = "Emgauwa";
-    response->status_code = 200;
-    response->content_type = "text/plain";
-    response->content_length = STRLEN(content);;
-    response->content = content;
-    response->alloced_content = false;
-}
-
-static void
-endpoint_not_found_func(struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response)
-{
-    (void)args;
-    (void)hm;
-
-    static const char content[] = "404 - NOT FOUND";
-    response->status_code = 404;
-    response->content_type = "text/plain";
-    response->content_length = STRLEN(content);;
-    response->content = content;
-    response->alloced_content = false;
-}
-
 static struct mg_str
 get_method_str_for_int(int method_int)
 {
@@ -73,14 +46,14 @@ router_init()
 {
     // add index endpoint
     endpoint_index.route = NULL;
-    endpoint_index.func = endpoint_index_func;
+    endpoint_index.func = endpoint_func_index;
     endpoint_index.method = 0;
     endpoint_index.args_count = 0;
     endpoint_index.args = NULL;
 
     // add 404 endpoint
     endpoint_not_found.route = NULL;
-    endpoint_not_found.func = endpoint_not_found_func;
+    endpoint_not_found.func = endpoint_func_not_found;
     endpoint_not_found.method = 0;
     endpoint_not_found.args_count = 0;
     endpoint_not_found.args = NULL;
@@ -130,9 +103,9 @@ router_register_endpoint(const char *route, int method, endpoint_func_f func)
         }
     }
 
-    if(endpoints_registered >= ENDPOINTS_MAX_COUNT)
+    if(endpoints_registered >= ROUTER_ENDPOINTS_MAX_COUNT)
     {
-        LOG_ERROR("can't register more than %d endpoints\n", ENDPOINTS_MAX_COUNT);
+        LOG_ERROR("can't register more than %d endpoints\n", ROUTER_ENDPOINTS_MAX_COUNT);
         return NULL;
     }