Files
simplex-chat/apps/multiplatform/spec/api.md
2026-02-26 17:54:44 +00:00

40 KiB

Chat API Reference

Table of Contents

  1. Overview
  2. Command Categories
  3. Response Types
  4. Event Types
  5. Error Types
  6. Source Files

1. Overview

The SimpleX Chat API bridge connects Kotlin/Compose UI code to the Haskell core via JNI. All communication follows a command/response JSON protocol:

Kotlin suspend fun api*()
  -> ChatController.sendCmd(rhId, CC.*, ctrl)
       -> serialize CC to cmdString (JSON)
       -> chatSendCmdRetry(ctrl, cmdString, retryNum)   [JNI / external fun]
            -> Haskell core processes command
            -> returns JSON response string
       -> json.decodeFromString<API>(responseString)
            -> API.Result(rhId, CR.*) or API.Error(rhId, ChatError)
  -> pattern-match on CR subclass -> update ChatModel / return data to UI

Key types in the pipeline:

Type Role Location
CC (sealed class) Command definitions (~165 subclasses) SimpleXAPI.kt#L3529
API (sealed class) Top-level response wrapper (Result / Error) SimpleXAPI.kt#L5975
CR (sealed class) Chat response variants (~180 subclasses) SimpleXAPI.kt#L6114
ChatError (sealed class) Error hierarchy SimpleXAPI.kt#L6974
ChatController (object) Singleton hosting all api* functions SimpleXAPI.kt#L493

