Introduction
Kotlin is a modern, concise, and safe programming language that is gaining popularity in server-side application development. Thanks to its compatibility with Java and powerful frameworks like Ktor, you can create a full-fledged REST API in literally half an hour. In this article, we will show you how to write a REST API in Kotlin using the Ktor framework, even if you are a beginner.
We will create a simple application for managing a to-do list (Todo API) with support for CRUD operations: create, read, update, and delete. The entire process will take no more than 30 minutes if you follow the instructions.
1. Project Setup and Dependencies
To start, you will need IntelliJ IDEA (Community Edition) and Gradle. Let's create a new Kotlin project with Ktor support.
Step 1: Creating a Gradle Project
Open IntelliJ IDEA and create a new project: File → New → Project. Select Gradle and specify the language Kotlin. Click Finish.
Step 2: Adding Ktor Dependencies
Open the build.gradle.kts file and add the following dependencies:
plugins { kotlin("jvm") version "1.9.0" application}
repositories { mavenCentral()}
dependencies { implementation("io.ktor:ktor-server-core:2.3.0") implementation("io.ktor:ktor-server-netty:2.3.0") implementation("io.ktor:ktor-server-content-negotiation:2.3.0") implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.0") implementation("ch.qos.logback:logback-classic:1.4.11")}
application { mainClass.set("ApplicationKt")}Click the Sync Now button in the top right corner to download the dependencies.
2. Creating the Data Model and Service
Before writing the routes, let's define a data model for our task and a simple service for storing data in memory.
TodoItem Model
Create a file TodoItem.kt in the src/main/kotlin folder:
import kotlinx.serialization.Serializable
@Serializabledata class TodoItem( val id: Int, val title: String, val completed: Boolean = false)TodoService
Create a file TodoService.kt:
import java.util.concurrent.atomic.AtomicInteger
class TodoService { private val items = mutableListOf<TodoItem>() private val idCounter = AtomicInteger(1)
fun getAll(): List<TodoItem> = items.toList()
fun getById(id: Int): TodoItem? = items.find { it.id == id }
fun create(title: String): TodoItem { val newItem = TodoItem(id = idCounter.getAndIncrement(), title = title) items.add(newItem) return newItem }
fun update(id: Int, title: String?, completed: Boolean?): TodoItem? { val index = items.indexOfFirst { it.id == id } if (index == -1) return null val current = items[index] val updated = current.copy( title = title ?: current.title, completed = completed ?: current.completed ) items[index] = updated return updated }
fun delete(id: Int): Boolean = items.removeAll { it.id == id }}3. Configuring the Server and Routes
Now let's create the main application file Application.kt and define the REST API routes.
import io.ktor.server.application.*import io.ktor.server.engine.*import io.ktor.server.netty.*import io.ktor.server.routing.*import io.ktor.server.response.*import io.ktor.server.request.*import io.ktor.serialization.kotlinx.json.*import io.ktor.server.plugins.contentnegotiation.*
fun main() { embeddedServer(Netty, port = 8080, host = "0.0.0.0") { configureSerialization() configureRouting() }.start(wait = true)}
fun