Get your credentials
In the cabinet, go to Settings > Mobile SDK, click Add Integration, choose iOS and enter your app’s bundle identifier as the App ID. The integration dialog shows:
The channel’s App ID must equal your bundle identifier; the SDK sends it when the chat session starts and a mismatch is refused. These values are identifiers, not secrets, so shipping them in the app is fine.
Install
- Xcode
- Package.swift
- CocoaPods
- In Xcode, choose File > Add Package Dependencies…
- Paste
https://github.com/Anecdote-AI/clarity-ios-sdk. - Set the dependency rule to Up to Next Major Version, from
1.3.0. - Add the ClaritySDK product to your app target.
Initialize
CallClarity.initialize once at launch:
application(_:didFinishLaunchingWithOptions:).
Configuration options
Identify the user
After your user logs in, and before the first open:ClarityUser also takes phone and avatar.
- Calling
identifywith a differentexternalIdis a logout plus login: the previous user’s session is wiped, so conversations never leak between users. - Calling it again with the same
externalIdand new profile fields updates the profile and keeps the conversation. - On logout, call
Clarity.resetSession().
Verify the user (signed identity)
ClarityUser.jwt is not in ClaritySDK 1.3.0. It ships in the next release; this section describes it so you can prepare your backend.externalId alone is a claim the app makes about itself. To have Clarity trust it, your backend signs a short-lived JWT for the user with the channel’s identity secret, and the app passes it as jwt:
- When the token expires, fetch a new one and call
identifyagain with the sameexternalId. The conversation is kept. - A refused token is reported through
onErroras.pageLoadFailedwith code401, and the message names the reason.
Open the chat
Clarity.show(mode:sheetHeightFraction:from:) presents from a view controller you choose.
Badge your Help button
EveryClarityListener method is optional:
Clarity.unreadCount, Clarity.isWidgetVisible and Clarity.currentTicketStatus directly. unreadCount is a flag: 1 while unseen replies exist, else 0.
Delivery while the chat is closed is best effort. When freshness matters, for example when the app returns to the foreground, call Clarity.refresh(). Missed replies and status changes arrive through the same listener.
Attributes and product events
If your workspace marks contact attributes as required, set them right after
Clarity.initialize, before the chat first loads. A session missing a required attribute is refused, and show() reports .pageLoadFailed naming the missing keys. With autoPreload on, the first load starts about 1.5 seconds after launch; alternatively set autoPreload: false and call Clarity.preload() once the attributes are set.Notifications
While the app is running
When a reply arrives with the chat closed, the SDK raisesonNewMessage, sets the unread flag and posts a local notification, but only if your app already has notification permission. The SDK never prompts. Route taps back to the chat from your UNUserNotificationCenterDelegate:
willPresent delegate must also allow them, for example completionHandler([.banner, .sound]).
Push notifications (APNs)
Forward your device token so replies can reach the device while the app is in the background:setDeviceToken also accepts the token as a hex string.
Background push delivery is enabled per organization. Ask your Clarity contact about availability.
Attachments, camera and microphone
Customers can attach images and PDFs. Photo Library and Choose File need no permissions. Take Photo uses the camera inside your app, and iOS terminates an app that opens the camera without a usage description. Add one to enable it:Customization
The chat’s colours, logos, font and texts come from Settings > Widget in the cabinet, the same settings as the web widget. Per-app switches such as voice calling, dictation and the Inbox tab are in the iOS integration’s dialog. In code you control the presentation (presentationMode, sheetHeightFraction), language and autoFocusInput.
API reference
Troubleshooting
Every failure arrives inonError as a ClarityError with a kind:
Nothing appears on show()
Nothing appears on show()
Check
onError. .handshakeRejected means the organization id, integration key or App ID is wrong; the App ID must equal your bundle identifier. .network means the device cannot reach baseUrl. In debug builds, a diagnostic screen names the reason.Replies while the chat is closed do not notify
Replies while the chat is closed do not notify
Local notifications need your app to have asked for notification permission. The SDK never prompts.
Take Photo does nothing
Take Photo does nothing
Add
NSCameraUsageDescription to your Info.plist.Which URL is the SDK loading?
Which URL is the SDK loading?
Clarity.previewWidgetUrl(...) returns it, and onDebugEvent on your listener traces each step: the session handshake, navigation and the chat becoming ready.