diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b8d7560..bd84094a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## Unreleased
 
-### Conforming to API v3
+### Added
+
+- [Springdoc](https://springdoc.org) library, to enrich the project with two new features:
+  - Generation of an OpenAPI 3.0 spec file, akin to [the Trebol API](https://github.com/trebol-ecommerce/api)'s
+  - Generation of a [Swagger UI](https://swagger.io/tools/swagger-ui/) page and endpoint.
+
+### Changed
+
+#### Conforming to API v3
 
   - Follow new specification for error messages
     - Introduce new model class `AppError`
@@ -68,6 +76,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
     - All PUT,PATCH,DELETE,OPTIONS requests return 204
   - Remove duplicated functionality endpoint `/public/checkout/result/{token}`
     - Served the same purpose as `/public/receipt/{token}`
+  - Remove support for paths with leading slash
+    - For example, `/public/checkout/` is no longer accepted, only `/public/checkout`
 
 ## [v0.2.4] - 2024-08-28
 
diff --git a/pom.xml b/pom.xml
index 37cb2734..377cdd8e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -157,6 +157,11 @@
       <artifactId>unirest-java</artifactId>
       <version>${unirest.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.springdoc</groupId>
+      <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+      <version>2.6.0</version>
+    </dependency>
 
     <!-- Testing -->
     <dependency>
diff --git a/src/main/java/org/trebol/api/controllers/AccessController.java b/src/main/java/org/trebol/api/controllers/AccessController.java
index f13f54e8..c3cd2096 100644
--- a/src/main/java/org/trebol/api/controllers/AccessController.java
+++ b/src/main/java/org/trebol/api/controllers/AccessController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import io.jsonwebtoken.Claims;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -46,6 +48,7 @@
 
 @RestController
 @RequestMapping("/access")
+@Tag(name = "User Accounts")
 @PreAuthorize("isAuthenticated()")
 public class AccessController {
     private final AuthorizationHeaderParserService<Claims> jwtClaimsParserService;
@@ -66,7 +69,8 @@ public AccessController(
         this.regexMatcherService = regexMatcherService;
     }
 
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List authorized API routes")
     public AuthorizedAccessPojo getApiRoutesAccess(@RequestHeader HttpHeaders requestHeaders)
         throws UsernameNotFoundException, IllegalStateException {
         UserDetails userDetails = this.getUserDetails(requestHeaders);
@@ -79,7 +83,8 @@ public AuthorizedAccessPojo getApiRoutesAccess(@RequestHeader HttpHeaders reques
             .build();
     }
 
-    @GetMapping({"/{apiRoute}", "/{apiRoute}/"})
+    @GetMapping("/{apiRoute}")
+    @Operation(summary = "List authorized access to API route")
     public AuthorizedAccessPojo getApiResourceAccess(
         @RequestHeader HttpHeaders requestHeaders,
         @PathVariable String apiRoute)
diff --git a/src/main/java/org/trebol/api/controllers/AccountProfileController.java b/src/main/java/org/trebol/api/controllers/AccountProfileController.java
index fe83bcf0..acd0a8af 100644
--- a/src/main/java/org/trebol/api/controllers/AccountProfileController.java
+++ b/src/main/java/org/trebol/api/controllers/AccountProfileController.java
@@ -20,6 +20,8 @@
 
 package org.trebol.api.controllers;
 
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -36,6 +38,7 @@
 
 @RestController
 @RequestMapping("/account/profile")
+@Tag(name = "User Accounts")
 @PreAuthorize("isAuthenticated()")
 public class AccountProfileController {
     private final ProfileService userProfileService;
@@ -47,14 +50,16 @@ public AccountProfileController(
         this.userProfileService = userProfileService;
     }
 
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "View stored profile information")
     public PersonPojo getProfile(Principal principal)
         throws EntityNotFoundException {
         String username = principal.getName();
         return userProfileService.getProfileFromUserName(username);
     }
 
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace stored profile information")
     public void updateProfile(Principal principal, @RequestBody PersonPojo newProfile)
         throws EntityNotFoundException, BadInputException {
         String username = principal.getName();
diff --git a/src/main/java/org/trebol/api/controllers/DataBillingTypesController.java b/src/main/java/org/trebol/api/controllers/DataBillingTypesController.java
index 5ca68511..b826c3c8 100644
--- a/src/main/java/org/trebol/api/controllers/DataBillingTypesController.java
+++ b/src/main/java/org/trebol/api/controllers/DataBillingTypesController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -40,6 +42,7 @@
 
 @RestController
 @RequestMapping("/data/billing_types")
+@Tag(name = "Params management")
 public class DataBillingTypesController
     extends DataGenericController<BillingTypePojo, BillingType> {
 
@@ -54,7 +57,8 @@ public DataBillingTypesController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List billing types.")
     public DataPagePojo<BillingTypePojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
     }
diff --git a/src/main/java/org/trebol/api/controllers/DataCustomersController.java b/src/main/java/org/trebol/api/controllers/DataCustomersController.java
index 7a0ce1b6..0b3a7019 100644
--- a/src/main/java/org/trebol/api/controllers/DataCustomersController.java
+++ b/src/main/java/org/trebol/api/controllers/DataCustomersController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -45,6 +47,7 @@
 
 @RestController
 @RequestMapping("/data/customers")
+@Tag(name = "People management")
 @PreAuthorize("isAuthenticated()")
 public class DataCustomersController
     extends DataCrudGenericController<PersonPojo, Customer> {
@@ -60,14 +63,16 @@ public DataCustomersController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List customers.")
     @PreAuthorize("hasAuthority('customers:read')")
     public DataPagePojo<PersonPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Register new customer.")
     @PreAuthorize("hasAuthority('customers:create')")
     @ResponseStatus(CREATED)
     public void create(@Valid @RequestBody PersonPojo input)
@@ -76,7 +81,8 @@ public void create(@Valid @RequestBody PersonPojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace customers data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('customers:update')")
     public void update(@Valid @RequestBody PersonPojo input, @RequestParam Map<String, String> requestParams)
@@ -85,7 +91,8 @@ public void update(@Valid @RequestBody PersonPojo input, @RequestParam Map<Strin
     }
 
     @Override
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Deregister customers.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('customers:delete')")
     public void delete(Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/DataImagesController.java b/src/main/java/org/trebol/api/controllers/DataImagesController.java
index b55ad28a..a0a22fb2 100644
--- a/src/main/java/org/trebol/api/controllers/DataImagesController.java
+++ b/src/main/java/org/trebol/api/controllers/DataImagesController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -54,6 +56,7 @@
 
 @RestController
 @RequestMapping("/data/images")
+@Tag(name = "Images management")
 @PreAuthorize("isAuthenticated()")
 public class DataImagesController
     extends DataCrudGenericController<ImagePojo, Image> {
@@ -69,14 +72,16 @@ public DataImagesController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List image links data.")
     @PreAuthorize("hasAuthority('images:read')")
     public DataPagePojo<ImagePojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Define new image links.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('images:create')")
     public void create(@Valid @RequestBody ImagePojo input)
@@ -85,7 +90,8 @@ public void create(@Valid @RequestBody ImagePojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace image links data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('images:update')")
     public void update(@Valid @RequestBody ImagePojo input, @RequestParam Map<String, String> requestParams)
@@ -94,7 +100,8 @@ public void update(@Valid @RequestBody ImagePojo input, @RequestParam Map<String
     }
 
     @Override
-    @PatchMapping({"", "/"})
+    @PatchMapping
+    @Operation(summary = "Update parts of image links data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('images:update')")
     public void partialUpdate(
@@ -105,7 +112,8 @@ public void partialUpdate(
     }
 
     @Override
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Remove image links.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('images:delete')")
     public void delete(@RequestParam Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/DataOrderStatusesController.java b/src/main/java/org/trebol/api/controllers/DataOrderStatusesController.java
index 81f835d0..e2dee329 100644
--- a/src/main/java/org/trebol/api/controllers/DataOrderStatusesController.java
+++ b/src/main/java/org/trebol/api/controllers/DataOrderStatusesController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -41,6 +43,7 @@
 
 @RestController
 @RequestMapping("/data/order_statuses")
+@Tag(name = "Params management")
 @PreAuthorize("isAuthenticated()")
 public class DataOrderStatusesController
     extends DataGenericController<OrderStatusPojo, OrderStatus> {
@@ -56,7 +59,8 @@ public DataOrderStatusesController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List order statuses.")
     @PreAuthorize("hasAuthority('order_statuses:read')")
     public DataPagePojo<OrderStatusPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
diff --git a/src/main/java/org/trebol/api/controllers/DataOrdersController.java b/src/main/java/org/trebol/api/controllers/DataOrdersController.java
index e1daf6e8..c2447624 100644
--- a/src/main/java/org/trebol/api/controllers/DataOrdersController.java
+++ b/src/main/java/org/trebol/api/controllers/DataOrdersController.java
@@ -22,6 +22,8 @@
 
 import com.querydsl.core.types.OrderSpecifier;
 import com.querydsl.core.types.Predicate;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.lang.Nullable;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -61,6 +63,7 @@
 
 @RestController
 @RequestMapping("/data/orders")
+@Tag(name = "Orders management")
 @PreAuthorize("isAuthenticated()")
 public class DataOrdersController
     extends DataCrudGenericController<OrderPojo, Order> {
@@ -83,7 +86,8 @@ public DataOrdersController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List orders.")
     @PreAuthorize("hasAuthority('orders:read')")
     public DataPagePojo<OrderPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         if (allRequestParams!=null) {
@@ -106,7 +110,8 @@ public DataPagePojo<OrderPojo> readMany(@RequestParam Map<String, String> allReq
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Create new orders.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('orders:create')")
     public void create(@Valid @RequestBody OrderPojo input)
@@ -115,7 +120,8 @@ public void create(@Valid @RequestBody OrderPojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace orders data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('orders:update')")
     public void update(@Valid @RequestBody OrderPojo input, @RequestParam Map<String, String> requestParams)
@@ -124,7 +130,8 @@ public void update(@Valid @RequestBody OrderPojo input, @RequestParam Map<String
     }
 
     @Override
-    @PatchMapping({"", "/"})
+    @PatchMapping
+    @Operation(summary = "Update parts of orders data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('orders:update')")
     public void partialUpdate(
@@ -135,7 +142,8 @@ public void partialUpdate(
     }
 
     @Override
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Remove orders.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('orders:delete')")
     public void delete(@RequestParam Map<String, String> requestParams)
@@ -143,7 +151,8 @@ public void delete(@RequestParam Map<String, String> requestParams)
         super.delete(requestParams);
     }
 
-    @PostMapping({"/confirmation", "/confirmation/"})
+    @PostMapping("/confirmation")
+    @Operation(summary = "Confirm a pending order.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('orders:update')")
     public void confirmSell(@RequestBody OrderPojo sell)
@@ -155,7 +164,8 @@ public void confirmSell(@RequestBody OrderPojo sell)
         }
     }
 
-    @PostMapping({"/rejection", "/rejection/"})
+    @PostMapping("/rejection")
+    @Operation(summary = "Reject a pending order.")
     @PreAuthorize("hasAuthority('orders:update')")
     public void rejectSell(@RequestBody OrderPojo sell)
         throws BadInputException, MailingServiceException {
@@ -165,7 +175,8 @@ public void rejectSell(@RequestBody OrderPojo sell)
         }
     }
 
-    @PostMapping({"/completion", "/completion/"})
+    @PostMapping("/completion")
+    @Operation(summary = "Mark an order as completed.")
     @PreAuthorize("hasAuthority('orders:update')")
     public void completeSell(@RequestBody OrderPojo sell)
         throws BadInputException, MailingServiceException {
diff --git a/src/main/java/org/trebol/api/controllers/DataPeopleController.java b/src/main/java/org/trebol/api/controllers/DataPeopleController.java
index f2cfb03c..c7f99254 100644
--- a/src/main/java/org/trebol/api/controllers/DataPeopleController.java
+++ b/src/main/java/org/trebol/api/controllers/DataPeopleController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -41,6 +43,7 @@
 
 @RestController
 @RequestMapping("/data/people")
+@Tag(name = "People management")
 @PreAuthorize("isAuthenticated()")
 public class DataPeopleController
     extends DataGenericController<PersonPojo, Person> {
@@ -56,7 +59,8 @@ public DataPeopleController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List people.")
     @PreAuthorize("hasAuthority('people:read')")
     public DataPagePojo<PersonPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
diff --git a/src/main/java/org/trebol/api/controllers/DataProductCategoriesController.java b/src/main/java/org/trebol/api/controllers/DataProductCategoriesController.java
index c3fc359e..512008e6 100644
--- a/src/main/java/org/trebol/api/controllers/DataProductCategoriesController.java
+++ b/src/main/java/org/trebol/api/controllers/DataProductCategoriesController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -54,6 +56,7 @@
 
 @RestController
 @RequestMapping("/data/product_categories")
+@Tag(name = "Product Categories management")
 public class DataProductCategoriesController
     extends DataCrudGenericController<ProductCategoryPojo, ProductCategory> {
 
@@ -68,7 +71,8 @@ public DataProductCategoriesController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List product categories.")
     public DataPagePojo<ProductCategoryPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         if (allRequestParams==null || allRequestParams.isEmpty()) {
             allRequestParams = Map.of("parentId", "");
@@ -77,7 +81,8 @@ public DataPagePojo<ProductCategoryPojo> readMany(@RequestParam Map<String, Stri
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Define new product categories.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('product_categories:create')")
     public void create(@Valid @RequestBody ProductCategoryPojo input)
@@ -86,7 +91,8 @@ public void create(@Valid @RequestBody ProductCategoryPojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace product categories data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('product_categories:update')")
     public void update(@Valid @RequestBody ProductCategoryPojo input, @RequestParam Map<String, String> requestParams)
@@ -95,7 +101,8 @@ public void update(@Valid @RequestBody ProductCategoryPojo input, @RequestParam
     }
 
     @Override
-    @PatchMapping({"", "/"})
+    @PatchMapping
+    @Operation(summary = "Update parts of product categories data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('product_categories:update')")
     public void partialUpdate(
@@ -106,7 +113,8 @@ public void partialUpdate(
     }
 
     @Override
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Remove product categories.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('product_categories:delete')")
     public void delete(@RequestParam Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/DataProductListContentsController.java b/src/main/java/org/trebol/api/controllers/DataProductListContentsController.java
index f2e6dba9..d71cebbf 100644
--- a/src/main/java/org/trebol/api/controllers/DataProductListContentsController.java
+++ b/src/main/java/org/trebol/api/controllers/DataProductListContentsController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.Predicate;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Example;
@@ -68,6 +70,7 @@
 
 @RestController
 @RequestMapping("/data/product_list_contents")
+@Tag(name = "Product Lists management")
 public class DataProductListContentsController {
     private static final String ITEM_NOT_FOUND = "Requested item(s) not found";
     private final PaginationService paginationService;
@@ -97,7 +100,8 @@ public DataProductListContentsController(
         this.itemConverterService = itemConverterService;
     }
 
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "View contents of product lists.")
     public DataPagePojo<ProductPojo> readContents(@RequestParam Map<String, String> requestParams)
         throws BadInputException, EntityNotFoundException {
         Optional<ProductList> match = this.fetchProductListByCode(requestParams);
@@ -128,7 +132,8 @@ public DataPagePojo<ProductPojo> readContents(@RequestParam Map<String, String>
         return new DataPagePojo<>(products, pageIndex, totalCount, pageSize);
     }
 
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Add products to lists.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('product_lists:contents')")
     public void addToContents(@Valid @RequestBody ProductPojo input,
@@ -151,7 +156,8 @@ public void addToContents(@Valid @RequestBody ProductPojo input,
         }
     }
 
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Fully replace contents of product lists.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('product_lists:contents')")
     public void updateContents(@RequestBody Collection<ProductPojo> input,
@@ -177,7 +183,8 @@ public void updateContents(@RequestBody Collection<ProductPojo> input,
         }
     }
 
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Remove products from lists.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('product_lists:contents')")
     public void deleteFromContents(@RequestParam Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/DataProductListsController.java b/src/main/java/org/trebol/api/controllers/DataProductListsController.java
index 2c63068b..74993d84 100644
--- a/src/main/java/org/trebol/api/controllers/DataProductListsController.java
+++ b/src/main/java/org/trebol/api/controllers/DataProductListsController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -54,6 +56,7 @@
 
 @RestController
 @RequestMapping("/data/product_lists")
+@Tag(name = "Product Lists management")
 public class DataProductListsController
     extends DataCrudGenericController<ProductListPojo, ProductList> {
 
@@ -68,13 +71,15 @@ public DataProductListsController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "View product lists.")
     public DataPagePojo<ProductListPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Define new product lists.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('product_lists:create')")
     public void create(@Valid @RequestBody ProductListPojo input)
@@ -83,7 +88,8 @@ public void create(@Valid @RequestBody ProductListPojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace product lists data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('product_lists:update')")
     public void update(@Valid @RequestBody ProductListPojo input, @RequestParam Map<String, String> requestParams)
@@ -92,7 +98,8 @@ public void update(@Valid @RequestBody ProductListPojo input, @RequestParam Map<
     }
 
     @Override
-    @PatchMapping({"", "/"})
+    @PatchMapping
+    @Operation(summary = "Update parts of product lists data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('product_lists:update')")
     public void partialUpdate(
@@ -103,7 +110,8 @@ public void partialUpdate(
     }
 
     @Override
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Remove product lists.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('product_lists:delete')")
     public void delete(@RequestParam Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/DataProductsController.java b/src/main/java/org/trebol/api/controllers/DataProductsController.java
index b4837c0a..35bdeb41 100644
--- a/src/main/java/org/trebol/api/controllers/DataProductsController.java
+++ b/src/main/java/org/trebol/api/controllers/DataProductsController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -54,6 +56,7 @@
 
 @RestController
 @RequestMapping("/data/products")
+@Tag(name = "Products management")
 public class DataProductsController
     extends DataCrudGenericController<ProductPojo, Product> {
 
@@ -68,13 +71,15 @@ public DataProductsController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List products.")
     public DataPagePojo<ProductPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Define new products.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('products:create')")
     public void create(@Valid @RequestBody ProductPojo input)
@@ -83,7 +88,8 @@ public void create(@Valid @RequestBody ProductPojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace products data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('products:update')")
     public void update(@Valid @RequestBody ProductPojo input, @RequestParam Map<String, String> requestParams)
@@ -92,7 +98,8 @@ public void update(@Valid @RequestBody ProductPojo input, @RequestParam Map<Stri
     }
 
     @Override
-    @PatchMapping({"", "/"})
+    @PatchMapping
+    @Operation(summary = "Update parts of products data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('products:update')")
     public void partialUpdate(
@@ -103,7 +110,8 @@ public void partialUpdate(
     }
 
     @Override
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Remove products.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('products:delete')")
     public void delete(@RequestParam Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/DataSalespeopleController.java b/src/main/java/org/trebol/api/controllers/DataSalespeopleController.java
index 38b99e9b..c4c466a5 100644
--- a/src/main/java/org/trebol/api/controllers/DataSalespeopleController.java
+++ b/src/main/java/org/trebol/api/controllers/DataSalespeopleController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -53,6 +55,7 @@
 
 @RestController
 @RequestMapping("/data/salespeople")
+@Tag(name = "People management")
 @PreAuthorize("isAuthenticated()")
 public class DataSalespeopleController
     extends DataCrudGenericController<PersonPojo, Salesperson> {
@@ -68,14 +71,16 @@ public DataSalespeopleController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List salespeople.")
     @PreAuthorize("hasAuthority('salespeople:read')")
     public DataPagePojo<PersonPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Register new salespeople.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('salespeople:create')")
     public void create(@Valid @RequestBody PersonPojo input)
@@ -84,7 +89,8 @@ public void create(@Valid @RequestBody PersonPojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace salespeople data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('salespeople:update')")
     public void update(@Valid @RequestBody PersonPojo input, @RequestParam Map<String, String> requestParams)
@@ -93,7 +99,8 @@ public void update(@Valid @RequestBody PersonPojo input, @RequestParam Map<Strin
     }
 
     @Override
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Deregister salespeople.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('salespeople:delete')")
     public void delete(@RequestParam Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/DataShippersController.java b/src/main/java/org/trebol/api/controllers/DataShippersController.java
index 07a4ad49..6a44e3f0 100644
--- a/src/main/java/org/trebol/api/controllers/DataShippersController.java
+++ b/src/main/java/org/trebol/api/controllers/DataShippersController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -54,6 +56,7 @@
 
 @RestController
 @RequestMapping("/data/shippers")
+@Tag(name = "Shippers management")
 public class DataShippersController
     extends DataCrudGenericController<ShipperPojo, Shipper> {
 
@@ -68,13 +71,15 @@ public DataShippersController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List shippers.")
     public DataPagePojo<ShipperPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Define new shippers.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('shippers:create')")
     public void create(@Valid @RequestBody ShipperPojo input)
@@ -83,7 +88,8 @@ public void create(@Valid @RequestBody ShipperPojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace shippers data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('shippers:update')")
     public void update(@Valid @RequestBody ShipperPojo input, @RequestParam Map<String, String> requestParams)
@@ -92,7 +98,8 @@ public void update(@Valid @RequestBody ShipperPojo input, @RequestParam Map<Stri
     }
 
     @Override
-    @PatchMapping({"", "/"})
+    @PatchMapping
+    @Operation(summary = "Update parts of shippers data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('shippers:update')")
     public void partialUpdate(
@@ -103,7 +110,8 @@ public void partialUpdate(
     }
 
     @Override
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Remove shippers.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('shippers:delete')")
     public void delete(@RequestParam Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/DataUserRolesController.java b/src/main/java/org/trebol/api/controllers/DataUserRolesController.java
index 433849c0..3b16e800 100644
--- a/src/main/java/org/trebol/api/controllers/DataUserRolesController.java
+++ b/src/main/java/org/trebol/api/controllers/DataUserRolesController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -53,6 +55,7 @@
 
 @RestController
 @RequestMapping("/data/user_roles")
+@Tag(name = "Params management")
 @PreAuthorize("isAuthenticated()")
 public class DataUserRolesController
     extends DataCrudGenericController<UserRolePojo, UserRole> {
@@ -68,14 +71,16 @@ public DataUserRolesController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List user roles.")
     @PreAuthorize("hasAuthority('user_roles:read')")
     public DataPagePojo<UserRolePojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Define new user roles.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('user_roles:create')")
     public void create(@Valid @RequestBody UserRolePojo input)
@@ -84,7 +89,8 @@ public void create(@Valid @RequestBody UserRolePojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace user roles data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('user_roles:update')")
     public void update(@Valid @RequestBody UserRolePojo input, @RequestParam Map<String, String> requestParams)
@@ -93,7 +99,8 @@ public void update(@Valid @RequestBody UserRolePojo input, @RequestParam Map<Str
     }
 
     @Override
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Remove user roles.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('user_roles:delete')")
     public void delete(@RequestParam Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/DataUsersController.java b/src/main/java/org/trebol/api/controllers/DataUsersController.java
index 13661c98..bf199e5a 100644
--- a/src/main/java/org/trebol/api/controllers/DataUsersController.java
+++ b/src/main/java/org/trebol/api/controllers/DataUsersController.java
@@ -21,6 +21,8 @@
 package org.trebol.api.controllers;
 
 import com.querydsl.core.types.OrderSpecifier;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -54,6 +56,7 @@
 
 @RestController
 @RequestMapping("/data/users")
+@Tag(name = "Users management")
 @PreAuthorize("isAuthenticated()")
 public class DataUsersController
     extends DataCrudGenericController<UserPojo, User> {
@@ -69,14 +72,16 @@ public DataUsersController(
     }
 
     @Override
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "List users.")
     @PreAuthorize("hasAuthority('users:read')")
     public DataPagePojo<UserPojo> readMany(@RequestParam Map<String, String> allRequestParams) {
         return super.readMany(allRequestParams);
     }
 
     @Override
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Register new users.")
     @ResponseStatus(CREATED)
     @PreAuthorize("hasAuthority('users:create')")
     public void create(@Valid @RequestBody UserPojo input)
@@ -85,7 +90,8 @@ public void create(@Valid @RequestBody UserPojo input)
     }
 
     @Override
-    @PutMapping({"", "/"})
+    @PutMapping
+    @Operation(summary = "Replace users data.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('users:update')")
     public void update(@Valid @RequestBody UserPojo input, @RequestParam Map<String, String> requestParams)
@@ -93,7 +99,8 @@ public void update(@Valid @RequestBody UserPojo input, @RequestParam Map<String,
         super.update(input, requestParams);
     }
 
-    @DeleteMapping({"", "/"})
+    @DeleteMapping
+    @Operation(summary = "Remove users.")
     @ResponseStatus(NO_CONTENT)
     @PreAuthorize("hasAuthority('users:delete')")
     public void delete(Principal principal, @RequestParam Map<String, String> requestParams)
diff --git a/src/main/java/org/trebol/api/controllers/PublicAboutController.java b/src/main/java/org/trebol/api/controllers/PublicAboutController.java
index eee7af27..28836fb8 100644
--- a/src/main/java/org/trebol/api/controllers/PublicAboutController.java
+++ b/src/main/java/org/trebol/api/controllers/PublicAboutController.java
@@ -20,6 +20,8 @@
 
 package org.trebol.api.controllers;
 
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -29,6 +31,7 @@
 
 @RestController
 @RequestMapping("/public/about")
+@Tag(name = "About")
 public class PublicAboutController {
 
     private final CompanyService companyService;
@@ -38,7 +41,8 @@ public PublicAboutController(CompanyService companyService) {
         this.companyService = companyService;
     }
 
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "View information useful to customers regarding the business.")
     public CompanyDetailsPojo readCompanyDetails() {
         return companyService.readDetails();
     }
diff --git a/src/main/java/org/trebol/api/controllers/PublicCheckoutController.java b/src/main/java/org/trebol/api/controllers/PublicCheckoutController.java
index 3f538d3c..671fe865 100644
--- a/src/main/java/org/trebol/api/controllers/PublicCheckoutController.java
+++ b/src/main/java/org/trebol/api/controllers/PublicCheckoutController.java
@@ -22,6 +22,8 @@
 
 import com.querydsl.core.types.Predicate;
 import io.jsonwebtoken.lang.Maps;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.lang.Nullable;
@@ -60,6 +62,7 @@
 
 @RestController
 @RequestMapping("/public/checkout")
+@Tag(name = "Checkout")
 public class PublicCheckoutController {
     private final CheckoutService service;
     private final OrdersCrudService ordersCrudService;
@@ -89,7 +92,8 @@ public PublicCheckoutController(
      * @throws PaymentServiceException If an error happens during the payment
      *                                 payment process
      */
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Submit cart contents to request an order and begin a checkout")
     @PreAuthorize("hasAuthority('" + AUTHORITY_CHECKOUT + "')")
     public PaymentRedirectionDetailsPojo submitCart(@Valid @RequestBody OrderPojo transactionRequest)
         throws BadInputException, PaymentServiceException, EntityExistsException {
@@ -106,7 +110,8 @@ public PaymentRedirectionDetailsPojo submitCart(@Valid @RequestBody OrderPojo tr
      * @throws EntityNotFoundException If the token does not match that of any "pending" transaction
      * @throws PaymentServiceException If an error happens during internal API calls
      */
-    @GetMapping({"/validate", "/validate/"})
+    @GetMapping("/validate")
+    @Operation(summary = "Request that an order status be updated after having begun checkout")
     public ResponseEntity<Void> validateSuccesfulTransaction(@RequestParam Map<String, String> transactionData)
         throws BadInputException, EntityNotFoundException, PaymentServiceException, MailingServiceException {
         if (!transactionData.containsKey(WEBPAY_SUCCESS_TOKEN_HEADER_NAME)) { // success
@@ -133,7 +138,8 @@ public ResponseEntity<Void> validateSuccesfulTransaction(@RequestParam Map<Strin
      * @throws EntityNotFoundException If the token does not match that of any "pending" transaction
      * @throws PaymentServiceException If an error happens during internal API calls
      */
-    @PostMapping({"/validate", "/validate/"})
+    @PostMapping("/validate")
+    @Operation(summary = "Submit failed or aborted state for an order after having begun checkout")
     public ResponseEntity<Void> validateAbortedTransaction(@RequestParam Map<String, String> transactionData)
         throws BadInputException, EntityNotFoundException, PaymentServiceException {
 
diff --git a/src/main/java/org/trebol/api/controllers/PublicReceiptController.java b/src/main/java/org/trebol/api/controllers/PublicReceiptController.java
index 5a9c634e..a218376f 100644
--- a/src/main/java/org/trebol/api/controllers/PublicReceiptController.java
+++ b/src/main/java/org/trebol/api/controllers/PublicReceiptController.java
@@ -20,6 +20,8 @@
 
 package org.trebol.api.controllers;
 
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -34,6 +36,7 @@
 
 @RestController
 @RequestMapping("/public/receipt")
+@Tag(name = "Checkout")
 public class PublicReceiptController {
     private final ReceiptService receiptService;
 
@@ -44,7 +47,16 @@ public PublicReceiptController(
         this.receiptService = receiptService;
     }
 
-    @GetMapping({"/{token}", "/{token}/"})
+    /**
+     * Fetch result of transaction after it has been confirmed and validated
+     *
+     * @param token The token used during the transaction
+     * @return An object with all available data about the transaction
+     * @throws BadInputException when an empty token is provided
+     * @throws EntityNotFoundException when no transaction matches the provided token
+     */
+    @GetMapping("/{token}")
+    @Operation(summary = "View a summary of an order once complete or rejected")
     public ReceiptPojo fetchReceiptById(@PathVariable("token") String token)
         throws BadInputException, EntityNotFoundException {
         if (StringUtils.isBlank(token)) {
diff --git a/src/main/java/org/trebol/api/controllers/PublicRegisterController.java b/src/main/java/org/trebol/api/controllers/PublicRegisterController.java
index f7edc5d2..65a1abd0 100644
--- a/src/main/java/org/trebol/api/controllers/PublicRegisterController.java
+++ b/src/main/java/org/trebol/api/controllers/PublicRegisterController.java
@@ -20,6 +20,8 @@
 
 package org.trebol.api.controllers;
 
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -34,6 +36,7 @@
 
 @RestController
 @RequestMapping("/public/register")
+@Tag(name = "User Accounts")
 public class PublicRegisterController {
     private final RegistrationService registrationService;
 
@@ -44,7 +47,8 @@ public PublicRegisterController(
         this.registrationService = registrationService;
     }
 
-    @PostMapping({"", "/"})
+    @PostMapping
+    @Operation(summary = "Request creation of new user account.")
     public void register(@Valid @RequestBody RegistrationPojo userProfile)
         throws BadInputException, EntityExistsException {
         this.registrationService.register(userProfile);
diff --git a/src/main/java/org/trebol/api/controllers/RootController.java b/src/main/java/org/trebol/api/controllers/RootController.java
index f4615c3d..1321b6de 100644
--- a/src/main/java/org/trebol/api/controllers/RootController.java
+++ b/src/main/java/org/trebol/api/controllers/RootController.java
@@ -20,14 +20,18 @@
 
 package org.trebol.api.controllers;
 
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 @RestController
+@Tag(name = "Health check")
 public class RootController {
 
-    @GetMapping({"", "/"})
+    @GetMapping
+    @Operation(summary = "Non-operating endpoint.")
     public ResponseEntity<Void> defaultMapping() {
         return ResponseEntity.ok().build();
     }
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index fb1b9d6c..1b6c67ce 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -35,6 +35,14 @@ trebol.api.able-to-edit-orders-after-being-processed=false
 trebol.validation.id-number-regexp=^\d{7,9}[\dk]$
 trebol.validation.phonenumber-regexp=^\\+(?:[0-9] ?){6,14}[0-9]$
 ##############################
+# SPRINGDOC OPENAPI
+## Disallow generation of OpenAPI specification
+#springdoc.api-docs.enabled=false
+#springdoc.api-docs.path=/v3/api-docs
+## Disallow Swagger UI interface (for API navigation and testing)
+#springdoc.swagger-ui.enabled=false
+#springdoc.swagger-ui.path=/swagger-ui/index.html
+##############################
 # SECURITY
 ## The private key to encrypt and decrypt JWTs with
 trebol.security.jwt-secret-key=YOU.SHOULD.PROVIDE.YOUR.OWN.SECRET.KEY.THIS.IS.JUST.A.PLACEHOLDDER