
For PocketBase: modular clients, coroutine-first APIs, result-based error handling, typed decoding helpers, cancellation-safe operations, auth workflows, realtime subscriptions, plus files and admin services.
Kotlin Multiplatform SDK for PocketBase with modular clients, coroutine-first APIs, and result-based error handling.
core, client, auth, records, files, realtime
PocketBaseResult<T> with map, flatMap, recover, getOrElse
CancellationException is rethrown, never swallowedgetTyped<T>(), postTyped<T>(), deserialize<T>()
Add the dependencies you need:
[versions]
pocketbase-kmp = "0.3.3"
[libraries]
pocketbase-core = { module = "io.github.androidpoet:pocketbase-core", version.ref = "pocketbase-kmp" }
pocketbase-client = { module = "io.github.androidpoet:pocketbase-client", version.ref = "pocketbase-kmp" }
pocketbase-auth = { module = "io.github.androidpoet:pocketbase-auth", version.ref = "pocketbase-kmp" }
pocketbase-records = { module = "io.github.androidpoet:pocketbase-records", version.ref = "pocketbase-kmp" }
pocketbase-files = { module = "io.github.androidpoet:pocketbase-files", version.ref = "pocketbase-kmp" }
pocketbase-realtime = { module = "io.github.androidpoet:pocketbase-realtime", version.ref = "pocketbase-kmp" }kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.pocketbase.client)
implementation(libs.pocketbase.auth)
implementation(libs.pocketbase.records)
implementation(libs.pocketbase.files)
implementation(libs.pocketbase.realtime)
}
}
}val pb = PocketBase.create(baseUrl = "http://127.0.0.1:8090")
val auth = createAuthClient(pb.client)
val records = createRecordsClient(pb.client)
val files = createFilesClient(pb.client)
val realtime = createRealtimeClient(pb.client)val listResult = records.getList(
collectionIdOrName = "tasks",
page = 1,
perPage = 20,
filter = "status = 'open'",
)
listResult.onSuccess { page ->
println("items=${page.items.size}, total=${page.totalItems}")
}.onFailure { error ->
println("error=${error.message}")
}
val fullList = records.getFullList("tasks", batch = 200)@Serializable
data class HealthResponse(val code: Int, val message: String)
val health: PocketBaseResult<HealthResponse> = pb.client.getTyped("/api/health")auth.authWithPassword(
collectionIdOrName = "users",
identity = "user@example.com",
password = "secret",
).onSuccess { session ->
println("token=${session.token}")
}
auth.refresh("users")
auth.requestPasswordReset("users", "user@example.com")
auth.requestVerification("users", "user@example.com")Notes from official PocketBase behavior:
val token = files.getToken()
val url = files.getUrl(
collectionIdOrName = "tasks",
recordId = "RECORD_ID",
filename = "photo.png",
)realtime.onEvent { event, data ->
println("$event -> $data")
}
realtime.connect()
realtime.subscribe("collections/tasks")Realtime note:
val value = PocketBaseResult.catching { 42 }
.map { it * 2 }
.getOrElse { -1 }
val kotlinResult = value.let { PocketBaseResult.Success(it) }.toKotlinResult()┌─────────────────────────────────────────────────────────────────────┐
│ Your App │
├──────────┬────────────┬───────────┬───────────┬───────────┬────────┤
│auth │records │files │realtime │services │client │
│password │CRUD/list │token/url │subscribe │health/logs│HTTP │
│oauth2/otp│full-list │helpers │reconnect │settings │auth │
├──────────┴────────────┴───────────┴───────────┴───────────┼────────┤
│ pocketbase-core │ │
│ PocketBaseResult · errors · response models │ │
└───────────────────────────────────────────────────────────────┴────────┘
| Module | Artifact | Description |
|---|---|---|
pocketbase-core |
io.github.androidpoet:pocketbase-core |
Result type, error model, core response models |
pocketbase-client |
io.github.androidpoet:pocketbase-client |
HTTP transport, config, auth store, admin services |
pocketbase-auth |
io.github.androidpoet:pocketbase-auth |
Record auth and account lifecycle endpoints |
pocketbase-records |
io.github.androidpoet:pocketbase-records |
Record CRUD + paginated/full-list helpers |
pocketbase-files |
io.github.androidpoet:pocketbase-files |
File token and URL helper operations |
pocketbase-realtime |
io.github.androidpoet:pocketbase-realtime |
Realtime connect/subscribe/unsubscribe stream client |
Detailed endpoint parity: docs/api-coverage.md
| Platform | Target |
|---|---|
| Android | androidTarget() |
| JVM | jvm() |
| iOS |
iosX64() iosArm64() iosSimulatorArm64()
|
| macOS |
macosX64() macosArm64()
|
| tvOS |
tvosX64() tvosArm64() tvosSimulatorArm64()
|
| watchOS |
watchosX64() watchosArm64() watchosSimulatorArm64()
|
| Linux | linuxX64() |
| Windows | mingwX64() |
| Web | wasmJs() |
./gradlew checkJvmDirect per-task alternative:
./gradlew jvmTestAvoid running ./gradlew test or allTests for local verification unless you intentionally want Android/native target tasks as well.
/api/batch must be enabled).MIT. See LICENSE.
Kotlin Multiplatform SDK for PocketBase with modular clients, coroutine-first APIs, and result-based error handling.
core, client, auth, records, files, realtime
PocketBaseResult<T> with map, flatMap, recover, getOrElse
CancellationException is rethrown, never swallowedgetTyped<T>(), postTyped<T>(), deserialize<T>()
Add the dependencies you need:
[versions]
pocketbase-kmp = "0.3.3"
[libraries]
pocketbase-core = { module = "io.github.androidpoet:pocketbase-core", version.ref = "pocketbase-kmp" }
pocketbase-client = { module = "io.github.androidpoet:pocketbase-client", version.ref = "pocketbase-kmp" }
pocketbase-auth = { module = "io.github.androidpoet:pocketbase-auth", version.ref = "pocketbase-kmp" }
pocketbase-records = { module = "io.github.androidpoet:pocketbase-records", version.ref = "pocketbase-kmp" }
pocketbase-files = { module = "io.github.androidpoet:pocketbase-files", version.ref = "pocketbase-kmp" }
pocketbase-realtime = { module = "io.github.androidpoet:pocketbase-realtime", version.ref = "pocketbase-kmp" }kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.pocketbase.client)
implementation(libs.pocketbase.auth)
implementation(libs.pocketbase.records)
implementation(libs.pocketbase.files)
implementation(libs.pocketbase.realtime)
}
}
}val pb = PocketBase.create(baseUrl = "http://127.0.0.1:8090")
val auth = createAuthClient(pb.client)
val records = createRecordsClient(pb.client)
val files = createFilesClient(pb.client)
val realtime = createRealtimeClient(pb.client)val listResult = records.getList(
collectionIdOrName = "tasks",
page = 1,
perPage = 20,
filter = "status = 'open'",
)
listResult.onSuccess { page ->
println("items=${page.items.size}, total=${page.totalItems}")
}.onFailure { error ->
println("error=${error.message}")
}
val fullList = records.getFullList("tasks", batch = 200)@Serializable
data class HealthResponse(val code: Int, val message: String)
val health: PocketBaseResult<HealthResponse> = pb.client.getTyped("/api/health")auth.authWithPassword(
collectionIdOrName = "users",
identity = "user@example.com",
password = "secret",
).onSuccess { session ->
println("token=${session.token}")
}
auth.refresh("users")
auth.requestPasswordReset("users", "user@example.com")
auth.requestVerification("users", "user@example.com")Notes from official PocketBase behavior:
val token = files.getToken()
val url = files.getUrl(
collectionIdOrName = "tasks",
recordId = "RECORD_ID",
filename = "photo.png",
)realtime.onEvent { event, data ->
println("$event -> $data")
}
realtime.connect()
realtime.subscribe("collections/tasks")Realtime note:
val value = PocketBaseResult.catching { 42 }
.map { it * 2 }
.getOrElse { -1 }
val kotlinResult = value.let { PocketBaseResult.Success(it) }.toKotlinResult()┌─────────────────────────────────────────────────────────────────────┐
│ Your App │
├──────────┬────────────┬───────────┬───────────┬───────────┬────────┤
│auth │records │files │realtime │services │client │
│password │CRUD/list │token/url │subscribe │health/logs│HTTP │
│oauth2/otp│full-list │helpers │reconnect │settings │auth │
├──────────┴────────────┴───────────┴───────────┴───────────┼────────┤
│ pocketbase-core │ │
│ PocketBaseResult · errors · response models │ │
└───────────────────────────────────────────────────────────────┴────────┘
| Module | Artifact | Description |
|---|---|---|
pocketbase-core |
io.github.androidpoet:pocketbase-core |
Result type, error model, core response models |
pocketbase-client |
io.github.androidpoet:pocketbase-client |
HTTP transport, config, auth store, admin services |
pocketbase-auth |
io.github.androidpoet:pocketbase-auth |
Record auth and account lifecycle endpoints |
pocketbase-records |
io.github.androidpoet:pocketbase-records |
Record CRUD + paginated/full-list helpers |
pocketbase-files |
io.github.androidpoet:pocketbase-files |
File token and URL helper operations |
pocketbase-realtime |
io.github.androidpoet:pocketbase-realtime |
Realtime connect/subscribe/unsubscribe stream client |
Detailed endpoint parity: docs/api-coverage.md
| Platform | Target |
|---|---|
| Android | androidTarget() |
| JVM | jvm() |
| iOS |
iosX64() iosArm64() iosSimulatorArm64()
|
| macOS |
macosX64() macosArm64()
|
| tvOS |
tvosX64() tvosArm64() tvosSimulatorArm64()
|
| watchOS |
watchosX64() watchosArm64() watchosSimulatorArm64()
|
| Linux | linuxX64() |
| Windows | mingwX64() |
| Web | wasmJs() |
./gradlew checkJvmDirect per-task alternative:
./gradlew jvmTestAvoid running ./gradlew test or allTests for local verification unless you intentionally want Android/native target tasks as well.
/api/batch must be enabled).MIT. See LICENSE.