NewInstance Documentation
View as Markdown

iOS

Native Swift chat SDK with a SwiftUI chat screen: AI chatbot, live-agent handoff, attachments and typing indicators. iOS 14+, Swift 5.9.

Installlink

Swift PM (note the lowercase package name):

.package(url: "https://github.com/talktothelaw/new-instance-livechat.git", from: "0.5.0")
// target dependency:
.product(name: "LiveAndAiChat", package: "liveandaichat-ios")

CocoaPods: pod 'LiveAndAiChat', '~> 0.5.0'

Quick startlink

Your backend mints a customer token (see Session tokens (REST API)) and hands it to the app:

import LiveAndAiChat

let chat = try LiveAndAiChat.Builder()
    .config(try LiveAndAiChatConfig(customerToken: tokenFromYourBackend))
    .build()

chat.present(from: viewController)

UIKit hosts call present(from:), which presents the screen and wires the built-in document picker. SwiftUI hosts embed ChatScreen(sdk:onClose:onPickFile:) directly. Unlike Android, openChat() presents no UI on iOS: it flips state and starts initialize(); the host presents the screen.

Configurationlink

FieldDefaultNotes
customerTokennoneCustomer token minted by your backend. Selects customer token mode (recommended)
apiKeynoneThe full keyId:secret, sent whole. Selects key mode, trusted internal apps only
baseUrlhttps://service.newinstance.cloudRelease builds reject overrides
gqlPath / ssePath / wsPath/service / /graphql/stream / /graphql/wsTransport paths
transport / initialMessageinherited / noneOverrides
allowRemoteAttachmentUrlsfalseOpt-in: lets attach(_:) download and upload http(s) sources
themedashboard themeChatThemeOverride(...) local theme, ranked below the dashboard theme and above the built-in one. See Theming

The config initialiser throws LiveAndAiChatError with code E_CONFIG for both credentials, neither, or a bare key ID, and ChatUser requires a non-empty customerName. The raw key and token are not readable from the config, and its descriptions redact them.

Auth modeslink

Customer token mode (recommended). LiveAndAiChatConfig(customerToken:). The SDK sends Authorization: Bearer <token> and the server derives the customer from the signed claims, so setUser fields are not sent. When a fresh token is due, call try chat.setUserToken(freshTokenFromYourBackend): it swaps the credential for every later request and reconnects without destroying the SDK. A token for the same customer keeps the conversation; the SDK compares the token's subject, not the token string.

Key mode (trusted internal apps only). This ships your secret inside the IPA, so never use it in an app distributed to the public.

let chat = try LiveAndAiChat.Builder()
    .config(try LiveAndAiChatConfig(apiKey: "sk_live_abc123:YOUR_SECRET_KEY"))
    .build()
chat.setUser(ChatUser(customerName: "Ada", customerId: "usr_123", customerEmail: "ada@example.com"))

The SDK sends the full key in x-api-key. setUserToken(_:) throws E_CONFIG in key mode. See Authentication and identity.

API surfacelink

initialize, openChat, closeChat (now also dismisses the presented chat screen), sendMessage, setUser(_:) (key mode identity), setUserToken(_:) (swap the customer token; throws in key mode), attachFile(data:name:mimeType:previewUri:) (returns the queue-item id), attach(_:previewUri:), removeAttachment (cancels an in-flight upload), clearAttachments, updateDraft(_:), retryMessage, requestHandoff(reason:), sendTypingStart / sendTypingStop, destroy, addDelegate / removeDelegate; LiveAndAiChat.current() returns the most recently built instance. present(from:) now presents over whatever is topmost instead of requiring a modal-free host.

State: @Published orgConfig, connectionState and lifecycle, plus derived flowState, messages, conversation, assignment, agentTyping, unreadCount, widgetOpen, draftText. Delegate callbacks (all optional): didReceiveMessage, didSendMessage, agentTypingDidChange, connectionStateDidChange, didEncounterError, unreadCountDidChange, attachmentDidUpdate, chatDidClose. lifecycle == .failed means call initialize() again.

Errorslink

didEncounterError(_:) is the channel for "why is my chat not working". Nothing on it reaches the chat interface, and it never carries the API key, the identity token, or customer data.

LiveAndAiChatError carries type (.network, .validation, .auth, .system), message, recoverable, and code (the raw GraphQL or transport code). Call sdkCode(usingIdentityToken:) to normalise onto the ChatErrorCode vocabulary shared with every other chat SDK:

func didEncounterError(_ error: LiveAndAiChatError) {
    switch error.sdkCode(usingIdentityToken: true) {
    case ChatErrorCode.invalidIdentityToken: refreshChatToken()
    case ChatErrorCode.invalidPublicKey: reportMisconfiguration()
    default: break
    }
}

Pass usingIdentityToken: true when the SDK is in customer token mode: an auth failure cannot otherwise tell a rejected key from a rejected token. After an auth failure the SDK does not reconnect with the same credential; a later setUserToken(_:) restarts it. The full code list is in Authentication and identity -> Diagnosing problems.

Programmatic attachmentslink

attach(AttachmentRequest(source:name:mimeType:declaredSize:metadata:)) accepts .base64, .dataUri, .filePath (security-scoped picker URLs handled), .bytes, or .remoteUrl (config-gated); AttachmentSource.detect(_:) safely classifies strings. Validation runs before anything is queued: base64 must decode, files must be readable, non-empty and at most 25 MB, MIME must be png/jpeg/webp/gif/pdf, a wrong declaredSize is rejected as corruption, and the extension must agree with the MIME type. Uploads run off the main thread; progress and results stream through the attachment queue and attachmentDidUpdate (statuses queued, uploading, uploaded, failed, cancelled). A message is never sent with an attachment that has not finished uploading, and attachment contents are never logged.

The chat close eventlink

chatDidClose fires exactly once per chat presentation: the in-chat X (closeButton), a dismissal gesture (gesture), closeChat() (programmatic), destroy() (sessionEnded), or the host dismissing the screen (hostNavigation). The event carries reason, initiator (user/host/sdk), timestamp, conversationId, assignmentId, channel, previousState, unreadCount, hasDraft, pendingAttachmentCount and SDK metadata; never message contents, credentials or attachment data.

Platform noteslink

  • No Info.plist usage keys are required: attachments use the system document picker. Add a Photos usage description only if your app saves chat images.
  • UI strings are inline English; there is no localisation override today, and no push support.
  • destroy() makes the instance unusable (a later call trips a precondition); build a new instance to start again.
  • theme and sdkCode(usingIdentityToken:) require 0.3.0. The two exclusive auth modes and setUserToken(_:) require 0.4.0, which also removes ChatUser.customerToken and ChatUser.fromToken.
  • Steps from your connected MCP servers (forms and secure pages) require 0.5.0; see MCP servers.