JNI bridge functions (declared in Core.kt#L25):

external fun chatMigrateInit(dbPath: String, dbKey: String, confirm: String): Array<Any>
external fun chatCloseStore(ctrl: ChatCtrl): String
external fun chatSendCmdRetry(ctrl: ChatCtrl, msg: String, retryNum: Int): String
external fun chatSendRemoteCmdRetry(ctrl: ChatCtrl, rhId: Int, msg: String, retryNum: Int): String
external fun chatRecvMsg(ctrl: ChatCtrl): String
external fun chatRecvMsgWait(ctrl: ChatCtrl, timeout: Int): String

sendCmd flow (SimpleXAPI.kt#L804):

  1. Obtains the ChatCtrl handle (or uses the provided otherCtrl).
  2. Serializes the CC command to its cmdString.
  3. Dispatches to Dispatchers.IO; calls chatSendCmdRetry (local) or chatSendRemoteCmdRetry (remote host).
  4. Decodes the returned JSON string into API.
  5. Logs the result to the terminal item list.

Asynchronous event receiver (startReceiver, SimpleXAPI.kt#L660):

A long-running coroutine on Dispatchers.IO repeatedly calls chatRecvMsgWait (blocking JNI). Each received API message is dispatched to processReceivedMsg (SimpleXAPI.kt#L2568), which pattern-matches on CR subclasses to update ChatModel state and trigger notifications.


2. Command Categories

All functions below are suspend fun members of ChatController (SimpleXAPI.kt#L493). The rh / rhId parameter is Long? identifying a remote host (null = local device).

2.1 User Management

Command Parameters Description Line
apiGetActiveUser rh: Long?, ctrl: ChatCtrl? Fetch the currently active user profile L841
apiCreateActiveUser rh: Long?, p: Profile?, pastTimestamp: Boolean, ctrl: ChatCtrl? Create a new user profile and set it as active L851
listUsers rh: Long? List all user profiles sorted by display name L871
apiSetActiveUser rh: Long?, userId: Long, viewPwd: String? Switch the active user to a different profile L881
apiSetAllContactReceipts rh: Long?, enable: Boolean Enable/disable delivery receipts for all contacts globally L888
apiSetUserContactReceipts u: User, userMsgReceiptSettings: UserMsgReceiptSettings Set delivery receipt settings for user contacts L894
apiSetUserGroupReceipts u: User, userMsgReceiptSettings: UserMsgReceiptSettings Set delivery receipt settings for user groups L900
apiSetUserAutoAcceptMemberContacts u: User, enable: Boolean Toggle auto-accept for member contact requests L906
apiHideUser u: User, viewPwd: String Hide a user profile behind a password L912
apiUnhideUser u: User, viewPwd: String Unhide a previously hidden user profile L915
apiMuteUser u: User Mute all notifications for a user profile L918
apiUnmuteUser u: User Unmute notifications for a user profile L921
apiDeleteUser u: User, delSMPQueues: Boolean, viewPwd: String? Delete a user profile and optionally its SMP queues L930
apiUpdateProfile rh: Long?, profile: Profile Update the active user's display profile L1682
apiSetProfileAddress rh: Long?, on: Boolean Enable/disable including address in user profile L1694
apiSetUserUIThemes rh: Long?, userId: Long, themes: ThemeModeOverrides? Set UI theme overrides for a user L1732

2.2 Chat Lifecycle

Command Parameters Description Line
apiStartChat ctrl: ChatCtrl? Start the chat engine (returns true if newly started) L937
apiStopChat (none) Stop the chat engine L955
apiSetAppFilePaths filesFolder, tempFolder, assetsFolder, remoteHostsFolder: String, ctrl: ChatCtrl? Configure file-system paths for the Haskell core L961
apiSetEncryptLocalFiles enable: Boolean Enable/disable encryption of locally stored files L967
apiSaveAppSettings settings: AppSettings Persist application settings to the core L969
apiGetAppSettings settings: AppSettings Retrieve application settings from the core L975
apiGetChats rh: Long? Fetch the list of all chats for the active user L1013
apiGetChat rh, type, id, scope, contentTag, pagination, search Fetch a single chat with paginated messages L1031
apiGetChatContentTypes rh: Long?, type: ChatType, id: Long, scope: GroupChatScope? Get available content type filters for a chat L1044
apiClearChat rh: Long?, type: ChatType, id: Long Delete all messages in a chat L1675
apiDeleteChat rh: Long?, type: ChatType, id: Long, chatDeleteMode: ChatDeleteMode Delete a chat (contact, group, connection, etc.) L1620
apiChatRead rh: Long?, type: ChatType, id: Long Mark a chat as read L1888
apiChatItemsRead rh, type, id, scope, itemIds Mark specific chat items as read L1902
apiChatUnread rh: Long?, type: ChatType, id: Long, unreadChat: Boolean Toggle a chat's unread flag L1909
getChatItemTTL rh: Long? Get the auto-delete TTL for chat items L1286
setChatItemTTL rh: Long?, chatItemTTL: ChatItemTTL Set the auto-delete TTL for chat items L1299
setChatTTL rh: Long?, chatType, id, chatItemTTL Set TTL for a specific chat L1306

2.3 Message Operations

Command Parameters Description Line
apiSendMessages rh, type, id, scope, live, ttl, composedMessages Send one or more messages to a chat L1074
apiCreateChatItems rh: Long?, noteFolderId: Long, composedMessages: List<ComposedMessage> Create items in a private notes folder L1111
apiReportMessage rh, groupId, chatItemId, reportReason, reportText Report a message in a group L1119
apiGetChatItemInfo rh, type, id, scope, itemId Get delivery info for a specific chat item L1126
apiForwardChatItems rh, toChatType, toChatId, toScope, fromChatType, fromChatId, fromScope, itemIds, ttl Forward messages between chats L1133
apiPlanForwardChatItems rh, fromChatType, fromChatId, fromScope, chatItemIds Check forward feasibility before forwarding L1138
apiUpdateChatItem rh, type, id, scope, itemId, updatedMessage, live Edit an existing message L1145
apiChatItemReaction rh, type, id, scope, itemId, add, reaction Add or remove a reaction to a message L1168
apiGetReactionMembers rh: Long?, groupId: Long, itemId: Long, reaction: MsgReaction List members who reacted with a specific emoji L1175
apiDeleteChatItems rh, type, id, scope, itemIds, mode Delete messages (for self or for everyone) L1183
apiDeleteMemberChatItems rh: Long?, groupId: Long, itemIds: List<Long> Moderate: delete another member's messages L1190
apiArchiveReceivedReports rh: Long?, groupId: Long Archive all received reports in a group L1197
apiDeleteReceivedReports rh: Long?, groupId: Long, itemIds: List<Long>, mode: CIDeleteMode Delete specific received reports L1204

2.4 Group Operations

Command Parameters Description Line
apiNewGroup rh: Long?, incognito: Boolean, groupProfile: GroupProfile Create a new group L2092
apiAddMember rh: Long?, groupId: Long, contactId: Long, memberRole: GroupMemberRole Invite a contact to a group L2100
apiJoinGroup rh: Long?, groupId: Long Accept a group invitation L2109
apiAcceptMember rh: Long?, groupId: Long, groupMemberId: Long, memberRole: GroupMemberRole Accept a member joining via group link L2135
apiDeleteMemberSupportChat rh: Long?, groupId: Long, groupMemberId: Long Delete a member's support chat L2144
apiRemoveMembers rh: Long?, groupId: Long, memberIds: List<Long>, withMessages: Boolean Remove members from a group L2151
apiMembersRole rh: Long?, groupId: Long, memberIds: List<Long>, memberRole: GroupMemberRole Change the role of group members L2160
apiBlockMembersForAll rh: Long?, groupId: Long, memberIds: List<Long>, blocked: Boolean Block/unblock members for all group participants L2169
apiLeaveGroup rh: Long?, groupId: Long Leave a group L2178
apiListMembers rh: Long?, groupId: Long List all members of a group L2185
apiUpdateGroup rh: Long?, groupId: Long, groupProfile: GroupProfile Update group profile (name, image, etc.) L2192
apiCreateGroupLink rh: Long?, groupId: Long, memberRole: GroupMemberRole Create a group invitation link L2211
apiGroupLinkMemberRole rh: Long?, groupId: Long, memberRole: GroupMemberRole Update the default role for group link joins L2226
apiDeleteGroupLink rh: Long?, groupId: Long Delete the group invitation link L2235
apiGetGroupLink rh: Long?, groupId: Long Retrieve the current group invitation link L2245
apiAddGroupShortLink rh: Long?, groupId: Long Create a short link for the group L2252
apiCreateMemberContact rh: Long?, groupId: Long, groupMemberId: Long Create a direct contact from a group member L2262
apiSendMemberContactInvitation rh: Long?, contactId: Long, mc: MsgContent Send a direct message invitation to a group member L2271
apiAcceptMemberContact rh: Long?, contactId: Long Accept a member's direct contact invitation L2280
apiSetMemberSettings rh: Long?, groupId: Long, groupMemberId: Long, memberSettings: GroupMemberSettings Configure per-member settings (e.g., mentions) L1343
apiGroupMemberInfo rh: Long?, groupId: Long, groupMemberId: Long Get a group member's info and connection stats L1353
apiSetGroupAlias rh: Long?, groupId: Long, localAlias: String Set a local alias for a group L1718

2.5 Contact Operations

Command Parameters Description Line
apiAddContact rh: Long?, incognito: Boolean Create a one-time invitation link for a new contact L1444
apiSetConnectionIncognito rh: Long?, connId: Long, incognito: Boolean Toggle incognito on a pending connection L1455
apiChangeConnectionUser rh: Long?, connId: Long, userId: Long Change the user profile on a pending connection L1464
apiConnectPlan rh: Long?, connLink: String, inProgress: MutableState<Boolean> Analyze a connection link before connecting L1474
apiConnect rh: Long?, incognito: Boolean, connLink: CreatedConnLink Connect via an invitation or address link L1482
apiPrepareContact rh, connLink, contactShortLinkData Prepare a contact chat from a short link (before connecting) L1546
apiPrepareGroup rh, connLink, groupShortLinkData Prepare a group chat from a short link (before connecting) L1555
apiConnectPreparedContact rh, contactId, incognito, msg Connect to a previously prepared contact L1580
apiConnectPreparedGroup rh, groupId, incognito, msg Join a previously prepared group L1590
apiConnectContactViaAddress rh: Long?, incognito: Boolean, contactId: Long Connect to a contact using their public address L1600
apiDeleteContact rh: Long?, id: Long, chatDeleteMode: ChatDeleteMode Delete a contact and return the deleted Contact L1644
apiContactInfo rh: Long?, contactId: Long Get a contact's connection stats and custom profile L1346
apiSetContactAlias rh: Long?, contactId: Long, localAlias: String Set a local display alias for a contact L1711
apiSetConnectionAlias rh: Long?, connId: Long, localAlias: String Set a local display alias for a pending connection L1725
apiSetContactPrefs rh: Long?, contactId: Long, prefs: ChatPreferences Update feature preferences for a contact L1704
apiCreateUserAddress rh: Long? Create a long-term public contact address L1746
apiDeleteUserAddress rh: Long? Delete the user's public contact address L1762
apiAddMyAddressShortLink rh: Long? Create a short link for the user's address L1784
apiSetUserAddressSettings rh: Long?, settings: AddressSettings Configure auto-accept for incoming contact requests L1795
apiAcceptContactRequest rh: Long?, incognito: Boolean, contactReqId: Long Accept an incoming contact request L1809
apiRejectContactRequest rh: Long?, contactReqId: Long Reject an incoming contact request L1832
apiSwitchContact rh: Long?, contactId: Long Initiate SMP server switch for a contact L1374
apiAbortSwitchContact rh: Long?, contactId: Long Abort an in-progress server switch L1388
apiSyncContactRatchet rh: Long?, contactId: Long, force: Boolean Force ratchet synchronization with a contact L1402
apiGetContactCode rh: Long?, contactId: Long Get the security verification code for a contact L1416
apiVerifyContact rh: Long?, contactId: Long, connectionCode: String? Verify a contact's security code L1430

2.6 File Operations

Command Parameters Description Line
receiveFiles rhId, user, fileIds, userApprovedRelays, auto Accept and download one or more files (handles relay approval) L1946
receiveFile rhId, user, fileId, userApprovedRelays, auto Accept and download a single file (convenience wrapper) L2062
cancelFile rh: Long?, user: User, fileId: Long Cancel an in-progress file transfer and clean up L2072
apiCancelFile rh: Long?, fileId: Long, ctrl: ChatCtrl? Cancel a file transfer (low-level, returns updated chat item) L2080
uploadStandaloneFile user: UserLike, file: CryptoFile, ctrl: ChatCtrl? Upload a standalone file (used for migration) L1916
downloadStandaloneFile user: UserLike, url: String, file: CryptoFile, ctrl: ChatCtrl? Download a standalone file by URL L1926
standaloneFileInfo url: String, ctrl: ChatCtrl? Retrieve metadata for a standalone file link L1936

2.7 Call Operations

Command Parameters Description Line
apiGetCallInvitations rh: Long? Retrieve pending call invitations L1842
apiSendCallInvitation rh: Long?, contact: Contact, callType: CallType Initiate a call by sending an invitation L1849
apiRejectCall rh: Long?, contact: Contact Reject an incoming call L1854
apiSendCallOffer rh, contact, rtcSession, rtcIceCandidates, media, capabilities Send a WebRTC call offer L1859
apiSendCallAnswer rh: Long?, contact: Contact, rtcSession: String, rtcIceCandidates: String Send a WebRTC call answer L1866
apiSendCallExtraInfo rh: Long?, contact: Contact, rtcIceCandidates: String Send additional ICE candidates during a call L1872
apiEndCall rh: Long?, contact: Contact End an active call L1878
apiCallStatus rh: Long?, contact: Contact, status: WebRTCCallStatus Report call status updates to the core L1883

2.8 Settings & Network

Command Parameters Description Line
apiSetNetworkConfig cfg: NetCfg, showAlertOnError: Boolean, ctrl: ChatCtrl? Apply network configuration (SOCKS proxy, timeouts, etc.) L1313
apiSetNetworkInfo networkInfo: UserNetworkInfo Update network reachability information L1340
apiSetSettings rh: Long?, type: ChatType, id: Long, settings: ChatSettings Update per-chat settings (notifications, favorites) L1333
apiStorageEncryption currentKey: String, newKey: String Change the database encryption passphrase L999
testStorageEncryption key: String, ctrl: ChatCtrl? Verify a database encryption key is correct L1006
testProtoServer rh: Long?, server: String Test connectivity to a protocol server L1211
reconnectServer rh: Long?, server: String Reconnect to a specific server L1326
reconnectAllServers rh: Long? Reconnect to all servers L1331
apiSetChatUIThemes rh: Long?, chatId: ChatId, themes: ThemeModeOverrides? Set per-chat UI theme overrides L1739
apiContactQueueInfo rh: Long?, contactId: Long Get server queue diagnostics for a contact L1360
apiGroupMemberQueueInfo rh: Long?, groupId: Long, groupMemberId: Long Get server queue diagnostics for a group member L1367

2.9 Chat Tags

Command Parameters Description Line
apiCreateChatTag rh: Long?, tag: ChatTagData Create a new chat tag (folder/label) L1052
apiSetChatTags rh: Long?, type: ChatType, id: Long, tagIds: List<Long> Assign tags to a chat L1060
apiDeleteChatTag rh: Long?, tagId: Long Delete a chat tag L1068
apiUpdateChatTag rh: Long?, tagId: Long, tag: ChatTagData Update a chat tag's name or emoji L1070
apiReorderChatTags rh: Long?, tagIds: List<Long> Set the display order of chat tags L1072

2.10 Server Operators

Command Parameters Description Line
getServerOperators rh: Long? Get server operator conditions detail L1219
setServerOperators rh: Long?, operators: List<ServerOperator> Update the list of server operators L1226
getUserServers rh: Long? Get the user's configured servers per operator L1233
setUserServers rh: Long?, userServers: List<UserOperatorServers> Save user's configured servers per operator L1241
validateServers rh: Long?, userServers: List<UserOperatorServers> Validate server configuration for errors L1253
getUsageConditions rh: Long? Get current and accepted usage conditions L1261
setConditionsNotified rh: Long?, conditionsId: Long Mark conditions as shown to user L1268
acceptConditions rh: Long?, conditionsId: Long, operatorIds: List<Long> Accept usage conditions for operators L1275

2.11 Archive

Command Parameters Description Line
apiExportArchive config: ArchiveConfig Export chat database to a ZIP archive L981
apiImportArchive config: ArchiveConfig Import chat database from a ZIP archive L987
apiDeleteStorage (none) Delete all chat database storage L993

ArchiveConfig (SimpleXAPI.kt#L4162):

class ArchiveConfig(
  val archivePath: String,
  val disableCompression: Boolean? = null,
  val parentTempDirectory: String? = null
)

3. Response Types

All command responses are deserialized into the API sealed class (SimpleXAPI.kt#L5975):

sealed class API {
  class Result(val remoteHostId: Long?, val res: CR) : API()
  class Error(val remoteHostId: Long?, val err: ChatError) : API()
}

The CR sealed class (SimpleXAPI.kt#L6114) contains approximately 180 response variants. Key categories:

Category Examples Lines
User ActiveUser, UsersList, UserPrivacy, UserProfileUpdated L6104-L6157
Chat state ChatStarted, ChatRunning, ChatStopped, ApiChats, ApiChat L6106-L6110
Tags ChatTags, TagsUpdated L6112, L6137
Contacts Invitation, SentConfirmation, SentInvitation, ContactConnected, ContactDeleted L6138-L6165
Messages NewChatItems, ChatItemUpdated, ChatItemsDeleted, ChatItemReaction, ForwardPlan L6176-L6184
Groups GroupCreated, SentGroupInvitation, UserAcceptedGroupSent, GroupUpdated, GroupMembers L6186-L6219
Files (receive) RcvFileAccepted, RcvFileStart, RcvFileComplete, RcvFileCancelled, RcvFileError L6221-L6232
Files (send) SndFileStart, SndFileComplete, SndFileCancelled, SndFileCompleteXFTP L6234-L6244
Calls CallInvitation, CallOffer, CallAnswer, CallExtraInfo, CallEnded L6246-L6251
Remote host RemoteHostList, RemoteHostStarted, RemoteHostConnected, RemoteHostStopped L6255-L6262
Remote ctrl RemoteCtrlList, RemoteCtrlFound, RemoteCtrlConnected, RemoteCtrlStopped L6264-L6269
Encryption ContactPQAllowed, ContactPQEnabled L6271-L6272
Misc CmdOk, ArchiveExported, ArchiveImported, AppSettingsR, VersionInfo L6274-L6283
Fallback Response (unknown type + raw JSON), Invalid (unparseable) L6282-L6283

Each CR subclass is annotated with @Serializable @SerialName("jsonTag") for polymorphic JSON deserialization.


4. Event Types

The chat core pushes asynchronous events through the same CR type hierarchy. The startReceiver coroutine (SimpleXAPI.kt#L660) continuously calls chatRecvMsgWait (blocking JNI), then dispatches each message to processReceivedMsg (SimpleXAPI.kt#L2568).

Events handled in processReceivedMsg include:

Event Description
ContactConnected A contact has completed the connection handshake
ContactConnecting A contact connection is in progress
ContactSndReady Contact's sending channel is ready
ContactDeletedByContact A contact deleted their side of the conversation
ReceivedContactRequest An incoming contact request arrived
NewChatItems New messages received
ChatItemUpdated A message was edited
ChatItemsDeleted Messages were deleted
ChatItemReaction A reaction was added/removed
ChatItemsStatusesUpdated Delivery statuses updated
GroupCreated A new group was created
ReceivedGroupInvitation An invitation to join a group
JoinedGroupMember A new member joined
DeletedMember / DeletedMemberUser A member was removed
LeftMember A member left voluntarily
GroupUpdated Group profile changed
MemberRole A member's role changed
MemberBlockedForAll A member was blocked for all
RcvFileStart / RcvFileComplete / RcvFileError File receive progress
SndFileStart / SndFileComplete / SndFileError File send progress
CallInvitation / CallOffer / CallAnswer / CallEnded Call signaling events
ContactPQEnabled Post-quantum encryption status changed
RemoteHostStopped / RemoteCtrlStopped Remote access session ended
SubscriptionStatusEvt Connection subscription status changed

Each event triggers updates to ChatModel (reactive Compose state) and optionally fires platform notifications via ntfManager.


5. Error Types

ChatError (SimpleXAPI.kt#L6974)

sealed class ChatError {
  class ChatErrorChat(val errorType: ChatErrorType)       // Application-level errors
  class ChatErrorAgent(val agentError: AgentErrorType)     // SMP/XFTP agent errors
  class ChatErrorStore(val storeError: StoreError)         // Database store errors
  class ChatErrorDatabase(val databaseError: DatabaseError)// Database engine errors
  class ChatErrorRemoteHost(val remoteHostError: ...)      // Remote host errors
  class ChatErrorRemoteCtrl(val remoteCtrlError: ...)      // Remote controller errors
  class ChatErrorInvalidJSON(val json: String)             // JSON parsing failure
}

ChatErrorType (SimpleXAPI.kt#L7004)

Common application error codes (~70 variants):

Error Meaning
NoActiveUser No user profile is set as active
UserExists Attempted to create a duplicate user
InvalidDisplayName Display name contains invalid characters
ChatNotStarted / ChatNotStopped Chat engine in wrong state
InvalidConnReq / UnsupportedConnReq Bad or incompatible connection link
ContactNotReady / ContactDisabled Contact in unusable state
GroupUserRole Insufficient group permissions
GroupNotJoined User has not joined the group
FileNotFound / FileCancelled / FileAlreadyReceiving File transfer errors
FileNotApproved File from unapproved relay server
HasCurrentCall / NoCurrentCall Call state conflicts
CommandError / InternalError / CEException Generic/internal errors

StoreError (SimpleXAPI.kt#L7168)

Database-level errors: DuplicateName, UserNotFound, GroupNotFound, ChatItemNotFound, LargeMsg, UserContactLinkNotFound, etc.

ArchiveError (SimpleXAPI.kt#L7658)

sealed class ArchiveError {
  class ArchiveErrorImport(val importError: String)
  class ArchiveErrorFile(val file: String, val fileError: String)
}

6. Source Files

File Purpose Path
SimpleXAPI.kt API bridge: all api* functions, CC, CR, ChatError common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt
Core.kt JNI externals, initChatController, chatMigrateInit common/src/commonMain/kotlin/chat/simplex/common/platform/Core.kt
ChatModel.kt Reactive UI state (ChatModel object) common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt
DatabaseUtils.kt DBMigrationResult, MigrationError, DB password helpers common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DatabaseUtils.kt
Files.kt Platform-expect file path declarations common/src/commonMain/kotlin/chat/simplex/common/platform/Files.kt
Files.android.kt Android actual file paths common/src/androidMain/kotlin/chat/simplex/common/platform/Files.android.kt
Files.desktop.kt Desktop actual file paths common/src/desktopMain/kotlin/chat/simplex/common/platform/Files.desktop.kt
Cryptor.kt Platform-expect encryption interface common/src/commonMain/kotlin/chat/simplex/common/platform/Cryptor.kt
Cryptor.android.kt Android: AndroidKeyStore AES-GCM encryption common/src/androidMain/kotlin/chat/simplex/common/platform/Cryptor.android.kt
Cryptor.desktop.kt Desktop: placeholder (no-op) encryption common/src/desktopMain/kotlin/chat/simplex/common/platform/Cryptor.desktop.kt

All paths are relative to apps/multiplatform/.