Kotlin SDK

Kotlin SDK Quick Start — WowSQL Docs

Kotlin Quick Start

WowSQL Kotlin SDK — Get started in minutes

Get your API key: Use the WowSQL project dashboard to create or copy your API key. The same key works for database, auth, and storage (unified API key).

Installation

Official package: View on Maven Central →

// Gradle (Kotlin DSL)
implementation("com.WowSQL:WowSQL-kotlin:1.0.0")

Initialize Client

import com.WowSQL.WowSQLClient

// Initialize client with your API key (same key for database, auth, storage)
val client = WowSQLClient(
    projectUrl = "myproject",
    apiKey = "your_api_key_here"
)

// Or with full URL
val clientFull = WowSQLClient(
    projectUrl = "https://myproject.wowsqlconnect.com",
    apiKey = "your_api_key"
)

// Always use select() before get()/execute()
val users = client.table<Map<String, Any?>>("users").select("*").get()

Query Data

Basic Queries

// Get all records
val users = client.table("users").select("*").get()

// With filters
val adults = client.table("users").select("*").gte("age", 18).get()

// Select specific columns
val names = client.table("users").select("id", "name").get()

Advanced Queries

// Multiple filters with sorting
val activeUsers = client.table("users")
    .select("*")
    .eq("status", "active")
    .gt("age", 18)
    .order("created_at", "desc")
    .limit(20)
    .offset(0)
    .get()

println("Found ${activeUsers.count} users")
activeUsers.data.forEach { println(it["name"]) }

Filter Helper Methods

// Using helper methods: eq, gt, like, in, between
val users = client.table("users")
    .eq("status", "active")
    .gt("age", 18)
    .like("email", "%@gmail.com")
    .in("role", listOf("admin", "moderator"))
    .between("created_at", "2024-01-01", "2024-12-31")
    .get()

GROUP BY and Aggregates

Basic GROUP BY

// Group by category with counts
val result = client.table("products")
    .select("category", "COUNT(*) as count", "AVG(price) as avg_price")
    .groupBy("category")
    .get()

// Group by date
val result2 = client.table("orders")
    .select("DATE(created_at) as date", "COUNT(*) as orders", "SUM(total) as revenue")
    .groupBy("DATE(created_at)")
    .orderBy("date", "desc")
    .get()

HAVING Clause

val result = client.table("products")
    .select("category", "COUNT(*) as count")
    .groupBy("category")
    .having("COUNT(*)", "gt", 10)
    .get()

CRUD Operations

Create Record

val result = client.table("users").create(mapOf(
    "name" to "John Doe",
    "email" to "john@example.com",
    "age" to 30
))
println("Created user with ID: ${result["id"]}")

Update Record

client.table("users").update(123, mapOf("email" to "newemail@example.com"))
println("User updated successfully")

Delete Record

client.table("users").delete(123)
println("User deleted successfully")

Get Single Record by ID

val user = client.table("users").getById(123)
println("User: ${user?.get("name")}")

Get First Record

val user = client.table("users").eq("status", "active").first()
user?.let { println("First active user: ${it["name"]}") }

Filter Operators

Available operators for filtering data:

OperatorDescriptionExample (Kotlin)
eqEquals.eq("status", "active")
neqNot equals.neq("status", "deleted")
gtGreater than.gt("age", 18)
gteGreater than or equal.gte("age", 18)
ltLess than.lt("price", 100)
lteLess than or equal.lte("price", 100)
likePattern matching.like("name", "john")
inIN operator.in("category", listOf("electronics", "books"))
not_inNOT IN.notIn("status", listOf("deleted", "archived"))
betweenBETWEEN.between("price", 10, 100)

Error Handling

try {
    val users = client.table("users").select("*").get()
    println("Success: ${users.data.size} users")
} catch (e: WowSQLException) {
    when (e.statusCode) {
        401 -> println("Authentication failed — check your API key")
        404 -> println("Table or resource not found")
        else -> println("Error (${e.statusCode}): ${e.message}")
    }
}

Authentication

Use the same API key for authentication. One key works for database and auth.

Sign Up & Sign In

val auth = ProjectAuthClient(projectUrl = "myproject", apiKey = "your_api_key")

