Skip to content
reception

Search documentation

Loading documentation…

    Log in
    Browse documentation

    App integration

    Native iOS integration

    Connect Reception to a SwiftUI or UIKit app. The setup prompt guides placement, user details and the design round; this page supplies its native code. For JavaScript apps, use React Native.

    View Markdown

    1. Install

    Add https://github.com/reception-sh/reception-ios.git with Up to Next Major Version, product Reception, to your app target. For XcodeGen or Tuist, edit the manifest and regenerate. Requires iOS 17+ and Xcode 26; check an older deployment target with the developer before changing it.

    2. Configure

    Configure once on the main actor in your existing SwiftUI App initializer, or UIKit application(_:didFinishLaunchingWithOptions:). Keep your root view and other startup work:

    Swift
    import Reception
    
    // Reception support chat. Docs for changes: https://reception.sh/llms.txt
    Reception.configure(appId: "app_YOUR_APP_ID")

    3. Open chat

    Copy your app’s existing button style and call Reception.shared.openChat():

    Swift
    import SwiftUI
    import Reception
    
    // Inside your screen; use your own button styling.
    Button("Support") { Reception.shared.openChat() }

    Reception.shared.closeChat() dismisses the sheet. Your app owns the Support entry and its unread badge.

    Appearance and language

    Immediately after configuration, set Reception.shared.appearance.accentColor, onAccentColor, chatBackground, incomingBackground, incomingForeground and fontFamily from matching app assets or theme properties. Leave unmatched options unset. Dynamic color assets follow light/dark mode; update the options when the app’s own theme setting changes.

    Swift
    // Use the app's existing color asset, only if it has one with this name.
    Reception.shared.appearance.accentColor = Color("AccentColor")

    Import SwiftUI for Color. For a fixed or app-selected light/dark mode, set appearance.preferredColorScheme to .light or .dark; nil follows the app. Only with an in-app language picker, set Reception.shared.languageOverride to its language tag at launch and whenever it changes; nil follows iOS. Keep the built-in texts until the design round. See Appearance and Language.

    Entry and unread badges

    Read Reception.shared.unreadCount in the SwiftUI view so observation updates the badge; hide it at zero. For example, inside your existing button label:

    Swift
    if Reception.shared.unreadCount > 0 {
        Text("\(Reception.shared.unreadCount)")
    }

    Apply the app’s badge style and the setup prompt’s placement rules. Badge only the tab with the main entry: SwiftUI .badge(Reception.shared.unreadCount) or UIKit tabBarItem.badgeValue (nil at zero). UIKit needs re-arming observation, not a one-time count; follow UIKit integration. More placements: Open & close chat and Unread badges.

    Accounts and user details

    Call these on the main actor after configuration, using values from your app:

    Swift
    // A name without an account: userId is nil.
    Reception.shared.identify(userId: userId, name: name, email: email)
    Reception.shared.setMetadata(metadata) // Complete [String: String] dictionary, at most 20 fields.

    Use nil for unavailable identity fields. Send entered names even in apps without accounts. Update identity and the complete metadata dictionary whenever they change; names/emails belong in identify, never metadata.

    When an actual signed-in session ends (including an expired restored session or account switch), call Reception.shared.logout() before the next identity. Never log out a guest at startup. For deletion, try await Reception.shared.deleteData() before discarding the session; catch ReceptionError, keep the session and offer retry on failure. Both clear identity, metadata and push token; supply them again for the next session.

    For verified identity, use Reception.shared.identify(token: token) with your server’s signed token. Handle .identityRejected(let error) in Reception.shared.onEvent through the app’s token-refresh flow. Follow Users & accounts for server setup, refresh, account switching and deletion limits.

    Push

    Wire push even if permission has not been granted, preserving the app’s existing consent flow. Never request permission here. Import UIKit and UserNotifications, then merge these methods into the app’s delegates:

    Swift
    // In the app delegate (SwiftUI: reuse or add @UIApplicationDelegateAdaptor):
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken token: Data) {
        Reception.shared.setPushToken(token)
    }
    
    // In the existing UNUserNotificationCenterDelegate:
    nonisolated func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions {
        if let options = await Reception.shared.notificationPresentationOptions(userInfo: notification.request.content.userInfo) {
            return options
        }
        return [.banner, .sound] // Keep the app's existing policy for its own notifications.
    }
    
    nonisolated func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
        if await Reception.shared.handlePushNotification(response) { return }
        // Keep the app's existing tap handling for its own notifications here.
    }

    Merge these into existing callbacks and keep other notification services working. With Firebase Messaging or OneSignal, pass the raw APNs token Data, never an FCM token or OneSignal ID. Add the Push Notifications capability when signing allows. If the app sets its icon badge itself, set Reception.shared.updatesAppBadge = false at launch.

    Call await Reception.shared.registerForPushIfAuthorized() at launch, on foreground, after your existing permission flow succeeds, and after logout or successful deletion. It registers only when already authorized and never prompts. If there is no notification delegate, assign UNUserNotificationCenter.current().delegate = self in the app delegate’s launch callback. Keep the delegate alive and preserve other provider callbacks. The foreground helper handles receipt itself; do not also forward the same receipt with handlePushNotification. Configure credentials in Push notifications, then verify actual delivery on a device.

    Paywalls

    Use the matching Swift helper in Paywall cards, started after Reception and your purchase vendor. The app owns its purchase screen; present it above chat so dismissal returns to the conversation.

    Embedded chat

    Place ReceptionChatView() in your screen after configuration. Your screen owns dismissal; do not also call openChat(). See Embedded chat for layout and lifecycle details.

    Events and diagnostics

    Assign Reception.shared.onEvent for chat, message, image, review, paywall, deletion and identity-rejection events. Set Reception.logLevel to .debug while diagnosing an integration. See the SDK reference for the complete API.

    Build and simulator checks

    Build your app’s scheme in Debug for an installed iOS simulator with normal signing. Follow the setup prompt to run -ReceptionSetupCheck, then -ReceptionPreview welcome and -ReceptionPreview conversation. The previews use local example data and send nothing.