SDK Functionality
Working with subscription statuses
Getting a subscription status
AltcraftSDK
└── val pushSubscriptionFunctions: PublicPushSubscriptionFunctions
// Status of the profile’s latest subscription
├── suspend fun getStatusOfLatestSubscription(
│ context: Context
│ ): DataClasses.ResponseWithHttpCode?
// Status for the current token/provider
├── suspend fun getStatusForCurrentSubscription(
│ context: Context
│ ): DataClasses.ResponseWithHttpCode?
// Status of the latest subscription for the given provider (if null — current provider is used)
└── suspend fun getStatusOfLatestSubscriptionForProvider(
context: Context,
provider: String? = null
): DataClasses.ResponseWithHttpCode?
Subscription status request functions:
fun getStatusOfLatestSubscription()— status of the profile’s latest subscription;fun getStatusOfLatestSubscriptionForProvider()— status for the current token/provider;fun getStatusForCurrentSubscription()— status of the latest subscription by provider. Ifnullis passed, the current provider is used.
suspend fun getStatusOfLatestSubscription(context: Context): DataClasses.ResponseWithHttpCode?
Retrieves the status of the profile’s latest subscription. Returns a ResponseWithHttp? object containing response?.profile?.subscription — the latest subscription created in the profile. If no such subscription exists, null is returned.
Usage example:
// Status of the profile’s latest subscription
AltcraftSDK.pushSubscriptionFunctions.getStatusOfLatestSubscription(context)
suspend fun getStatusForCurrentSubscription(context: Context): DataClasses.ResponseWithHttpCode?
Retrieves the status for the current token/provider. Returns a ResponseWithHttp? object containing response?.profile?.subscription — the subscription found by the current push token and provider. If no such subscription exists, null is returned.
Usage example:
// Status matching the current token/provider
AltcraftSDK.pushSubscriptionFunctions.getStatusForCurrentSubscription(context)
suspend fun getStatusOfLatestSubscriptionForProvider(context: Context, provider: String? = null): DataClasses.ResponseWithHttpCode?
Retrieves the status of the latest subscription for a provider. Returns a ResponseWithHttp? object containing response?.profile?.subscription — the latest subscription created with the specified push provider. If the provider is not specified (provider = null), the current token’s provider is used. If no such subscription exists, null is returned.
// Latest subscription status for a provider (uses current if null)
AltcraftSDK.pushSubscriptionFunctions.getStatusOfLatestSubscriptionForProvider(context, provider = null)
Below is an example of extracting profile, subscription, and category data from a status response. This approach applies to all status-fetching functions:
Data from status functions
CoroutineScope(Dispatchers.IO).launch {
AltcraftSDK.pushSubscriptionFunctions
.getStatusForCurrentSubscription(this@App)
?.let { it ->
val httpCode = it.httpCode
val response = it.response
val error = response?.error
val errorText = response?.errorText
val profile = response?.profile
val subscription = profile?.subscription
val cats = subscription?.cats
}
}
Changing a subscription status
AltcraftSDK
└─ val pushSubscriptionFunctions: PublicPushSubscriptionFunctions
// Subscribe (status = SUBSCRIBED)
├─ fun pushSubscribe(
│ context: Context,
│ sync: Boolean = true,
│ profileFields: Map<String, Any?>? = null,
│ customFields: Map<String, Any?>? = null,
│ cats: List<DataClasses.CategoryData>? = null,
│ replace: Boolean? = null,
│ skipTriggers: Boolean? = null
│ ): Unit
// Suspend (status = SUSPENDED)
├─ fun pushSuspend(
│ context: Context,
│ sync: Boolean = true,
│ profileFields: Map<String, Any?>? = null,
│ customFields: Map<String, Any?>? = null,
│ cats: List<DataClasses.CategoryData>? = null,
│ replace: Boolean? = null,
│ skipTriggers: Boolean? = null
│ ): Unit
// Unsubscribe (status = UNSUBSCRIBED)
└─ fun pushUnSubscribe(
context: Context,
sync: Boolean = true,
profileFields: Map<String, Any?>? = null,
customFields: Map<String, Any?>? = null,
cats: List<DataClasses.CategoryData>? = null,
replace: Boolean? = null,
skipTriggers: Boolean? = null
): Unit
Subscription status change functions:
fun pushSubscribe()— subscribes to push notifications;fun pushUnSubscribe()— cancels the push subscription;fun pushSuspend()— suspends the push subscription (no notifications are delivered, and an unsubscribe event is not created in the user’s profile);fun unSuspendPushSubscription()— used to implementLogIn/LogOuttransitions.
These functions share the same signature with the following parameters:
context: Context
Required: Yes Description: Android Context.
sync: Boolean
Default: true
Required: No
Description: Flag that sets synchronous execution of the request.
Successful request execution:
On success, this group of functions emits an event with code 230 that contains event.value, which depends on the sync flag:
If sync == true
ResponseWithHttpCode
├─ httpCode: 200
└─ response
├─ error: 0
├─ errorText: ""
└─ profile
├─ id: "your id"
├─ status: "subscribed"
├─ isTest: false
└─ subscription
├─ subscriptionId: "your subscriptionId"
├─ hashId: "c52b28d2"
├─ provider: "ios-apns"
├─ status: "subscribed"
├─ fields
│ ├─ _os_ver: {"raw":"18.6.2","ver":"[\"18.0\", \"6.0\", \"2.0\"]"}
│ ├─ _device_type: "Mobile"
│ ├─ _ad_track: false
│ ├─ _device_name: "iPhone"
│ ├─ _os_language: "en"
│ ├─ _os_tz: "+0300"
│ ├─ _os: "IOS"
│ └─ _device_model: "iPhone14,7"
└─ cats
└─ [ { name: "developer_news", title: "dev_news", steady: false, active: false } ]
For synchronous requests, event.value["response_with_http_code"] exposes:
-
httpCode – transport status code;
-
Response – a public struct containing:
-
error: Int?— internal server error code (0 if no errors), -
errorText: String?— error text (empty if no errors), -
profile: ProfileData?— profile data if the request is successful:- profile info (ProfileData)
- subscription (SubscriptionData)
- subscription categories (CategoryData)
- if the request fails,
profile = nullwill be returned only
-
Data structures
public struct Response {
let error: Int? // Internal error code
let errorText: String? // Error text
let profile: ProfileData?
}
public struct ProfileData {
let subscription: SubscriptionData?
let cats: [CategoryData]?
}
public struct SubscriptionData {
// Subscription data
}
public struct CategoryData {
// Subscription category data
}
If sync == false
ResponseWithHttpCode
├─ httpCode: Int?
└─ response: Response?
├─ error: Int?
├─ errorText: String?
└─ profile: ProfileData? = null
For asynchronous requests, event.value["response_with_http_code"] exposes:
-
httpCode – transport status code;
-
Response – a public struct containing:
error: Int?— internal server error code (0 if no errors),errorText: String?— error text (empty if no errors),profile: ProfileData?— profile data, alwaysnullfor async requests.
Failed request execution:
If a request from this group fails, an event with one of the following codes will be emitted:
- 430 – error without automatic retry on the SDK side;
- 530 – error with automatic retry on the SDK side.
Event contents:
- only
httpCodeif the Altcraft server was unavailable; erroranderrorTextif the server returned an error.
Reading push event values
AltcraftSDK.eventSDKFunctions.subscribe { event ->
if (event.eventCode in listOf(230, 430, 530)) {
(event.eventValue?.get("response_with_http_code")
as? DataClasses.ResponseWithHttpCode)?.let { responseWithHttp ->
// HTTP code
val httpCode = responseWithHttp.httpCode
// Response
val response = responseWithHttp.response
val error = response?.error
val errorText = response?.errorText
// Profile
val profile = response?.profile
val profileId = profile?.id
val profileStatus = profile?.status
val profileIsTest = profile?.isTest
// Subscription
val subscription = profile?.subscription
val subscriptionId = subscription?.subscriptionId
val hashId = subscription?.hashId
val provider = subscription?.provider
val subscriptionStatus = subscription?.status
// Fields (Map<String, JsonElement>)
val fields = subscription?.fields
// Categories (List<CategoryData>)
val cats = subscription?.cats
val firstCat = cats?.firstOrNull()
val catName = firstCat?.name
val catTitle = firstCat?.title
val catSteady = firstCat?.steady
val catActive = firstCat?.active
}
}
profileFields:Map<String, Any?>?
Default: null
Required: No
Description: A map containing profile fields.
The parameter may include system fields (e.g., _fname — first name or _lname — last name) as well as optional fields (pre-created manually in the platform UI). Allowed JSON-compatible structures:
- Scalar values:
- String
- Boolean
- Int
- Long
- Float
- Double
null
- Objects:
Map<String, *> - Lists:
List<*> - Array of maps:
Array<Map<String, *>>
If an invalid optional field is passed, the request will fail with:
SDK error: 430
http code: 400
error: 400
errorText: Platform profile processing error: with field "field_name": Incorrect field
customFields:Map<String, Any?>?
Default: null
Required: No
Description: A map containing subscription fields.
May include system fields (e.g., _device_model — device model or _os — operating system) as well as optional fields (pre-created manually in the platform UI). Allowed value types (JSON-compatible, scalars only):
- String
- Boolean
- Int
- Long
- Float
- Double
null
If an invalid optional field is passed, the request will fail with:
SDK error: 430
http code: 400
error: 400
errorText: Platform profile processing error: field "field_name" is not valid: failed convert custom field
Most subscription system fields are collected automatically by the SDK and added to push requests. These include: "_os", "_os_tz", "_os_language", "_device_type", "_device_model", "_device_name", "_os_ver", "_ad_track", "_ad_id".
cats:listOf(CategoryData)
Default: null
Required: No
Description: Subscription categories.
Category structure:
data class CategoryData(
val name: String? = null,
val title: String? = null,
val steady: Boolean? = null,
val active: Boolean? = null
)
When sending a push request with categories, use only the name (category name) and active (category active status) fields; other fields are not used for request processing. title and steady are populated when retrieving subscription info.
Example:
val cats = listOf(
DataClasses.CategoryData(name = "football", active = true),
DataClasses.CategoryData(name = "hockey", active = true)
)
Categories used in the request must be created beforehand and added to the resource in the Altcraft platform. If a category not present in the resource is used, the request will fail:
SDK error: 430
http code: 400
error: 400
errorText: Platform profile processing error: field "subscriptions.cats" is not valid: category not found in resource
replace:Boolean?
Default: null
Required: No
Description: When enabled, all subscriptions of other profiles with the same push token in the current database are set to unsubscribed after a successful request.
skipTriggers:Boolean?
Default: null
Required: No
Description: When enabled, the profile containing this subscription will be ignored by campaign and scenario triggers.
Request implementation examples
Example: subscribing to push notifications
Minimal working setup:
AltcraftSDK.pushSubscriptionFunctions.pushSubscribe(context)
Passing all available parameters:
AltcraftSDK.pushSubscriptionFunctions.pushSubscribe(
context = this,
sync = true,
profileFields = mapOf("_fname" to "Andrey", "_lname" to "Pogodin"),
customFields = mapOf("developer" to true),
cats = listOf(DataClasses.CategoryData(name = "developer_news", active = true)),
replace = false,
skipTriggers = false
)
For pushSubscribe, pushSuspend, and pushUnSubscribe, the SDK automatically retries the request if the HTTP status code is in 500..599. No retry occurs for codes outside this range.
Function unSuspendPushSubscription()
The function fun unSuspendPushSubscription() is intended to implement LogIn/LogOut transitions. It works as follows:
- searches for subscriptions with the same push token as the current one that do not belong to the profile referenced by the current JWT token;
- changes the status of the found subscriptions from
subscribedtosuspended; - changes the status of subscriptions in the profile referenced by the current JWT from
suspendedtosubscribed(if the JWT-referenced profile exists and contains subscriptions); - returns a
ResponseWithHttpCode?data class in whichresponse.profileis the current profile referenced by the JWT (if the profile does not exist,response.profilewill benull).
Recommended LogIn / LogOut implementation
LogIn transition:
- An anonymous user enters the app. The user is assigned
JWT_1, pointing to database #1Anonymous. - A push subscription is created; the profile is created in #1Anonymous.
- The user registers and is assigned
JWT_2, pointing to database #2Registered. - Call
unSuspendPushSubscription()— the anonymous user’s subscription in #1Anonymous is suspended. - Search the profile in #2Registered to restore the subscription.
- Since a subscription with this push token does not exist in #2Registered,
unSuspendPushSubscription()returnsnull. - After receiving
null, callpushSubscribe()to create a new profile in #2Registered.
LogOut transition:
- The user logs out in the app (
LogOut). - The user is assigned
JTW_1, pointing to database #1Anonymous. - Call
unSuspendPushSubscription(), which will suspend the subscription in #2Registered and set the subscription status in #1Anonymous tosubscribed. - The request returns
#1Anonymous != null— the subscription already exists; no new one is required.
Example:
private suspend fun unSuspend(context: Context, logIn: Boolean) {
// Change JWT before the request
setAuth(context, logIn)
AltcraftSDK.pushSubscriptionFunctions
.unSuspendPushSubscription(context)
?.let { result ->
if (result.httpCode == 200 && result.response?.profile?.subscription == null) {
AltcraftSDK.pushSubscriptionFunctions.pushSubscribe(
context = context
// Specify required params
)
}
}
}
fun logIn(context: Context) = CoroutineScope(Dispatchers.IO).launch { unSuspend(context, true) }
fun logOut(context: Context) = CoroutineScope(Dispatchers.IO).launch { unSuspend(context, false) }
Managing provider push tokens
AltcraftSDK
└── val pushTokenFunctions: PublicPushTokenFunctions
|
// Save a token manually (onNewToken)
├── fun setPushToken(context: Context, provider: String, token: String): Unit
|
// Get current device token data
├── suspend fun getPushToken(context: Context): DataClasses.TokenData?
|
// Set Firebase Cloud Messaging provider (null — remove)
├── fun setFCMTokenProvider(provider: FCMInterface?): Unit
|
// Set Huawei Mobile Services provider (null — remove)
├── fun setHMSTokenProvider(provider: HMSInterface?): Unit
|
// Set RuStore provider (null — remove)
├── fun setRuStoreTokenProvider(provider: RustoreInterface?): Unit
|
// Delete the push token for the specified provider
├── suspend fun deleteDeviceToken(context: Context, provider: String, complete: () -> Unit): Unit
|
// Force token refresh (delete → refresh)
├── fun forcedTokenUpdate(context: Context, complete: () -> Unit): Unit
|
// Change provider priority list and trigger token refresh
└── suspend fun changePushProviderPriorityList(context: Context, priorityList: List<String>): Unit
SDK functions for working with a provider token:
fun setPushToken()— manually set the device push token and provider inUserDefaults;fun getPushToken()— get the current push token;fun setFCMTokenProvider()— set or clear the FCM push token;fun setHMSTokenProvider()— set or clear the HMS push token;fun setRuStoreTokenProvider()— set or clear the RuStore push token;fun changePushProviderPriorityList()— dynamically switch provider and refresh the subscription’s push token;fun deleteDeviceToken()— delete the push token of the specified provider;fun forcedTokenUpdate()— delete the current push token and then refresh it.
fun setPushToken(context: Context, provider: String, token: String): Unit
Used to manually set the device push token and provider. Should be called in the push provider service’s onNewToken(). Serves as a simplified way to pass the token to the SDK without implementing provider interfaces.
Using this function to pass the token is not recommended. The recommended approach is to implement FCMInterface, HMSInterface, or APNSInterface.
Usage example:
// Manually save the token (onNewToken)
AltcraftSDK.pushTokenFunctions.setPushToken(context, provider, token)
Passing a token in FCMService.onNewToken():
class FCMService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
// Pass the new token manually
AltcraftSDK.pushTokenFunctions.setPushToken(this, FCM_PROVIDER, token)
}
override fun onDeletedMessages() {}
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
AltcraftSDK.PushReceiver.takePush(this@FCMService, message.data)
}
}
suspend fun getPushToken(context: Context): DataClasses.TokenData?
The function returns the current device push-token data and its provider as the data class TokenData(val provider: String, val token: String). If the token is unavailable, null will be returned.
Usage example:
// Get current push token data
AltcraftSDK.pushTokenFunctions.getPushToken(context)
Example of a push token data request:
CoroutineScope(Dispatchers.IO).launch {
AltcraftSDK.pushTokenFunctions.getPushToken(context).let {
val provider = it?.provider
val token = it?.token
}
}
fun setFCMTokenProvider(provider: FCMInterface?): Unit
Sets or removes the Firebase Cloud Messaging push-token provider. To disable the provider, pass null.
Usage example:
// Set Firebase Cloud Messaging provider (null — remove)
AltcraftSDK.pushTokenFunctions.setFCMTokenProvider(FCMProvider())
Call setFCMTokenProvider() in Application.onCreate() before calling AltcraftSDK.initialization(). This guarantees registration at the start of the app process, regardless of the lifecycle state and whether the app is running in the foreground or background.
fun setHMSTokenProvider(provider: HMSInterface?): Unit
Sets or removes the Huawei Mobile Services push-token provider. To disable the provider, pass null.
Usage example:
// Set Huawei Mobile Services provider (null — remove)
AltcraftSDK.pushTokenFunctions.setHMSTokenProvider(HMSProvider())
Call setHMSTokenProvider() in Application.onCreate() before calling AltcraftSDK.initialization(). This guarantees registration at the start of the app process, regardless of the lifecycle state and whether the app is running in the foreground or background.
fun setRuStoreTokenProvider(provider: RustoreInterface?): Unit
Sets or removes the RuStore push-token provider. To disable the provider, pass null.
Usage example:
// Set RuStore provider (null — remove)
AltcraftSDK.pushTokenFunctions.setRustoreTokenProvider(RustoreProvider())
Call setRustoreTokenProvider() in Application.onCreate() before calling AltcraftSDK.initialization(). This guarantees registration at the start of the app process, regardless of the lifecycle state and whether the app is running in the foreground or background.
suspend fun changePushProviderPriorityList(context: Context, priorityList: List<String>): Unit
Allows dynamic switching of the push provider with subscription token refresh. Pass a new list with a different provider order, for example: listOf(HMS_PROVIDER, RUSTORE_PROVIDER, FCM_PROVIDER).
// Apply a new provider priority list and trigger token refresh
AltcraftSDK.pushTokenFunctions.changePushProviderPriorityList(context, listOf(HMS_PROVIDER, RUSTORE_PROVIDER, FCM_PROVIDER))
suspend fun deleteDeviceToken(context: Context, provider: String, complete: () -> Unit): Unit
Deletes the push token for the specified provider. The token is invalidated and removed from the device’s local cache and from the push-provider’s server. After deletion, a new token can be requested.
// Delete the push token for the given provider (invalidate locally and on the server)
AltcraftSDK.pushTokenFunctions.deleteDeviceToken(context, provider) {
// callback after deletion
}
fun forcedTokenUpdate(context: Context, complete: () -> Unit): Unit
Deletes the current push token and then refreshes it.
Usage example:
// Force token refresh (delete → update)
AltcraftSDK.pushTokenFunctions.forcedTokenUpdate(context) {
// callback after update
}
Example of provider registration
We do not recommend using the setPushToken function to set a push token manually. Instead, configure token retrieval functions separately for each provider you use. Below is an example implementation of this approach:
Recommended provider registration method
class App : Application() {
override fun onCreate() {
super.onCreate()
// initialize RuStore provider
RuStorePushClient.init(this, "rustore project id")
// set JWT provider
AltcraftSDK.setJWTProvider(JWTProvider(applicationContext))
// set FCM provider
AltcraftSDK.pushTokenFunctions.setFCMTokenProvider(FCMProvider())
// set HMS provider
AltcraftSDK.pushTokenFunctions.setHMSTokenProvider(HMSProvider())
// set RuStore provider
AltcraftSDK.pushTokenFunctions.setRuStoreTokenProvider(RuStoreProvider())
// create AltcraftConfiguration
val config = AltcraftConfiguration.Builder(
apiUrl = "your api url",
R.drawable.ic_altcraft_label
).build()
// initialize SDK
AltcraftSDK.initialization(context = this@App, configuration = config)
}
}
Passing push notifications to the SDK
PushReceiver is a public class that contains the function that accepts notifications.
AltcraftSDK
└── open class PushReceiver
// Incoming push handling
├── open fun pushHandler(
│ context: Context,
│ message: Map<String, String>
│ ): Unit
// SDK entry point for push delivery
└── companion object
└── fun takePush(
context: Context,
message: Map<String, String>
): Unit
Functions for passing push notifications to the SDK:
fun takePush()— accepts notifications in the push providers’ service for further processing on the SDK side;fun pushHandler()— launches the standard Altcraft push-notification handling mechanism in the SDK.
Receiving a notification
fun takePush(context: Context, message: Map<String, String>): Unit
Accepts push notifications for further processing on the SDK side.
Usage example:
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
AltcraftSDK.PushReceiver.takePush(this@FCMService, message.data)
}
// message.data — message payload
Handling a notification
open fun pushHandler(context: Context, message: Map<String, String>): Unit
Starts the standard Altcraft push-notification handling mechanism in the SDK.
Receiving notifications in any app package (optional)
To receive notifications in any application package, do the following:
Step 1. Create an AltcraftPushReceiver class extending PushReceiver. Override the pushHandler() function in this class:
import android.content.Context
import androidx.annotation.Keep
import com.altcraft.sdk.AltcraftSDK
@Keep
class AltcraftPushReceiver : AltcraftSDK.PushReceiver() {
override fun pushHandler(context: Context, message: Map<String, String>) {
// standard processing of push messages and displaying notifications
super.pushHandler(context, message)
}
}
The class must be named AltcraftPushReceiver. If you name it differently, the SDK will not be able to find it to deliver the notification.
Step 2. Depending on your business goals, configure the logic of the AltcraftPushReceiver class:
-
If you want the SDK to handle and display notifications:
- use
super.pushHandler(context, message).
- use
-
If you want to handle notifications yourself:
- do not call
super.pushHandler(); - manually register open events using the
openEvent()function; otherwise, it will not be registered by the Altcraft platform.
- do not call
“deliveryEvent” delivery events are registered automatically. Creating AltcraftPushReceiver classes does not affect the registration of this event.
If you created multiple AltcraftPushReceiver classes, calling super.pushHandler() in each of them will display a message to the user. To avoid duplicate notifications, call super.pushHandler() in only one class.
Step 3. Add the package names that contain AltcraftPushReceiver classes to the pushReceiverModules configuration parameter. After that, the SDK will automatically detect the presence of AltcraftPushReceiver classes in the specified packages via reflection.
If the application code will be obfuscated, the class must be annotated with @Keep or added to the R8/ProGuard rules, otherwise the SDK will not be able to discover it.
Example of adding a package to the pushReceiverModules parameter:
pushReceiverModules = listOf(
context.packageName, // application package
"com.altcraft.altcraftmobile.test"
)
Mobile Events
// Function of the PublicMobileEventFunction object
AltcraftSDK
└── val mobileEventFunction: PublicMobileEventFunction
// Send a mobile event to the server
└── fun mobileEvent(
context: Context,
sid: String,
eventName: String,
sendMessageId: String? = null,
payload: Map<String, Any?>? = null,
matching: Map<String, Any?>? = null,
matchingType: String? = null,
profileFields: Map<String, Any?>? = null,
subscription: DataClasses.Subscription? = null,
utm: DataClasses.UTM? = null
): Unit
To register a mobile event, use the mobileEvent() function. It has the following parameters:
context: Context
Required: Yes
Description: Android Context.
sid: String
Required: Yes
Description: String identifier of the pixel to which mobile events are linked.
eventName: String
Required: Yes
Description: The name of the mobile event.
sendMessageId: String?
Required: No
Description: SMID identifier of the sent message (if the event is associated with a specific campaign).
payload: String
Required: No
Description: Event data — a map with string keys and values, where only scalar data types are allowed:
- String
- Boolean
- Int
- Long
- Float
- Double
null
matching: Map<String, Any?>?
Required: No
Description: A map for passing values with matching types and identifiers.
matchingType: String?
Required: No
Description: The type of matching.
profileFields: Map<String, Any?>?
Required: No
Description: Profile fields — a map with string keys and JSON-compatible values:
-
Scalar values:
- String
- Boolean
- Int
- Long
- Float
- Double
null
-
Objects:
Map<String, *> -
Lists:
List<*> -
Arrays of maps:
Array<Map<String, *>>
This parameter is used only when working with JWT authorization.
utm: DataClasses.UTM?
Required: No
Description: UTM tags. Added using the UTM data class, where each UTM type is a separate parameter.
data class UTM (
val campaign: String? = null,
val content: String? = null,
val keyword: String? = null,
val medium: String? = null,
val source: String? = null,
val temp: String? = null
)
subscription: DataClasses.Subscription?
Required: No
Description: Parameter for adding a subscription for a selected channel.
Possible values are implementations (subtypes) of the sealed interface Subscription:
EmailSubscription— email subscriptionSmsSubscription— SMS subscriptionPushSubscription— push subscriptionCcDataSubscription— subscription in Telegram, WhatsApp, Viber, or Notify.
Used only when working with JWT authorization.
Implementations of the Subscription interface
General model: Subscription
Purpose — base (sealed) interface for all types of subscriptions.
Serialization is polymorphic, with the discriminator field channel.
Common fields (for all implementations):
| Field | Type | Required | Description |
|---|---|---|---|
resource_id | Int | Yes | Identifier of the subscription resource/source |
status | String? | No | Subscription status (e.g., active/suspended) |
priority | Int? | No | Delivery priority for the subscription |
custom_fields | Map<String, Any?>? | No | Custom fields (key–value) for extended segmentation |
cats | List<String>? | No | Subscription categories |
channel | String | Yes | Channel type; defined by the implementation |
Subscription types:
1. Email channel subscription
EmailSubscription (channel = "email")
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
email | String | Yes | Recipient email address |
Notes: channel is always "email".
2. SMS channel subscription
SmsSubscription (channel = "sms")
Purpose: subscription to the SMS channel.
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
phone | String | Yes | Phone number in international format |
Notes: channel is always "sms".
3. Push notification subscription
PushSubscription (channel = "push")
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
provider | String | Yes | Provider (e.g., "android-firebase", etc.) |
subscription_id | String | Yes | Unique provider subscription identifier |
Notes: channel is always "push".
4. Subscription for custom communication channels
CcDataSubscription (channel ∈ {"telegram_bot","whatsapp","viber","notify"})
Additional fields:
| Field | Type | Required | Description |
|---|---|---|---|
channel | String | Yes | One of: "telegram_bot", "whatsapp", "viber", "notify". |
cc_data | JsonObject | Yes | Channel-specific data (e.g., chat ID, phone number, tokens). |
Notes: channel must explicitly match one of the supported values.
Receiving SDK Events in the Application
// Functions of the Events object
AltcraftSDK
└── val eventSDKFunctions: Events
// Subscribe to SDK events (replaces the existing subscriber)
├── fun subscribe(
│ newSubscriber: (DataClasses.Event) -> Unit
│ ): Unit
// Unsubscribe from events
└── fun unsubscribe(): Unit
The application can have only one active subscriber to SDK events.
Event Subscription
fun subscribe(newSubscriber: (DataClasses.Event) -> Unit): Unit
Used to subscribe and receive SDK events in the application.
When an SDK event occurs, it calls the callback and passes an instance of the Event class (or one of its subclasses).
Usage example:
AltcraftSDK.eventSDKFunctions.subscribe { event ->
// Handle event
}
All events provided by the SDK are instances of Event or its subclasses:
- Event — general event (info, successful requests);
- Error — error event;
- RetryError — error event for a request that will be automatically retried by the SDK.
Each event contains the following fields:
- function — the name of the function that triggered the event;
- eventCode — internal SDK event code (see "SDK Events");
- eventMessage — event message;
- eventValue — arbitrary
[String: Any?]?data passed as event payload; - date — timestamp of the event.
SDK Events
open class Event(
val function: String,
val eventCode: Int? = null,
val eventMessage: String? = null,
val eventValue: Map<String, Any?>? = null,
val date: Date = Date(),
)
open class Error(
function: String,
eventCode: Int? = 0,
eventMessage: String? = null,
eventValue: Map<String, Any?>? = null,
date: Date = Date(),
) : Event(function, eventCode, eventMessage, eventValue, date)
class RetryError(
function: String,
eventCode: Int? = 0,
eventMessage: String? = null,
eventValue: Map<String, Any?>? = null,
date: Date = Date(),
) : Error(function, eventCode, eventMessage, eventValue, date)
Example of a successful push subscription event
├─ function: processResponseprocessResponse
├─ eventCode: 230
├─ eventMessage: "successful request: push/subscribe"
├─ eventValue
│ ├─ http code: 200
│ └─ response
│ ├─ error: 0
│ ├─ errorText: ""
│ └─ profile
│ ├─ id: "your id"
│ ├─ status: "subscribed"
│ ├─ isTest: false
│ └─ subscription
│ ├─ subscriptionId: "your subscriptionId"
│ ├─ hashId: "c52b28d2"
│ ├─ provider: "android-firebase"
│ ├─ status: "subscribed"
│ ├─ fields
│ │ ├─ _device_name: "Pixel 7"
│ │ ├─ _device_model: "Google Pixel 7"
│ │ ├─ _os_tz: "+0300"
│ │ ├─ _os_language: "ru"
│ │ ├─ _os_ver: {"raw":"14","ver":[14]}
│ │ ├─ _ad_track: true
│ │ ├─ _os: "Android"
│ │ └─ _device_type: "Mobile"
│ └─ cats
│ └─ [ { name: "developer_news", title: "dev_news", steady: false, active: false } ]
└─ date: 2025-09-03 09:01:44 +0000
Unsubscribing from events
fun unsubscribe(): Unit
This function unsubscribes from SDK events. It stops event delivery while keeping the callback assigned.
Usage example:
// Unsubscribe from SDK events
AltcraftSDK.eventSDKFunctions.unsubscribe()
Additional SDK Functions
Manual Push Event Registration
These functions are only used if you implement your own notification handling logic and do not pass them to the Altcraft SDK. By default, the Altcraft SDK automatically processes notifications, so these methods are only required when you need custom client-side handling.
// Functions of the PublicPushEventFunctions object
AltcraftSDK
└── val pushEventFunction: PublicPushEventFunctions
// Register Altcraft push delivery (triggers delivery event)
├── fun deliveryEvent(
│ context: Context,
│ message: Map<String, String>? = null,
│ uid: String? = null
│ ): Unit
// Register Altcraft push open (triggers open event)
└── fun openEvent(
context: Context,
message: Map<String, String>? = null,
uid: String? = null
): Unit
Manual event registration functions:
fun deliveryEvent()— registers push delivery;fun openEvent()— registers push open.
fun deliveryEvent(context: Context, message: Map<String, String>? = null, uid: String? = null): Unit
Registers a push delivery event manually on the Altcraft platform.
To log the event on the server, pass the notification data in the message or uid parameter.
Usage example:
// Register Altcraft push delivery (triggers delivery event)
AltcraftSDK.pushEventFunction.deliveryEvent(context, message, uid)
fun openEvent(context: Context, message: Map<String, String>? = null, uid: String? = null): Unit
Registers a push open event manually on the Altcraft platform.
To log the event on the server, pass the notification data in the message or uid parameter.
Usage example:
// Register Altcraft push open (triggers open event)
AltcraftSDK.pushEventFunction.openEvent(context, message, uid)
SDK Data Clearing
fun clear(context: Context, onComplete: (() -> Unit)? = null)
This function clears all SDK data and cancels all pending background tasks.
It cancels WorkManager jobs, deletes Room database entries, and clears SharedPreferences.
Usage example:
AltcraftSDK
// Full SDK data cleanup (DB, SharedPreferences, background tasks)
└── fun clear(
context: Context,
onComplete: (() -> Unit)? = null
): Unit
The function includes an optional completion parameter, which is called after cleanup and task cancellation are complete.
Functional Profile Field Update
AltcraftSDK
└─ val pushSubscriptionFunctions: PublicPushSubscriptionFunctions
└─ fun actionField(key: String): ActionFieldBuilder
fun actionField(key: String): ActionFieldBuilder
A helper function for simplifying the functional profile field update process. It supports the following operations:
.set(value)
.unset(value)
.incr(value)
.add(value)
.delete(value)
.upsert(value)
Usage example:
AltcraftSDK.pushSubscriptionFunctions.pushSubscribe(
context = context,
// "_fname" — field to be changed
// .set("Andrey") — command that sets the value "Andrey" for this field
profileFields = AltcraftSDK.pushSubscriptionFunctions
.actionField("_fname").set("Andrey")
)
Resetting the performPushModuleCheck() Restriction
The performPushModuleCheck() function runs background jobs that handle push-notification-related retries and device token refresh requests.
Its execution is limited to a single run within one application process lifecycle.
Sometimes, you may need to reset this restriction. In such cases, use the function described below.
fun reinitializePushModuleInThisSession(): Unit
This function resets the flag preventing repeated execution of performPushModuleCheck().
Requesting Notification Permission
Starting from Android 13 (API 33, Tiramisu), apps must explicitly request the POST_NOTIFICATIONS permission before sending notifications.
On earlier Android versions, this call is not required — the permission is granted automatically.
fun requestNotificationPermission(context: Context, activity: ComponentActivity)
Checks the current notification permission status and, if necessary, displays the system permission request dialog to the user. If the user has previously denied notifications, calling this function again will re-prompt the permission dialog.