// Sign up
val result = auth.signUp("user@example.com", "SecurePassword123", "John Doe", null)
println("Access token: ${result.session.accessToken}")

// Sign in
val login = auth.signIn("user@example.com", "SecurePassword123")
println("User ID: ${login.user?.id}")

Password Reset

auth.forgotPassword("user@example.com")
auth.resetPassword("reset_token_from_email", "NewSecurePassword123")

OTP Authentication

auth.sendOtp("user@example.com", "login")
val result = auth.verifyOtp(
  email = "user@example.com",
  otp = "123456",
  purpose = "login"
)
println("Logged in: ${result.user.id}")

Magic Link & Email Verification

auth.sendMagicLink("user@example.com", "login")

OAuth Authentication

Setup checklist — do this once per provider, per project:
1. Dashboard → Project → Auth → Providers: enable the provider, paste Client ID and Client Secret (no leading/trailing spaces).
2. Copy the Redirect URI shown: https://<slug>.wowsqlconnect.com/api/auth/oauth/<provider>/callback and register it in your provider's developer console.
3. The callback URL is handled entirely by WowSQL — your app does not send an API key on it. WowSQL exchanges the code and redirects to your frontend_redirect_uri with ?access_token=&refresh_token=.

// ── Step 1: Server/ViewModel — get the authorization URL ─────────────────────
val oauthUrl = auth.getOAuthAuthorizationUrl(
  "google",
  "https://yourapp.com/auth/callback"
)
// Open a browser / custom tab to oauthUrl.authorizationUrl
// Google calls: https://<slug>.wowsqlconnect.com/api/auth/oauth/google/callback
// WowSQL exchanges the code and redirects to your frontend_redirect_uri.


// ── Step 2: App — handle the redirect ────────────────────────────────────────
// WowSQL redirects to: https://yourapp.com/auth/callback?access_token=...&refresh_token=...
// Use an Android deep-link / intent-filter to intercept the URI and extract the tokens.


// ── (Advanced) Manual code exchange — only if you handle the callback yourself
val result = auth.exchangeOAuthCallback(
  "google",
  "authorization_code_from_callback",
  "https://yourapp.com/auth/callback"  // must match step 1
)
println("OAuth login successful: ${result.user.id}")

With ViewModel (Android)

Use the client inside an Android ViewModel with coroutines:

class UsersViewModel(
    private val client: WowSQLClient
) : ViewModel() {

    private val _users = MutableLiveData<List<Map<String, Any?>>>()
    val users: LiveData<List<Map<String, Any?>>> = _users

    fun loadUsers() {
        viewModelScope.launch {
            try {
                val response = client.table("users")
                    .select("*")
                    .limit(10)
                    .execute()
                _users.value = response.data
            } catch (e: Exception) {
                // Handle error
            }
        }
    }
}

Storage Operations

Initialize Storage

val storage = WowSQLStorage(
    projectUrl = "myproject",
    apiKey = "your_api_key"
)

File Operations

// Upload file
val result = storage.uploadFromPath("path/to/document.pdf", "uploads/document.pdf", "documents")
println("Uploaded: ${result["file_key"]}")

// Get file URL
val urlData = storage.getFileUrl("uploads/document.pdf", 3600)
println("Download URL: ${urlData["file_url"]}")

// List files
val files = storage.listFiles("uploads/")
files.forEach { println("${it.key}: ${it.sizeMb} MB") }

// Delete file
storage.deleteFile("uploads/document.pdf")

// Check quota
val quota = storage.getQuota()
println("Used: ${quota.usedGb} GB / ${quota.quotaGb} GB")

Download or View File

Via REST: use GET .../files/{file_key}/download for attachment download, or GET .../files/{file_key}/view to view inline in the browser.

Schema DDL (WowSQLSchema)

UUID primary key: createTable requires primaryKey to name a column whose type is UUID. Use auto_increment on that column for DEFAULT gen_random_uuid(). Raw CREATE TABLE via execute SQL cannot use SERIAL PRIMARY KEY (or similar integer PK). Existing tables are unchanged.

schema.createTable(
    tableName = "items",
    columns = listOf(
        mapOf("name" to "id", "type" to "UUID", "auto_increment" to true),
        mapOf("name" to "title", "type" to "TEXT"),
    ),
    primaryKey = "id",
)