diff --git a/Controllers/CategoryController.cs b/Controllers/CategoryController.cs
new file mode 100644
index 0000000..ae1f520
--- /dev/null
+++ b/Controllers/CategoryController.cs
@@ -0,0 +1,111 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using QuotifyBE.Data;
+using QuotifyBE.Entities;
+using QuotifyBE.DTOs;
+using System.Threading.Tasks;
+using QuotifyBE.Mapping;
+using Microsoft.AspNetCore.Cors;
+using Microsoft.EntityFrameworkCore;
+
+namespace QuotifyBE.Controllers;
+
+
+[ApiController]
+[EnableCors]
+[Route("api/v1/categories")]
+[Produces("application/json")]
+public class CategoryController : ControllerBase
+{
+
+ private readonly ApplicationDbContext _db;
+ private readonly GeneralUseHelpers guhf;
+
+ public CategoryController(ApplicationDbContext db, GeneralUseHelpers GUHF)
+ {
+ _db = db;
+ guhf = GUHF;
+ }
+
+ // GET /api/v1/categories
+ ///
+ /// Get every category
+ ///
+ ///
+ /// Can (and will) return an empty list if no categories are found in DB.
+ /// Has CORS set.
+ ///
+ /// Returned on valid request
+ // /// Returned when there are no categories to list
+ [HttpGet]
+ [EnableCors]
+ [ProducesResponseType(typeof(CategoryShortDTO), 200)]
+ // [ProducesResponseType(typeof(ErrorDTO), 404)]
+ public async Task GetQuotePage()
+ {
+ // The following seems to be a bad idea, so I leave it as is. ~eee4
+ //
+ // int totalCategories = await _db.Categories.CountAsync();
+ //
+ // if (totalCategories <= 0)
+ // {
+ // return NotFound(new ErrorDTO { Status = "error", Error_msg = "No categories to list" });
+ // }
+
+ // Get all the categories
+ List categories = await _db.Categories
+ .ToListAsync();
+
+ // Convert them to a list of DTO
+ List result = categories
+ .Select(c => c.ToCategoryShortDTO())
+ .ToList();
+
+ // Return to user
+ return Ok(result);
+
+ }
+
+ // POST /api/v1/categories
+ ///
+ /// [AUTHED] Create a new category
+ ///
+ ///
+ /// Allows authorized users to create categories.
+ /// Important! Category names are case insensitive.
+ /// Has CORS set.
+ ///
+ /// Returned on valid request
+ /// Returned when such category already exists (case insensitive)
+ [HttpPost]
+ [Authorize]
+ [EnableCors]
+ [ProducesResponseType(typeof(CategoryShortDTO), 200)]
+ [ProducesResponseType(typeof(ErrorDTO), 406)]
+ public async Task PostNewCategory([FromBody] NewCategoryDTO formCategory)
+ {
+ // Check if such category doesn't already exist
+ Category? cat = await _db.Categories.FirstOrDefaultAsync(c => c.Name.ToLower() == formCategory.Name.ToLower());
+ if (cat != null)
+ {
+ return StatusCode(406, new ErrorDTO { Status = "error", Error_msg = "This category already exists" });
+ }
+
+ // Create new category
+ cat = new Category
+ {
+ Name = formCategory.Name,
+ Description = formCategory.Description,
+ CreatedAt = DateTime.UtcNow
+ };
+
+ // Add to DB
+ await _db.Categories.AddAsync(cat);
+ await _db.SaveChangesAsync();
+
+ // And send back to the user as DTO
+ return Ok(cat.ToCategoryShortDTO());
+
+ }
+
+}
diff --git a/DTOs/NewCategoryDTO.cs b/DTOs/NewCategoryDTO.cs
new file mode 100644
index 0000000..7ac97e4
--- /dev/null
+++ b/DTOs/NewCategoryDTO.cs
@@ -0,0 +1,6 @@
+namespace QuotifyBE.DTOs;
+public class NewCategoryDTO
+{
+ public string Name { get; set; } = string.Empty;
+ public string? Description { get; set; }
+}
diff --git a/Mapping/CategoryMapping.cs b/Mapping/CategoryMapping.cs
new file mode 100644
index 0000000..b4feaad
--- /dev/null
+++ b/Mapping/CategoryMapping.cs
@@ -0,0 +1,19 @@
+using QuotifyBE.DTOs;
+using QuotifyBE.Entities;
+
+namespace QuotifyBE.Mapping;
+
+public static class CategoryMapping
+{
+ public static CategoryShortDTO ToCategoryShortDTO(this Category category)
+ {
+
+ return new CategoryShortDTO
+ {
+ Id = category.Id,
+ Name = category.Name,
+ Description = category.Description,
+ CreatedAt = category.CreatedAt
+ };
+ }
+}