← All courses

Sharing Networking with Ktor

🗓 May 31, 2026 ⏱ 2 min read

Ktor: the multiplatform HTTP client

Ktor is a Kotlin networking library that works across all KMP targets. You write your API calls once in commonMain, and each platform plugs in its own networking engine under the hood.

Per-platform engines

Recall from the project-structure lesson: the Ktor core lives in common, but each platform adds an engine:

  • Androidktor-client-okhttp.
  • iOSktor-client-darwin.

Your calling code never mentions the engine — it just uses the shared client.

Configuring the client

import io.ktor.client.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.json.*

val client = HttpClient {
    install(ContentNegotiation) {
        json(Json { ignoreUnknownKeys = true })   // auto JSON parsing
    }
}

The ContentNegotiation plugin ties Ktor to kotlinx.serialization, so responses are decoded into your models automatically.

A shared API class

import io.ktor.client.request.*
import io.ktor.client.call.*

class UserApi(private val client: HttpClient) {

    suspend fun getUsers(): List<User> =
        client.get("https://api.example.com/users").body()

    suspend fun getUser(id: Int): User =
        client.get("https://api.example.com/users/$id").body()

    suspend fun createUser(user: User): User =
        client.post("https://api.example.com/users") {
            contentType(ContentType.Application.Json)
            setBody(user)
        }.body()
}

The .body() call decodes the JSON response straight into your model. Functions are suspend, so they run asynchronously via coroutines on every platform.

Same code, both apps

Your Android ViewModel and your iOS presenter both call userApi.getUsers() — identical code, one source of truth. Fix a bug or change an endpoint once, and both platforms get it.

Error handling

suspend fun safeUsers(): Result<List<User>> = runCatching {
    client.get("https://api.example.com/users").body()
}

Wrapping calls in runCatching (or try/catch) lets each platform show friendly errors for network failures.

Common mistakes

  • Forgetting the platform engine dependency (the client won’t work on that platform).
  • Not installing ContentNegotiation, so .body() can’t decode JSON.
  • Ignoring errors — always handle network failures.
Summary: Ktor lets you write one networking layer in common code, with a per-platform engine added under the hood. Configure ContentNegotiation for automatic JSON, expose suspend API functions, and handle errors — both apps share the exact same network code.