diff --git a/build.gradle.kts b/build.gradle.kts
index d8dc7f9..7c412b9 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -19,6 +19,10 @@ dependencies {
     implementation(Libs.javalin)
     implementation(Libs.slf4j_simple)
     implementation(Libs.jackson_databind)
+    implementation(Libs.jackson_module_kotlin)
+    implementation(Libs.swagger_core)
+    implementation(Libs.kotlin_openapi3_dsl)
+    implementation(Libs.swagger_ui)
 
     testImplementation(Libs.junit_jupiter)
 }
diff --git a/buildSrc/src/main/kotlin/Libs.kt b/buildSrc/src/main/kotlin/Libs.kt
index 1001201..fa5811b 100644
--- a/buildSrc/src/main/kotlin/Libs.kt
+++ b/buildSrc/src/main/kotlin/Libs.kt
@@ -7,12 +7,24 @@ import kotlin.String
  *   `$ ./gradlew buildSrcVersions`
  */
 object Libs {
+  /**
+   * https://github.com/derveloper/kotlin-openapi3-dsl
+   */
+  const val kotlin_openapi3_dsl: String = "cc.vileda:kotlin-openapi3-dsl:" +
+      Versions.kotlin_openapi3_dsl
+
   /**
    * http://github.com/FasterXML/jackson
    */
   const val jackson_databind: String = "com.fasterxml.jackson.core:jackson-databind:" +
       Versions.jackson_databind
 
+  /**
+   * https://github.com/FasterXML/jackson-module-kotlin
+   */
+  const val jackson_module_kotlin: String = "com.fasterxml.jackson.module:jackson-module-kotlin:" +
+      Versions.jackson_module_kotlin
+
   const val com_github_johnrengelman_shadow_gradle_plugin: String =
       "com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:" +
       Versions.com_github_johnrengelman_shadow_gradle_plugin
@@ -26,6 +38,11 @@ object Libs {
    */
   const val javalin: String = "io.javalin:javalin:" + Versions.javalin
 
+  /**
+   * https://github.com/swagger-api/swagger-core
+   */
+  const val swagger_core: String = "io.swagger.core.v3:swagger-core:" + Versions.swagger_core
+
   const val org_jetbrains_kotlin_jvm_gradle_plugin: String =
       "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:" +
       Versions.org_jetbrains_kotlin_jvm_gradle_plugin
@@ -51,4 +68,9 @@ object Libs {
    * http://www.slf4j.org
    */
   const val slf4j_simple: String = "org.slf4j:slf4j-simple:" + Versions.slf4j_simple
+
+  /**
+   * http://webjars.org
+   */
+  const val swagger_ui: String = "org.webjars:swagger-ui:" + Versions.swagger_ui
 }
diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt
index 4a5fa73..1cbe45b 100644
--- a/buildSrc/src/main/kotlin/Versions.kt
+++ b/buildSrc/src/main/kotlin/Versions.kt
@@ -12,14 +12,20 @@ import org.gradle.plugin.use.PluginDependencySpec
  * YOU are responsible for updating manually the dependency version.
  */
 object Versions {
+  const val kotlin_openapi3_dsl: String = "0.20.2"
+
   const val jackson_databind: String = "2.10.0.pr1"
 
+  const val jackson_module_kotlin: String = "2.10.0.pr1"
+
   const val com_github_johnrengelman_shadow_gradle_plugin: String = "5.1.0"
 
   const val de_fayard_buildsrcversions_gradle_plugin: String = "0.4.2"
 
   const val javalin: String = "3.4.1"
 
+  const val swagger_core: String = "2.0.9"
+
   const val org_jetbrains_kotlin_jvm_gradle_plugin: String = "1.3.50"
 
   const val org_jetbrains_kotlin: String = "1.3.50"
@@ -28,6 +34,8 @@ object Versions {
 
   const val slf4j_simple: String = "1.7.28"
 
+  const val swagger_ui: String = "3.23.5"
+
   /**
    *
    * See issue 19: How to update Gradle itself?
diff --git a/src/main/kotlin/com/anthonycicchetti/slackbot/Main.kt b/src/main/kotlin/com/anthonycicchetti/slackbot/Main.kt
index 22264ad..0ac1c46 100644
--- a/src/main/kotlin/com/anthonycicchetti/slackbot/Main.kt
+++ b/src/main/kotlin/com/anthonycicchetti/slackbot/Main.kt
@@ -5,30 +5,68 @@ import com.anthonycicchetti.slackbot.utility.RespObj
 import com.anthonycicchetti.slackbot.utility.TextResponse
 import io.javalin.http.Context
 import io.javalin.Javalin
+import io.javalin.plugin.openapi.OpenApiOptions
+import io.javalin.plugin.openapi.OpenApiPlugin
+import io.javalin.plugin.openapi.dsl.document
+import io.javalin.plugin.openapi.dsl.documented
+import io.javalin.plugin.openapi.ui.SwaggerOptions
+import io.swagger.v3.oas.models.OpenAPI
+import io.swagger.v3.oas.models.info.Info
+import io.swagger.v3.oas.models.servers.Server
 import org.slf4j.LoggerFactory
+import kotlin.math.roundToInt
 
 fun main() {
     val logger = LoggerFactory.getLogger("main")
 
-    val app = Javalin.create().start(7000)
+    val app = Javalin.create { config ->
+        config.registerPlugin(OpenApiPlugin(createOpenApiOptions()))
+        config.enableCorsForAllOrigins()
+        config.requestLogger {ctx, ms ->
+        logger.info("Took ${ms.roundToInt()} to process ${ctx.req.requestURL}")
+    }
+    }.start(7000)
     with(app) {
-        get("/") { ctx -> ctx.result("Hello World") }
+        options("/*", documented(document().ignore()) {})
+        get("/", documented(document().ignore()) { ctx -> ctx.result("Hello World") })
 
-        post("/slack/receive") { ctx ->
+        post("/slack/receive", documented(document().operation {
+            it.description = "NOT DOCUMENTED. Required for slack usage"
+            it.summary = "NOT DOCUMENTED. Required for slack usage"
+        }.ignore()) { ctx ->
+            logger.info("Received request from ${ctx.req.requestURL}")
             handleSlackEvent(ctx)
-        }
+        })
 
-        post("/api/v1/spongebob") { ctx ->
+        post("/api/v1/spongebob", documented(document().operation {
+            it.description = "Responds with the ${"spongemocked".toSpongemock()} version of the string posted"
+            it.summary = "POST for ${"spongemocking".toSpongemock()}"
+        }.body<String>().json<TextResponse>("200")) { ctx ->
+            logger.info("Spongemock: Received request from ${ctx.req.requestURL}")
             ctx.json(TextResponse(200, ctx.body().toSpongemock()))
-        }
+        })
 
-        post("/api/v1/uppercase") { ctx ->
+        post("/api/v1/uppercase", documented(document().operation {
+            it.description = "Responds with the UPPERCASED version of the string posted"
+            it.summary = "POST for UPPERCASING"
+        }.body<String>().json<TextResponse>("200")) { ctx ->
+            logger.info("Uppercase: Received request from ${ctx.req.requestURL}")
             ctx.json(TextResponse(200, ctx.body().toUpperCase()))
-        }
+        })
+    }
+
+
+    Runtime.getRuntime().addShutdownHook(Thread {
+        app.stop()
+    })
+
+    app.events { event ->
+        event.serverStopping { logger.info("Server stopping") }
+        event.serverStopped { logger.info("Server stopped") }
     }
 }
 
-fun handleSlackEvent(ctx: Context) {
+private fun handleSlackEvent(ctx: Context) {
     // Short circuit for ssl check
     if ((ctx.formParam("ssl_check") ?: "0") == "1") {
         ctx.status(200)
@@ -36,11 +74,11 @@ fun handleSlackEvent(ctx: Context) {
     }
 
     val responseObj = RespObj(
-        command = ctx.formParamMap().get("command")?.get(0).processToCommand(),
-        text = ctx.formParamMap().get("text")?.get(0) ?: "",
-        response_url = ctx.formParamMap().get("response_url")?.get(0) ?: "",
-        team_id = ctx.formParamMap().get("team_id")?.get(0) ?: "",
-        channel_id = ctx.formParamMap().get("channel_id")?.get(0) ?: ""
+        command = ctx.formParamMap()["command"]?.get(0).processToCommand(),
+        text = ctx.formParamMap()["text"]?.get(0) ?: "",
+        response_url = ctx.formParamMap()["response_url"]?.get(0) ?: "",
+        team_id = ctx.formParamMap()["team_id"]?.get(0) ?: "",
+        channel_id = ctx.formParamMap()["channel_id"]?.get(0) ?: ""
     )
 
     sendResponse(ctx, responseObj)
@@ -54,7 +92,7 @@ private fun String?.processToCommand(): Commands {
     }
 }
 
-fun sendResponse(ctx: Context, respObj: RespObj) {
+private fun sendResponse(ctx: Context, respObj: RespObj) {
     val returnMap = mutableMapOf<String, String>()
     with(returnMap) {
         when (respObj.command) {
@@ -71,4 +109,17 @@ fun sendResponse(ctx: Context, respObj: RespObj) {
 
     }
     ctx.json(returnMap)
+}
+
+private fun createOpenApiOptions(): OpenApiOptions {
+    val o = {
+        OpenAPI()
+            .info(Info().version("0.1.2").description("Slackbot Open API documentation"))
+            .addServersItem(Server().url("https://acicchetti.dev/"))
+            .addServersItem(Server().url("http://localhost:7000/"))
+    }
+
+    return OpenApiOptions(o)
+        .path("/swagger-docs")
+        .swagger(SwaggerOptions("/swagger").title("Slackbot Swagger Docs"))
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/anthonycicchetti/slackbot/utility/TextResponse.kt b/src/main/kotlin/com/anthonycicchetti/slackbot/utility/TextResponse.kt
index 7fbcba3..1723749 100644
--- a/src/main/kotlin/com/anthonycicchetti/slackbot/utility/TextResponse.kt
+++ b/src/main/kotlin/com/anthonycicchetti/slackbot/utility/TextResponse.kt
@@ -1,3 +1,3 @@
 package com.anthonycicchetti.slackbot.utility
 
-data class TextResponse(val status: Int, val response: String)
\ No newline at end of file
+data class TextResponse(val status: Int = 200, val response: String)
\ No newline at end of file