Android SDK (Kotlin)
The official Zyphr SDK for Android and JVM, built with OkHttp4 and Kotlin coroutines. Auto-generated from the OpenAPI specification.
Installation
Gradle (Kotlin DSL)
dependencies {
implementation("dev.zyphr:zyphr-sdk:0.1.0")
}
Gradle (Groovy)
implementation 'dev.zyphr:zyphr-sdk:0.1.0'
Configuration
import dev.zyphr.sdk.infrastructure.ApiClient
val client = ApiClient(
apiKey = "zy_live_xxx",
basePath = "https://api.zyphr.dev/v1" // Optional custom endpoint
)
Never hardcode API keys in your app. Store them securely using BuildConfig fields during development and a secure backend proxy in production. Mobile apps should use a backend endpoint that proxies Zyphr API calls to avoid exposing your API key.
API Classes
The SDK exposes one API class per resource:
| Class | Description |
|---|---|
EmailsApi | Send and manage email messages |
PushApi | Send push notifications |
SmsApi | Send SMS text messages |
InboxApi | In-app notification inbox |
SubscribersApi | Manage subscriber profiles |
DevicesApi | Register push notification devices |
TemplatesApi | Create and manage templates |
TopicsApi | Pub/sub topics |
WebhooksApi | Configure webhook endpoints |
All API methods are suspend functions and must be called from a coroutine scope.
Emails
Send Email
import dev.zyphr.sdk.api.EmailsApi
import dev.zyphr.sdk.models.SendEmailRequest
val emails = EmailsApi(client)
val result = emails.sendEmail(
SendEmailRequest(
to = "user@example.com",
from = "hello@yourapp.com",
subject = "Welcome!",
html = "<h1>Hello!</h1><p>Thanks for signing up.</p>",
text = "Hello! Thanks for signing up.",
replyTo = "support@yourapp.com",
tags = listOf("welcome", "onboarding"),
metadata = mapOf("userId" to "user_123")
)
)
println("Email sent: ${result.id}")
Send with Template
val result = emails.sendEmail(
SendEmailRequest(
to = "user@example.com",
templateId = "welcome-email",
templateData = mapOf(
"name" to "John",
"actionUrl" to "https://yourapp.com/activate"
)
)
)
Get Email Status
val email = emails.getEmail(id = "msg_abc123")
println("Status: ${email.status}")
List Emails
val response = emails.listEmails(page = 1, perPage = 25)
for (email in response.data) {
println("${email.id}: ${email.status}")
}
Push Notifications
Send Push
import dev.zyphr.sdk.api.PushApi
import dev.zyphr.sdk.models.SendPushRequest
val push = PushApi(client)
push.sendPush(
SendPushRequest(
userId = "user_123",
title = "New Message",
body = "You have a new message",
data = mapOf("messageId" to "msg_456")
)
)
Send to Specific Device
push.sendPush(
SendPushRequest(
deviceId = "device_abc",
title = "New Message",
body = "You have a new message"
)
)
Silent Push
push.sendPush(
SendPushRequest(
userId = "user_123",
contentAvailable = true,
data = mapOf("type" to "sync", "resource" to "messages")
)
)
Rich Notifications
push.sendPush(
SendPushRequest(
userId = "user_123",
title = "Photo shared",
body = "Jane shared a photo with you",
imageUrl = "https://yourapp.com/photo.jpg",
badge = 3,
sound = "default",
actionButtons = listOf(
ActionButton(id = "view", title = "View"),
ActionButton(id = "dismiss", title = "Dismiss")
)
)
)
SMS
import dev.zyphr.sdk.api.SmsApi
import dev.zyphr.sdk.models.SendSmsRequest
val sms = SmsApi(client)
val result = sms.sendSms(
SendSmsRequest(
to = "+14155551234",
body = "Your verification code is 123456"
)
)
println("SMS sent: ${result.id}")
In-App Inbox
import dev.zyphr.sdk.api.InboxApi
import dev.zyphr.sdk.models.SendInboxRequest
val inbox = InboxApi(client)
inbox.sendInboxNotification(
SendInboxRequest(
subscriberId = "user_123",
title = "New Comment",
body = "John commented on your post",
actionUrl = "/posts/123#comments"
)
)
Subscribers
Create Subscriber
import dev.zyphr.sdk.api.SubscribersApi
import dev.zyphr.sdk.models.CreateSubscriberRequest
val subscribers = SubscribersApi(client)
val subscriber = subscribers.createSubscriber(
CreateSubscriberRequest(
externalId = "user_123",
email = "user@example.com",
phone = "+14155551234",
name = "John Doe",
metadata = mapOf("plan" to "pro")
)
)
Get Subscriber
val subscriber = subscribers.getSubscriber(id = "user_123")
println("Name: ${subscriber.name}")
Update Subscriber
subscribers.updateSubscriber(
id = "user_123",
UpdateSubscriberRequest(
name = "Jane Doe",
metadata = mapOf("plan" to "enterprise")
)
)
Delete Subscriber
subscribers.deleteSubscriber(id = "user_123")
Device Management
Register Device
import dev.zyphr.sdk.api.DevicesApi
import dev.zyphr.sdk.models.RegisterDeviceRequest
val devices = DevicesApi(client)
devices.registerDevice(
RegisterDeviceRequest(
subscriberId = "user_123",
token = fcmToken,
platform = RegisterDeviceRequest.Platform.android,
appVersion = BuildConfig.VERSION_NAME,
osVersion = Build.VERSION.RELEASE
)
)
List Devices
val response = devices.listDevices(userId = "user_123")
for (device in response.data) {
println("${device.platform}: ${device.lastSeenAt}")
}
Unregister Device
devices.deleteDevice(id = "device_abc")
Topics
Subscribe to Topic
import dev.zyphr.sdk.api.TopicsApi
val topics = TopicsApi(client)
topics.subscribe(
topicId = "promotions",
subscriberId = "user_123"
)
Unsubscribe from Topic
topics.unsubscribe(
topicId = "promotions",
subscriberId = "user_123"
)
Send to Topic
push.sendToTopic(
topicId = "promotions",
SendPushRequest(
title = "Flash Sale!",
body = "50% off everything today"
)
)
Error Handling
All API methods are suspend functions that throw exceptions on failure:
import dev.zyphr.sdk.infrastructure.ClientException
import dev.zyphr.sdk.infrastructure.ServerException
try {
emails.sendEmail(request)
} catch (e: ClientException) {
// 4xx errors
println("Client error (${e.statusCode}): ${e.message}")
when (e.statusCode) {
400 -> println("Bad request — check your parameters")
401 -> println("Unauthorized — check your API key")
404 -> println("Resource not found")
429 -> println("Rate limited — slow down")
}
} catch (e: ServerException) {
// 5xx errors
println("Server error (${e.statusCode}): ${e.message}")
} catch (e: Exception) {
// Network errors
println("Network error: ${e.message}")
}
Retry with Exponential Backoff
suspend fun <T> withRetry(maxAttempts: Int = 3, operation: suspend () -> T): T {
var lastException: Exception? = null
repeat(maxAttempts) { attempt ->
try {
return operation()
} catch (e: ClientException) {
if (e.statusCode == 429) {
lastException = e
delay(2.0.pow(attempt).toLong() * 1000)
} else {
throw e // Don't retry other 4xx errors
}
} catch (e: ServerException) {
lastException = e
delay(2.0.pow(attempt).toLong() * 1000)
}
}
throw lastException!!
}
// Usage
val result = withRetry {
emails.sendEmail(request)
}
Coroutines & ViewModel Integration
All API methods are suspend functions. Use them with Android's coroutine scopes:
ViewModel
class NotificationViewModel(private val push: PushApi) : ViewModel() {
private val _sendState = MutableStateFlow<Result<Unit>?>(null)
val sendState: StateFlow<Result<Unit>?> = _sendState
fun sendNotification(userId: String, title: String, body: String) {
viewModelScope.launch {
_sendState.value = runCatching {
push.sendPush(
SendPushRequest(
userId = userId,
title = title,
body = body
)
)
}
}
}
}
Jetpack Compose
@Composable
fun SendNotificationScreen(viewModel: NotificationViewModel) {
val sendState by viewModel.sendState.collectAsState()
Button(onClick = {
viewModel.sendNotification("user_123", "Hello", "World")
}) {
Text("Send Notification")
}
sendState?.let { result ->
result.onSuccess { Text("Sent!") }
result.onFailure { Text("Error: ${it.message}") }
}
}
Thread Safety
The SDK uses OkHttp's connection pool and is safe to share across threads and coroutine scopes. Create a single ApiClient instance and reuse it throughout your app:
// In your Application class or DI module
val zyphrClient = ApiClient(apiKey = BuildConfig.ZYPHR_API_KEY)
// Inject into ViewModels/repositories
val emailsApi = EmailsApi(zyphrClient)
val pushApi = PushApi(zyphrClient)
Requirements
- Android API 21+ (Android 5.0)
- Kotlin 1.8+
- OkHttp 4.x
Next Steps
- Push Notifications for Android — Complete native Android push integration guide
- Push Notifications API — Full push API reference
- Device Management — Managing registered devices