Send a Message Programmatically
Drive the chat from the host app: send a message as the user without going through the input field. Useful for guided flows, in-app actions ("ask Kindly about my order"), or composing a message from contextual UI.
Usage
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import no.kindly.chatsdk.chat.KindlySDK
lifecycleScope.launch {
try {
val message = KindlySDK.sendMessage("Hi, I have a question about my order").await()
println("Sent â server id: ${message.id}")
} catch (e: Exception) {
println("Send failed: ${e.message}")
}
}If you don't need the reconciled message back, just call it and ignore the Deferred:
KindlySDK.sendMessage("Hi, I have a question about my order")You can also observe completion without a coroutine via invokeOnCompletion:
KindlySDK.sendMessage("Hi").invokeOnCompletion { error ->
if (error != null) println("Send failed: $error")
}With per-call context
Attach key/value context to this message only â overrides any context previously staged via setNewContext(...):
KindlySDK.sendMessage(
message = "Where is my order?",
newContext = mapOf("orderId" to "12345", "tier" to "premium"),
)Important: do not also display the message yourself
The SDK renders the bubble locally with a temporary id the moment you call sendMessage, then reconciles with the server-assigned id when the POST response returns. If you also add the message to a chat log you maintain, you'll see it twice.
The message also fires through the unified event stream:
import no.kindly.chatsdk.chat.models.KindlyEvent
lifecycleScope.launch {
KindlySDK.events.collect { event ->
if (event.detail is KindlyEvent.Detail.Message) {
val msg = (event.detail as KindlyEvent.Detail.Message).newMessage
println("${msg.sender}: ${msg.text}")
}
}
}Errors
The Deferred completes exceptionally with a KindlySDKError in these cases:
Error | Cause |
|---|---|
KindlySDKError.SDKNotInitialized | KindlySDK.start(...) was never called. |
KindlySDKError.ChatNotConnected | The chat is not currently connected. Observe KindlySDK.state for isConnected == true before calling, or call launchChat(context) first. |
KindlySDKError.InvalidData | The message text is empty or only whitespace. |
KindlySDKError.ApiError / other | Network or server errors are forwarded. |
Behaviour summary
- Trims whitespace; empty input completes exceptionally with KindlySDKError.InvalidData.
- Optimistic local render â bubble appears immediately with a temp id.
- POSTs to /message, reconciles temp id â server id on success.
- Emits KindlyEvent.message for the user's message (consumers of KindlySDK.events see it like any other message).
- Per-call newContext overrides global setNewContext(...) for this single call.
- Works whether or not the chat UI is currently displayed â the message is delivered, and when the user opens the chat next, they see it in place.