PolyMessaging) and live two-way voice calls (PolyVoice).
The iOS SDK wraps the Messaging API. All WebSocket events, streaming, and handoff behavior documented in the API reference apply.
Source on GitHub
polyai/ios-sdk: Swift package, CocoaPods, and example apps.
How it works
The SDK handles authentication, session management, WebSocket connections, and reconnection logic. Your app sends and receives messages through the SDK and renders them however you choose. The SDK ships as two products:PolyMessagingis chat-only and source-only, with no third-party dependencies.PolyVoiceis a separate product that adds voice calling and the WebRTC dependency. Chat-only apps never link the WebRTC binary. It reuses the messagingConfigurationand the sameCallState/PolyErrortypes. See Voice calling (iOS) for the full guide.
1
Install the SDK
Add the SDK to your project via Swift Package Manager or CocoaPods.
2
Configure authentication
Add your connector token (from Agent Studio) and register your app’s bundle identifier in Agent Studio. The backend rejects connections from unregistered bundle identifiers.
3
Initialize and start a session
Call
PolyMessaging.initialize(...) once at launch, then PolyMessaging.chat() to get a ChatSession. The SDK handles access token exchange and WebSocket connection automatically.4
Build your UI
Observe the
ChatSession and send user messages through it. Render the conversation in your own UI components.Requirements
PolyMessaging (chat) also supports macOS; PolyVoice is iOS-only.
Installation
The SDK is pre-1.0, so a minor version bump is allowed to include breaking changes. Always pin to the next minor version. Don’t use Xcode’s default “Up to Next Major” rule.- Xcode
- Swift Package Manager
- CocoaPods
In Xcode, go to File > Add Package Dependencies and enter the repository URL:Set the Dependency Rule to Up to Next Minor Version from
0.11.0, then tick the PolyMessaging library for your app target. If you’re using voice calling, also tick PolyVoice. It’s a separate product and isn’t added automatically.pod 'PolyMessaging' install pulls nothing extra. With SPM, adding the repo resolves the WebRTC package for the whole dependency graph, so a chat-only target downloads the xcframework but does not link it.
Authentication setup
The iOS SDK authenticates using a connector token and your app’s bundle identifier.1
Generate a connector token
In Agent Studio, go to Connector Settings and generate a connector token for your agent.
2
Register your bundle identifier
When generating the token, set the host identifier to your app’s bundle identifier (e.g.
com.yourcompany.app). This must match the CFBundleIdentifier in your app’s Info.plist. The SDK sends it automatically as the X-Host header, and the backend rejects connections from apps with a mismatched bundle identifier.Initialize once
CallPolyMessaging.initialize(...) once at app launch: in SwiftUI’s @main App init, or UIKit’s AppDelegate.application(_:didFinishLaunchingWithOptions:).
apiKey is the only required field. Every other field has a working default:
The full configuration reference on GitHub covers environments, error handling and connection states.
Chat session lifecycle
PolyMessaging.chat() returns a @MainActor ChatSession, an ObservableObject. It assembles streaming, tracks delivery, manages typing and surfaces handoff; your UI reads its state and calls its methods.
- Keep one
ChatSessionper chat screen. Each new session is a fresh REST handshake. - In SwiftUI, hold it with
@StateObject. - In UIKit, hold it in a stored property and observe its
@Publishedproperties with Combine. - Call
await session.client.shutdown()when you permanently tear down the chat surface. It is idempotent and cancels heartbeat, reconnect, and retry tasks.
Key features
Session persistence
Conversations survive an app relaunch.PolyMessaging.chat()resumes a valid stored session, or starts a fresh one. Sessions normally remain resumable for approximately ten minutes (the backend’s WebSocket idle timeout); after that,chat()starts a new conversation.PolyMessaging.start()always starts a new session. Use it for an explicit “New chat” entry point.PolyMessaging.hasResumableSession()tells the app whether a resumable session exists, so you can offer the choice before showing the chat.
Streaming responses
Streaming is enabled by default.ChatSession assembles the chunks automatically and updates messages, so the existing agent message grows token by token and then settles into the final message. You never handle chunks directly.
For complete-message bubbles, set Configuration.streamingEnabled to false:
Handoff to live agents
The full handoff flow is supported. When the PolyAI agent triggers a handoff, the SDK delivers the same handoff events (HANDOFF_ACCEPTED, HANDOFF_QUEUE_STATUS, LIVE_AGENT_JOINED, etc.) so your app can show queue status and live agent messages.
Response suggestions
Agent messages can include quick-reply suggestions inAgentMessage.suggestions ([ResponseSuggestion]). Render these as tappable buttons under the latest agent message. When the user taps one, call session.clearSuggestions(for: message.id), then send suggestion.messageText.
Rich content
AnAgentMessage can carry:
- Image attachments:
attachmentswithcontentType == .image - URL / link-card attachments:
attachmentswithcontentType == .url callActions: telephone buttons (ChatCallActionwithtitleandcontactNumber)
contentType == .unknown; it exists for forward compatibility.
Voice calling
PolyVoice places live, two-way WebRTC voice calls to the same agent that powers your chat. Calls are user-initiated: the user taps to call your agent.
Set both credentials once in PolyMessaging.initialize(...), then create calls with no arguments:
Configuration.webrtcToken is the normal place to configure the web calling token. iOS also supports VoiceOptions.webrtcToken as an optional per-call override; if both are supplied, the VoiceOptions value wins.
Calls run over PolyAI’s webrtc-bridge. The old webrtc-gateway path has been removed and no longer works.
Your app needs the microphone permission (NSMicrophoneUsageDescription; a call without it crashes) and the audio background mode so calls survive backgrounding. The SDK handles accessory-aware audio routing, automatic reconnection on transient network drops, and interruptions like incoming phone calls. Optional CallKit support runs the call as a system call; it requires specific delegate wiring, covered on the voice page.
Voice calling (iOS)
The full voice guide: installation, credentials, quick start, CallKit, audio routing, resilience, and troubleshooting.
Platform values
The platform identifier is sent automatically when the session is created, alongside adevice_type (mobile / tablet). It identifies the device, not the channel. For the channel a conversation arrives on, see Multichannel below.
Limitations
Example apps
The ios-sdk repository ships runnable example apps in both SwiftUI and UIKit: a chat ladder underExamples/*/Chat and voice demos under Examples/*/Voice.
Multichannel
The iOS SDK connects to the same agent project as your voice and webchat channels. Agent behavior, knowledge, and flows are shared; only channel-specific settings (greetings, formatting) differ. See multichannel agents for how to tailor behavior per channel. Two values tell your agent where a conversation came from:conv.channel_typeidentifies the channel. Its possible values arewebchat.polyai,chat.polyai,sms.twilio,sms.polyai,rcs.polyai,whatsapp.polyai, andsip.polyai. It is never"ios"or"android".platformidentifies the device: the SDK sendsplatform: "ios"(alongsidedevice_type) when the session is created. Use this to tailor behavior for native app users.
Related pages
Voice calling (iOS)
WebRTC voice calls with PolyVoice: setup, CallKit, audio routing, and troubleshooting
Messaging API reference
Full WebSocket protocol, events, streaming, and handoff
Sessions and authentication
Access tokens, session creation, and platform values
Multichannel agents
Build agents that work across voice, webchat, and mobile

