diff --git a/include/endpoints/api_v1_tags.h b/include/endpoints/api_v1_tags.h
index fa716c8..0f68f20 100644
--- a/include/endpoints/api_v1_tags.h
+++ b/include/endpoints/api_v1_tags.h
@@ -6,4 +6,10 @@
 void
 api_v1_tags_GET(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response);
 
+void
+api_v1_tags_STR_GET(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response);
+
+void
+api_v1_tags_STR_DELETE(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response);
+
 #endif /* CORE_ENDPOINTS_API_V1_TAGS_H */
diff --git a/src/endpoints/api_v1_relays_tag_STR.c b/src/endpoints/api_v1_relays_tag_STR.c
index d21a47b..cbe554e 100644
--- a/src/endpoints/api_v1_relays_tag_STR.c
+++ b/src/endpoints/api_v1_relays_tag_STR.c
@@ -14,6 +14,12 @@ api_v1_relays_tag_STR_GET(struct mg_connection *nc, struct http_message *hm, end
     (void)nc;
 
     int tag_id = tag_get_id(args[0].value.v_str);
+    if(tag_id == 0)
+    {
+        static const char content[] = "tag was not found";
+        endpoint_response_text(response, 404, content, STRLEN(content));
+        return;
+    }
     int *relays_ids = junction_tag_get_relays_for_tag_id(tag_id);
     if(relays_ids == NULL)
     {
diff --git a/src/endpoints/api_v1_schedules_tag_STR.c b/src/endpoints/api_v1_schedules_tag_STR.c
index 0cc38ab..3cbf403 100644
--- a/src/endpoints/api_v1_schedules_tag_STR.c
+++ b/src/endpoints/api_v1_schedules_tag_STR.c
@@ -14,6 +14,12 @@ api_v1_schedules_tag_STR_GET(struct mg_connection *nc, struct http_message *hm,
     (void)nc;
 
     int tag_id = tag_get_id(args[0].value.v_str);
+    if(tag_id == 0)
+    {
+        static const char content[] = "tag was not found";
+        endpoint_response_text(response, 404, content, STRLEN(content));
+        return;
+    }
     int *schedules_ids = junction_tag_get_schedules_for_tag_id(tag_id);
     if(schedules_ids == NULL)
     {
diff --git a/src/endpoints/api_v1_tags_STR.c b/src/endpoints/api_v1_tags_STR.c
new file mode 100644
index 0000000..ddac57f
--- /dev/null
+++ b/src/endpoints/api_v1_tags_STR.c
@@ -0,0 +1,110 @@
+#include <cJSON.h>
+#include <macros.h>
+#include <constants.h>
+#include <endpoints/api_v1_tags.h>
+#include <logger.h>
+#include <models/junction_tag.h>
+#include <models/relay.h>
+#include <models/tag.h>
+
+void
+api_v1_tags_STR_GET(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response)
+{
+    (void)hm;
+    (void)nc;
+
+    int tag_id = tag_get_id(args[0].value.v_str);
+    if(tag_id == 0)
+    {
+        static const char content[] = "tag was not found";
+        endpoint_response_text(response, 404, content, STRLEN(content));
+        return;
+    }
+    int *relays_ids = junction_tag_get_relays_for_tag_id(tag_id);
+    if(relays_ids == NULL)
+    {
+        LOG_ERROR("failed to load relays for tag from database\n");
+
+        static const char content[] = "failed to load relays for tag from database";
+        endpoint_response_text(response, 500, content, STRLEN(content));
+        return;
+    }
+    int *schedules_ids = junction_tag_get_schedules_for_tag_id(tag_id);
+    if(schedules_ids == NULL)
+    {
+        LOG_ERROR("failed to load schedules for tag from database\n");
+
+        static const char content[] = "failed to load schedules for tag from database";
+        endpoint_response_text(response, 500, content, STRLEN(content));
+        return;
+    }
+
+    cJSON *json = cJSON_CreateObject();
+
+    cJSON *json_relays = cJSON_CreateArray();
+    cJSON *json_schedules = cJSON_CreateArray();
+
+    for(int i = 0; relays_ids[i] != 0; ++i)
+    {
+        relay_t* relay = relay_get_by_id(relays_ids[i]);
+
+        if(!relay)
+        {
+            continue;
+        }
+        cJSON *json_relay = relay_to_json(relay);
+
+        cJSON_AddItemToArray(json_relays, json_relay);
+
+        relay_free(relay);
+    }
+    for(int i = 0; schedules_ids[i] != 0; ++i)
+    {
+        schedule_t* schedule = schedule_get_by_id(schedules_ids[i]);
+
+        if(!schedule)
+        {
+            continue;
+        }
+        cJSON *json_schedule = schedule_to_json(schedule);
+
+        cJSON_AddItemToArray(json_schedules, json_schedule);
+
+        schedule_free(schedule);
+    }
+
+    cJSON_AddItemToObject(json, "relays", json_relays);
+    cJSON_AddItemToObject(json, "schedules", json_schedules);
+
+    endpoint_response_json(response, 200, json);
+    cJSON_Delete(json);
+    free(relays_ids);
+    free(schedules_ids);
+}
+
+void
+api_v1_tags_STR_DELETE(struct mg_connection *nc, struct http_message *hm, endpoint_args_t *args, endpoint_response_t *response)
+{
+    (void)hm;
+    (void)nc;
+
+    int tag_id = tag_get_id(args[0].value.v_str);
+    if(tag_id == 0)
+    {
+        static const char content[] = "tag was not found";
+        endpoint_response_text(response, 404, content, STRLEN(content));
+        return;
+    }
+
+    if(tag_remove(tag_id))
+    {
+        LOG_ERROR("failed to remove tag from database\n");
+
+        static const char content[] = "failed to remove tag from database";
+        endpoint_response_text(response, 500, content, STRLEN(content));
+    }
+    else
+    {
+        endpoint_response_text(response, 200, "", 0);
+    }
+}
diff --git a/src/models/tag.c b/src/models/tag.c
index fda995e..1e91e16 100644
--- a/src/models/tag.c
+++ b/src/models/tag.c
@@ -172,6 +172,6 @@ tag_remove(int id)
     rc = sqlite3_step(stmt);
     sqlite3_finalize(stmt);
 
-    return rc == SQLITE_DONE;
+    return rc != SQLITE_DONE;
 }
 
diff --git a/src/router.c b/src/router.c
index 925477b..d920eef 100644
--- a/src/router.c
+++ b/src/router.c
@@ -79,6 +79,8 @@ router_init()
     router_register_endpoint("/api/v1/relays/tag/{str}", HTTP_METHOD_GET, api_v1_relays_tag_STR_GET);
 
     router_register_endpoint("/api/v1/tags/", HTTP_METHOD_GET, api_v1_tags_GET);
+    router_register_endpoint("/api/v1/tags/{str}", HTTP_METHOD_GET, api_v1_tags_STR_GET);
+    router_register_endpoint("/api/v1/tags/{str}", HTTP_METHOD_DELETE, api_v1_tags_STR_DELETE);
 }
 
 endpoint_t*