Mobile SDK Overview
The SmartOTP SDK holds the client secret on the device, protects it behind the user's PIN, and generates TOTP codes offline. It ships for Android and iOS. The SDK also wraps the API calls your app needs — activate, retire, status, sync time, latest transaction.
Platforms
| What | Description |
|---|---|
| Android | Kotlin. Entry point SdkSoft. Current version 0.4.0. |
| iOS | Swift. Framework CakeOTP.xcframework. |
What the SDK Does For You
| What | Description |
|---|---|
| Holds the secret | Stores the client secret key from Activate in local secure storage, encrypted with the user's PIN. |
| Generates codes | Produces basic and advance OTPs on the device with no network call. |
| Wraps the API | Calls activate, retire, get status, sync time and get latest transaction for you. |
| Tracks drift | Compares the device clock against the server and adjusts. |
Your backend still owns Register, Create Transaction and Validate OTP — the SDK never validates a code it generated.
The PIN
Everything the SDK stores is gated on a PIN the user chooses at activation.
| What | Description |
|---|---|
| Set it | storedSecureSmartOTP(pin) after a successful activate. |
| Check it | isValidPin(pin) before generating any code. |
| Change it | changePin(oldPin, newPin). The new PIN cannot repeat the previous two. |
WARNING
Android documents the PIN as 4 digits; iOS accepts 4 or 6. If one app has to interoperate with the other — same user, two devices — agree on a single length up front, otherwise a PIN set on iOS may be unusable on Android.
Generating a Code
isValidPin(pin) → false: show an error, ask again
↓ true
generateSmartOTP() → basic OTP, no transaction context
generateAdvancedSotp(challengeKey) → advance OTP, bound to one transactionThe challengeKey comes from Create Transaction, pushed to the device via Firebase or passed down by your backend.
Device and Session Helpers
Both platforms expose the same read-only accessors:
| What | Description |
|---|---|
isSmartOtpRegistered | Whether this device has registered SmartOTP with any user. |
getCurrentUserId · getCurrentUsername | The registered user on this device. |
getRegistrationId · getSerialId | Identifiers stored at activation. |
getTime | The server timestamp. |
getPeriod | The TOTP period in seconds. |
getRemainingValidityTime | Seconds left on the current code. |
Status Values
The SDK reports two states the Back-end Get Status endpoint does not.
| Field | Type | Description |
|---|---|---|
NOT_REGISTERED | string | This device has not registered SmartOTP with any user. |
NOT_CURRENT_USER | string | The userId asked about is not the user this device registered with. |
NON_ACTIVATED | string | Registered but not activated on this device, or activated on another one. |
ACTIVATED | string | SmartOTP is live for this user on this device. |
TEMPORARY_BLOCKED | string | SmartOTP for this user on this device is blocked. |
INFO
NOT_REGISTERED and NOT_CURRENT_USER are device-local conclusions the SDK draws before or instead of calling the server. Handle all five values, not just the three in the API documentation.
SDK Error Codes
Beyond the API codes, the SDK raises three of its own.
| Field | Type | Description |
|---|---|---|
-1 | int | Thông tin không hợp lệ — invalid information. |
-2 | int | Secret token decryption failed. Android only. |
190302 | int | OTP không chính xác — incorrect OTP. Raised by sync time when unblocking with useOtp. |
Overriding the Base URL
Every SDK API call accepts an overrideBaseUrl to point at a different environment without re-initializing.
WARNING
On iOS, passing null or an empty string for overrideBaseUrl does not fall back to the configured host — the call fails with Unknown host name. Omit the parameter entirely rather than passing an empty value.
Next Steps
- Android SDK Integration — Kotlin integration guide
- iOS SDK Integration — Swift integration guide
- Error Codes — the API error tables